仓库
仓库(Repository)是集中存放镜像的地方,一个仓库地址一般由注册服务器地址(Registry)和仓库名组成,如 dl.dockerpool.com/buntu 和 daocloud.io/centos 。
登录
Docker 官方维护了一个公共仓库 Docker Hub,在上面成功注册账号后,可以通过执行命令 docker login 输入用户名、密码登录Docker Hub。也可以通过 docker logout 退出登录。
拉取镜像
首先通过 docker search + 关键词(如centos)命令来查找镜像,
再通过 docker pull 命令来将所需的镜像拉取到本地镜像库。
其中,官方库中有一类镜像,其镜像名形如 username/centos ,是由Dkcker Hub的用户进行创建并维护的。
另外,在查找的时候通过 –filter=stars=N 参数可以指定仅显示收藏数量为
N 以上的镜像。
推送镜像
在本地镜像库 通过 docker tag 命令标记本地的镜像,如
$ docker tag ubuntu:18.04 username/ubuntu:18.04
并通过 docker push 命令推送到官方镜像库上
$ docker push username/ubuntu:18.04
自动构建
同时,也可以在Docker Hub上,指定跟踪一个目标网站(支持 GitHub 或BitBucket)上的项目,一旦项目发生新的提交 (commit)或者创建了新的标签(tag),Docker Hub 会自动构建镜像并推送到 Docker Hub 中。
配置自动构建的步骤如下:
- 登陆 Docker Hub ;
- 在账号设置(Account Settings)中关联(Linked Accounts)目标网站;
- 在 Docker Hub 中新建或选择已有的仓库,在 Builds 选项卡中选择Configure Automated Builds ;
- 选取一个目标网站中的项目(需要含 Dockerfile )和分支;指定 Dockerfile 的位置,并保存。
之后在 Docker Hub 的仓库页面的 Timeline 选项卡中查看每次构建的状态。
私有仓库
使用是官方提供的工具 docker-registry 构建私有的镜像仓库
首先获取官方镜像(由于本地不存在,会自动进行下载)
$ docker run -d -p 5000:5000 --restart=always --name registry registry
仓库默认情况下创建于容器的 /var/lib/registry 目录,也可以通过命令 -v 参数修改指定路径(如 /opt/data/registry )
$ docker run -d -p 5000:5000 -v /opt/data/registry:/var/lib/registry registry
之前提到过,可以通过 docker tag 命令来标记一个镜像,格式为
$ docker tag IMAGE[:TAG][REGISTRY_HOST[:REGISTRY_PORT]/]REPOSITORY[:TAG]
如
$ docker tag ubuntu:latest 127.0.0.1:5000/ubuntu:latest
并通过 docker push 上传标记的镜像,上传到仓库的镜像,在本地删除原镜像后可以通过 docker pull 重新获取。
由于 Nexus3.x 全面支持 Docker 的私有镜像,所以可以使用 Nexus3.x 这个软件来管理 Docker。
首先下载并启动 Nexus 容器
$ docker run -d --name nexus3 --restart=always -p 8081:8081 --mount src=nexus-data,target=/nexus-data sonatype/nexus3
启动成功并没有异常退出后,浏览器打开 http://YourIP:8081 访问 Nexus。
第一次启动 Nexus 的默认帐号是 admin ,密码是admin123
nexus 3.17版本后初始密码不是admin123而是一个随机密码
查询密码需要进入 Nexus 容器
#查询容器id
$ docker ps
#进入容器里面
$ docker exec -it 容器id bash
cd 命令进入 /opt/sonatype/nexus3/ 目录,并通过
vi admin.password
查询随机的初始密码
数据卷
数据卷(Volume)的意义,Docker内的文件系统是如何工作的
Union File System(联合文件系统)。
Docker 中的只读层及在顶部的读写层的组合。
当我们开启一个容器,Docker读取只读镜像并添加一个读写层在顶部。如果正在运行的容器修改了现有的文件,该文件将被拷贝出底层的只读层到最顶层的读写层。在读写层中的旧版本文件隐藏于该文件之下,但并没有被不破坏( 它仍然存在于镜像以下)。当Docker的容器被删除,然后重新启动镜像时,将开启一个没有任何更改的新的容器(先前的更改会丢失)。
为了能够保存(持久)数据以及共享容器间的数据,Docker提出了数据卷(Volumes)的概念。数据卷 是一个可供一个或多个容器使用的特殊目录,这个目录能够独立于联合文件系统的形式在宿主机中存在,可以提供很多有用的特性:
- 数据卷 可以在容器之间共享和重用
- 对 数据卷 的修改会立马生效
- 对 数据卷 的更新,不会影响镜像
- 数据卷 默认会一直存在,即使容器被删除(要删除数据卷得先删除挂载的容器)
注意: 数据卷 的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的
被指定为挂载点的目录中的文件会隐藏掉,能显示看的是挂载的 数据卷 。
通过 docker volume create my-vol 命令创建一个数据卷
同样的,可以通过 docker volume ls 命令查看数据卷列表(万能的ls查看)
删除数据卷也是通过 docker volume rm my-vol 命令
由于数据卷类似硬盘分区,用来持久化存储数据,这一点区别于容器,删除容器并不会删除数据卷
若要删除容器同时数据卷,需要用到 docker rm -v
可以使用 docker volume prune 删除冗余的数据卷
如果要查看数据卷信息的话,可以使用 docker volume inspect my-vol命令
$ docker volume inspect my-vol
[
{
"CreatedAt": "2019-08-11T07:54:40Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
"Name": "my-vol",
"Options": {},
"Scope": "local"
}
]
启动一个挂载数据卷的容器
在使用 docker run 命令时,使用 –mount source=my-vol,target=/webapp标记来将 数据卷 挂载到容器里,如
$ docker run -d -P --name web --mount source=my-vol,target=/webapp training/webapp python app.py
或
$ docker run -d --name uu --mount source=my-vol,target=/ubuntu ubuntu:18.04 bash
查看数据卷的具体信息
通过 docker inspect web 查看容器 web 的信息,数据卷 的信息在 Mounts 关键字里
$ docker inspect web
...
"Mounts": [
{
"Type": "volume",
"Name": "my-vol",
"Source": "/var/lib/docker/volumes/my-vol/_data",
"Destination": "/webapp",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
],
挂载主机目录
挂载一个主机目录作为数据卷
同样使用 –mount 标记可以指定挂载一个本地主机的目录到容器中去
$ docker run -d -P --name web \
--mount type=bind,source=/src/webapp,target=/opt/webapp \
training/webapp python app.py
该命令加载主机的 /src/webapp 目录到容器的 /opt/webapp 目录
本地目录的路径必须是绝对路径,以前使用 -v 参数时如果本地目录不存在 Docker 会自动为你创建一个文件夹,现在使用 --mount 参数时如果本地目录不存在,Docker 会报错
Docker 挂载主机目录的默认权限是 读写 ,用户也可以通过增加 readonly 指定为 只读
$ docker run -d -P --name web \
--mount type=bind,source=/src/webapp,target=/opt/webapp,readonly \
training/webapp python app.py
挂载主机目录与挂载直接数据卷的区别在于,source和target都是目录(前者为主机目录,后者为容器目录)
挂载一个本地主机文件作为数据卷
同样使用 –mount 标记也可以从主机挂载单个文件到容器中
$ docker run --rm -it \
--mount type=bind,source=$HOME/.bash_history,target=/root/.bash_history ubuntu:18.04 bash
同样的,source和target都是文件(前者为主机目录,后者为容器目录)
网络功能
Docker 允许通过外部访问容器或容器互联的方式来提供网络服务。
外部访问容器
之前,在挂载数据卷和目录时,用到过一个 -P 参数,它的作用是使Docker 随机映射一个 49000~49900 的端口到内部容器开放的网络端口。这样,容器内的网络应用,通过外部也可以访问。
如
$ docker run -d -P --name web --mount source=my-vol,target=/webapp training/webapp python app.py
或
$ docker run -d -P training/webapp python app.py
可以通过 == docker container ls== 来查看容器的 PORTS 属性(如果没有显示,可以添加 -a 参数)
同样的,可以通过 docker logs 命令来查看应用的信息
$ docker logs -f web
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
并且,-p 则可以指定要映射的端口(在一个指定端口上只可以绑定一个容器)
映射所有接口地址
$ docker run -d -p 5000:5000 training/webapp python app.py
该命令使用 hostPort : containerPort 格式本地的 5000 端口映射到容器的 5000 端口,默认会绑定本地所有接口上的所有地址。
映射到指定地址的指定端口
$ docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py
该命令使用 ip : hostPort : containerPort 格式指定映射使用一个特定地址。
映射到指定地址的任意端口
$ docker run -d -p 127.0.0.1::5000 training/webapp python app.py
该命令使用 ip :: containerPort 绑定 localhost 的任意端口到容器的 5000 端口,本地主机会自动分配一个端口。
$ docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
同样,也可以使用 udp 标记来指定 udp 端口。
查看映射端口配置
使用 docker port 来查看当前映射的端口配置,也可以查看到绑定的地址
先查看Docker的容器列表
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9006c5b7d188 training/webapp "python app.py" 27 seconds ago Up 25 seconds 5000/tcp, 127.0.0.1:5000->5000/udp web3
6c5ab06c16b8 training/webapp "python app.py" 56 seconds ago Up 54 seconds 127.0.0.1:5000->5000/tcp web2
be2517e7668c training/webapp "python app.py" 2 hours ago Up 2 hours 0.0.0.0:32769->5000/tcp web
在查看端口配置
$ docker port web 5000
0.0.0.0:32769
$ docker port web2 5000
127.0.0.1:5000
- 容器有自己的内部网络和 ip 地址(使用 docker inspect 可以获取所有的变量,Docker 还可以有一个可变的网络配置。)
- -p 标记可以多次使用来绑定多个端口
容器互联
- 使用 --link 参数来使容器互联。
- (建议)将容器加入自定义的 Docker 网络来连接多个容器。
新建网络
创建一个新的 Docker 网络,-d 参数指定 Docker 网络类型,有 bridge overlay 两种。
$ docker network create -d bridge my-net
连接容器
运行两个容器,以此连接到新建的 my-net 网络
$ docker run -it --rm --name busybox1 --network my-net busybox sh
$ docker run -it --rm --name busybox2 --network my-net busybox sh
接着进入容器,并在busybox1容器中ping busybox2容器
$ docker exec -it busybox1 sh / # ping busybox2
PING busybox2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.106 ms
......
同样地,在busybox2容器中进行ping操作
$ docker exec -it busybox2 sh / # ping busybox1
PING busybox1 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.096 ms
......
可以看到,两个容器之间是互相ping通的,既建立了互联关系
Docker Compose
如果你有多个容器之间需要互相连接,推荐使用 Docker Compose。
配置DNS
如何自定义配置容器的主机名和 DNS ? Docker 可以 利用虚拟文件来挂载容
器的 3 个相关配置文件。
在容器中使用 mount 命令可以看到挂载信息
$ mount
/dev/disk/by-uuid/1fec...ebdf on /etc/hostname type ext4 ...
/dev/disk/by-uuid/1fec...ebdf on /etc/hosts type ext4 ...
tmpfs on /etc/resolv.conf type tmpfs ...
这种机制可以让宿主主机 DNS 信息发生更新后,所有 Docker 容器的 DNS 配置通过 /etc/resolv.conf 文件立刻得到更新。
配置全部容器的 DNS ,也可以在 /etc/docker/daemon.json 文件中增加以下内容来设置。
(Docker 容器 No such file or directory)
{
"dns" : [
"114.114.114.114",
"8.8.8.8"
]
}
这样每次启动的容器 DNS 自动配置为 114.114.114.114 和 8.8.8.8 。
可以在使用 docker run 命令启动容器时加
入如下参数:
-h HOSTNAME 或者 –hostname=HOSTNAME 设定容器的主机名,该主机名不会再外部显示。
–dns=IP_ADDRESS 添加 DNS 服务器到容器的/etc/resolv.conf 中,让容器用这个服务器来解析所有不在 /etc/hosts 中的主机名。
–dns-search=DOMAIN 设定容器的搜索域。
注意:如果在容器启动时没有指定最后两个参数,Docker 会默认用主机上的/etc/resolv.conf 来配置容器。