Docker高级使用指南
目录
Docker数据管理
用户在使用docker过程中,往往需要查看容器内应用产生的数据,或者需要把容器内的数据进行备份,甚至多个容器之间进行数据的共享,这必然涉及到容器的数据管理操作。
容器的数据管理主要有两种方式:
- 数据卷(Data Volumes)
- 数据卷容器(Data Volume Dontainers)
数据卷
数据卷是一个可供容器使用的特殊目录,它绕过文件系统,可以提供很多有用的特性。
- 数据卷可以在容器间共享使用。
- 对数据卷的修改会马上生效。
- 对数据卷的更新,不会影响镜像。
- 卷会一直存在,直到没有容器使用。
数据卷的使用,类似Linux下对目录或文件进行mount操作。
在容器内创建一个数据卷
在用docker run命令时,使用-v可以在容器内创建一个数据卷。
1 | sudo docker run -d -P --name web -v /webapp training/webapp python app.py |
挂载一个主机目录作为数据卷
使用-v也可以指定挂载一个本地的目录到容器中去作为数据卷。
1 | sudo docker run -d -P --name web-2 -v /src/webapp:/opt/webapp training/webapp python app.py |
docker挂载的数据卷默认权限是读写(rw),用户也可以通过,ro设定只读。
1 | sudo docker run -d -P --name web-3 -v /src/webapp:/opt/webapp:ro training/webapp python app.py |
挂载一个本地主机文件作为数据卷
-v也可以从主句挂载单个文件到容器中作为数据卷。
1 | sudo docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash |
数据卷容器
如果用户需要在容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。数据卷容器其实就是一个普通的容器,专门用它提供数据卷供其他容器挂载。
首先创建一个数据卷容器dbdata,并在其中创建一个数据卷挂在到/dbdata。
1 | sudo docker run -it -v /dbdata --name dbdata ubuntu |
然后,可以在其他容器中使用–volumes-from来挂载dbdata容器中的数据卷。创建db1和db2两个容器,并从dbdata容器挂载数据卷。
1 | sudo docker run -it --volumes-from dbdata --name db1 ubuntu |
现在,容器db1和db2都挂载同一个数据卷到相同的/dbdata目录。三个容器任何一方在该目录写入,其他容器都可以看到。
在dbdata容器中创建一个test文件。
1 | root@33821d0743e1:/# cd dbdata/ |
在db1容器内查看。
可以多次使用–volumes-from参数来从多个容器挂载多个数据卷。还可以从其他已经挂载了容器卷的容器来挂载数据卷。
1 | sudo docker run -d --volumes-from db1 --name db3 ubuntu |
利用数据卷容器迁移数据
可以利用数据卷容器对其中的数据卷进行备份、恢复,以实现数据的迁移。
备份
1 | sudo docker run --volumes-from dbdata -v $(pwd):/backup --name worker ubuntu tar cvf /backup/backup.tar /dbdata |
恢复
首先创建一个带有数据卷的容器dbdata2。
1 | sudo docker run -v /dbdata --name dbdata2 ubuntu /bin/bash |
然后创建另一个新的容器,挂载dbdata2的容器,并使用untar解压备份文件到所挂载的容器卷即可。
1 | sudo docker run --volumes-from dbdata2 -v $(pwd):/backup ubuntu tar xvf /backup/backup.tar |
Docker网络配置
Docker提供了映射容器端口到宿主主机和容器互联机制来为容器提供网络服务。
端口映射实现访问容器
从外部访问容器应用
在启动容器时,如果不指定对应参数,在容器外部是无法通过网络来访问容器内的网络应用和服务的。
当容器中运行一些网络应用,要让外部访问这些应用,可以通过-P或者-p参数来指定端口映射。当使用-P标记时,Docker会随机映射一个端口至容器内部的开放的网络端口。
1 | docker run -d -P training/webapp python app.py |
可以通过docker logs命令来查看应用的信息。
-p则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有ip:hostPort:containerPort | ip::containerPort | hostPort::containerPort。
映射所有接口地址
使用hostPort:containerPort格式将本地的5000端口映射到容器的5000端口。
1 | docker run -d -p 5000:5000 training/webapp python app.py |
此时默认会绑定本地所有接口上的所有地址。多次使用-p标记可以绑定多个端口。
1 | docker run -d -p 5000:5000 -p 3000:80 training/webapp python app.py |
映射到指定地址的任意端口
使用ip::containerPort绑定localhost的任意端口到容器的5000端口,本地主机会自动分配一个端口。
1 | docker run -d -p 127.0.0.1::5000 training/webapp python app.py |
还可以使用udp标记来指定udp端口。
1 | docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py |
查看映射端口配置
1 | docker port CONTAINER [PRIVATE_PORT[/PROTO]] |
容器互联实现容器间通信
容器间的连接(linking)系统是除了端口外另一种可以与容器中应用进行交互的方式。它会在源和接收容器之间创建一个隧道,接收容器可以看到源容器指定的信息。
使用–name标记可以为容器自定义命名。
1 | docker run -d --name web -P training/webapp python app.py |
容器互联
使用--link参数可以让容器之间安全的进行交互。
先创建一个新的数据库容器。
1 | docker run -d --name db training/postgres |
删除之前创建的web容器。
1 | docker rm -f web |
然后创建一个新的web容器,并将它连接到db容器。
1 | docker run -d -P --name web --link db:db training/webapp python app.py |
Docker在两个容器之间创建了一个安全隧道,而且不用映射它们的端口到宿主主机上。在启动db容器的时候没有-p和-P标记,从而避免暴露数据库端口到外部网络上。
Docker通过两种方式为容器公开连接信息。
- 环境变量。
- 更新/etc/hosts文件。
使用env命令查看web容器的环境变量。
1 | docker exec web env |
除了环境变量,Docker还添加host信息到父容器的/etc/hosts的文件。
1 | docker exec web cat /etc/hosts |
这里有两个hosts信息,第一个是db容器的ip和主机名,第二个是web容器,web容器用自己的id作为默认主机名。可以在web容器中用ping命令测试与db容器的连通。
1 | docker exec web ping db |
Dockerfile创建镜像
Dockerfile是一个文本格式的配置文件,用户可以用Dockerfile快速创建自定义的镜像。
环境介绍
- Dockerfile中所用的文件一定是和Dockerfile文件在同一级目录下,可以为Dockerfile文件的父目录的子目录。
- Dockerfile中相对路径默认是Dockerfile所在的目录。
- Dockerfile中每一条指令被视为一层,分层构建,联合挂载。所以,能写到一行的指令,一定要写到一行。
- Dockerfile中指令不区分大小写,但习惯上将它大写,以便和参数区分开来。
指令介绍
FROM
功能为指定基础镜像,必须是第一条指令。
同时意味着接下来所写的指令将作为镜像的第一层开始。
1 | FROM <image> |
MAINTAINER
指定作者
1 | MAINTAINER <name> |
LABEL
为镜像指定标签。
1 | LABEL <key>=<value> <key>=<value> <key>=<value> |
ADD
复制文件到镜像中。
1 | ADD <src> ... <dest> |
1 | ADD test relativeDir/ |
COPY
复制文件到镜像中。
1 | COPY <src> ... <dest> |
EXPOSE
暴露容器运行时的监听端口给外部。
1 | EXPOSE <port>/<tcp/udp> |
ENV
设置环境变量。
1 | ENV <key> <value> |
在Dockerfile中使用环境变量
- $varname
- ${varname}
- ${varname:-default}
- ${varname:+default}
RUN
运行指定命令。
1 | RUN <command> |
CMD
容器启动时要运行的命令。
1 | CMD ["executable", "param1", "param2"] |
示例:
1 | CMD ["sh", "-c", "echo $HOME"] |
ENTRYPOINT
启动时的默认命令。
1 | ENTRYPOINT ["executable", "param1", "param2"] |
如果我们在Dockerfile中同时写了ENTRYPOINT和CMD,并且CMD指令不是一个完整可执行的命令,那么CMD指定的内容将会作为ENTRYPOINT的参数。
1 | FROM ubuntu |
如果我们在Dcokerfile中同时写了ENTRYPOINT和CMD,并且CMD是一个完整的指令,那么他们会相互覆盖,谁在最后谁生效。
1 | FROM ubuntu |
那么容器内将执行ls -al,top -b将不会被执行。
VOLUME
实现挂载功能,可将宿主机目录挂载到容器中。
1 | VOLUME ["/data"] |
1 | VOLUME ["/var/log"] |
USER
设置启动容器的用户,可以是用户名或UID。
1 | USER king |
WORKDIR
设置工作目录,对RUN,CMD,ENTRYPOINT,COPY和ADD生效。如果目录不存在会创建,也可以设置多次。
1 | WORKDIR /path/to/workdir |
1 | WORKDIR /a |
pwd的执行结果是/a/b/c。
WORKDIR也可以解析环境变量。
1 | ENV DIRPATH /path |
pwd的执行结果是/path/$DIRNAME。
ARG
设置变量。ARG命令定义一个变量,在docker build创建镜像的时候,使用**–build-arg=**来指定参数。
1 | ARG <name>[=<default value>] |
可以定义一个或者多个参数.
1 | FROM ubuntu |
还可以给参数一个默认值。
1 | FROM ubuntu |
ONBUILD
1 | ONBUILD [INSTRUCTION] |
这个命令只对当前镜像的子镜像生效。
比如当前镜像为A,在Dockerfile中添加:
1 | ONBUILD RUN ls -al |
这个ls -al命令不会在A镜像构建或启动的时候执行。此时有一个镜像B是基于A镜像构建的,那么这个ls -al命令会在镜像B构建的时候被执行。
STOPSIGNAL
当容器停止时给系统发送什么样的指令,默认是15.
1 | STOPSIGNAL signal |
HEALTHCHECK
1 | HEALTHCHECK [OPTIONS] CMD command |
- 在容器内部运行一个命令来检查容器的健康状况。
- 在基础镜像中取消健康检查命令。
[OPTIONS]支持以下三种选项:
- –interval=DURATION 两次检查默认的时间间隔,默认为30秒。
- –timeout=DURATION 健康检查命令运行超时时长,默认为30秒。
- -reties=N 当连续失败指定次数后,则容器被认为是不健康的,状态日为unhealthy,默认次数是3。
CMD后面的命令的返回值决定了本次健康检查是否成功,具体的返回值如下:
- 0:success。表示容器是健康的。
- 1:unhealthy。表示容器已经不能工作了。
- 2:reserved。保留值。
1 | HEALTHCHECK --interval=5m --timeout=3s \ |
健康检查的命令是:curl -f http://localhost/ || exit 1
两次检查的间隔是5分钟,命令超时时间是3秒。