ENTRYPOINT 入口点
ENTRYPOINT
的格式和 RUN
指令格式一样,分为 exec
格式和 shell
格式。需要通过 docker run
的参数 --entrypoint
1 | <ENTRYPOINT> "<CMD>" |
有cmd为什么要entrypoint
1 | FROM ubuntu:18.04 |
在使用参数时,参数会直接替换掉默认的指令,这里的 -i
替换了原来的 CMD
,而不是添加在原来的 curl -s http://myip.ipip.net
后面。而 -i
根本不是命令,所以自然找不到,使用entrypoint可以因为当存在 ENTRYPOINT
后,CMD
的内容将会作为参数传给 ENTRYPOINT
,而这里 -i
就是新的 CMD
,因此会作为参数传给 curl
2.可以写一个脚本
ENV 设置环境变量
1 | ENV VERSION=1.0 DEBUG=on \ |
这个例子中演示了如何换行,以及对含有空格的值用双引号括起来的办法,这和 Shell 下的行为是一致的。
ARG 构建参数
构建参数和 ENV
的效果一样,都是设置环境变量。所不同的是,ARG
所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。但是不要因此就使用 ARG
保存密码之类的信息,因为 docker history
还是可以看到所有值的
VOLUME 定义匿名卷
数据库文件应该保存于卷(volume)中,在 Dockerfile
中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。
1 | VOLUME /data |
EXPOSE 暴露端口
EXPOSE
指令是声明容器运行时提供服务的端口,这只是一个声明,在容器运行时并不会因为这个声明应用就会开启这个端口的服务以方便配置映射
另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P
时,会自动随机映射 EXPOSE
的端口
WORKDIR 指定工作目录
使用 WORKDIR
指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR
会帮你建立目录
1 | RUN cd /app |
每一个run都是不同的容器,改变文件路径要使用workdir
USER 指定当前用户
USER
指令和 WORKDIR
相似,都是改变环境状态并影响以后的层。WORKDIR
是改变工作目录,USER
则是改变之后层的执行 RUN
, CMD
以及 ENTRYPOINT
这类命令的身份注意,USER
只是帮助你切换到指定用户而已,这个用户必须是事先建立好的,否则无法切换。
HEALTHCHECK 健康检查
HEALTHCHECK
指令是告诉 Docker 应该如何进行判断容器的状态是否正常,这是 Docker 1.12 引入的新指令。
ONBUILD 为他人作嫁衣裳
ONBUILD
是一个特殊的指令,它后面跟的是其它指令,比如 RUN
, COPY
等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行
LABEL 为镜像添加元数据
LABEL
指令用来给镜像以键值对的形式添加一些元数据(metadata 我们还可以用一些标签来申明镜像的作者、文档地址等
容器
启动方式1.删了重新构建 2.重新启动
所需要的命令主要为 docker run
1 | $ docker run ubuntu:18.04 /bin/echo 'Hello world' |
1 | $ docker run -t -i ubuntu:18.04 /bin/bash |
启动一个bash终端,-t
选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上, -i
则让容器的标准输入保持打开。
docker run 后台启动步骤
检查本地是否存在指定的镜像,不存在就从 registry 下载
利用镜像创建并启动一个容器
分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
从地址池配置一个 ip 地址给容器
执行用户指定的应用程序
执行完毕后容器被终止
可以利用 docker container start
命令,直接将一个已经终止(exited
)的容器启动运行
守护态运行
更多的时候,需要让 Docker 在后台运行而不是直接把执行命令的结果输出在当前宿主机下。此时,可以通过添加 -d
参数来实现
1 | $ docker run -d ubuntu:18.04 /bin/sh -c "while true; do echo hello world; sleep 1; done" |
此时容器会在后台运行并不会把输出的结果 (STDOUT) 打印到宿主机上面(输出结果可以用 docker logs
查看)。
使用 -d
参数启动后会返回一个唯一的 id,也可以通过 docker container ls
命令来查看容器信息。
1 | $ docker container ls |
要获取容器的输出信息,可以通过 docker container logs
命令
1 | $ docker container logs [container ID or NAMES] |
终止
docker container stop
来终止一个运行中的容器
可以通过 docker container start
命令来重新启动。
此外,docker container restart
命令会将一个运行态的容器终止,然后再重新启动它。
进入容器
某些时候需要进入容器进行操作,包括使用 docker attach
命令或 docker exec
命令,推荐大家使用 docker exec
命令,原因会在下面说明。
docker attach 不需要参数直接跟id就行但是在bash界面的时候exit会直接导致整个容器关闭,
docker exec 后面可以多个参数 如-i,-t,且exit时不会关闭容器
导出和导入
如果要导出本地某个容器,可以使用 docker export
命令
可以使用 docker import
从容器快照文件中再导入为镜像,例如
此外,也可以通过指定 URL 或者某个目录来导入,例如
1 | $ docker import http://example.com/exampleimage.tgz example/imagerepo |
用户既可以使用 *docker load*
来导入镜像存储文件到本地镜像库,也可以使用 *docker import*
来导入一个容器快照到本地镜像库。这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入时可以重新指定标签等元数据信息。
删除
可以使用 docker container rm
来删除一个处于终止状态的容器。例如
1 | docker container prune |
可以清理所有处于终止的容器
仓库
拉取镜像
你可以通过 docker search
命令来查找官方仓库中的镜像,并利用 docker pull
命令来将它下载到本地。
其中包括镜像名字、描述、收藏数(表示该镜像的受关注程度)、是否官方创建(OFFICIAL
)、是否自动构建 (AUTOMATED
)
数据卷
1 | $ docker volume create my-vol |
查看所有的 数据卷
1 | $ docker volume ls |
在主机里使用以下命令可以查看指定 数据卷
的信息
1 | $ docker volume inspect my-vol |
启动一个挂载数据卷的容器
在用 docker run
命令的时候,使用 --mount
标记来将 数据卷
挂载到容器里。在一次 docker run
中可以挂载多个 数据卷
。
1 | $ docker run -d -P \ |
source=my-vol
:source
参数指定了数据卷的名称。在这个例子中,数据卷的名称是 my-vol
。如果这个数据卷在执行docker run
命令时不存在,Docker 会自动创建。
target=/usr/share/nginx/html
:target
参数定义了在Docker容器中的挂载点路径。在这个例子中,挂载点路径是 /usr/share/nginx/html
,这通常是nginx服务器托管静态文件的目录。
-d
:这是docker run
命令中的选项,全称是--detach
,用于将Docker容器在后台运行,并打印出容器ID。换句话说,使用-d
选项启动的容器将 “脱离” 控制台,以守护进程的方式在后台运行。-p
:这是docker run
命令中的选项,全称是--publish
,用于绑定容器的网络端口到主机的网络端口。格式如-p <host-port>:<container-port>
,例如-p 8080:80
表示将容器的 80 端口映射到主机的 8080 端口。 这样,你就可以通过访问主机的 8080 端口从外部访问容器的服务。
删除数据卷
1 | $ docker volume rm my-vol |
挂载主机目录
使用 --mount
标记可以指定挂载一个本地主机的目录到容器中,本地和容器里面的目录是共用
1 | $ docker run -d -P \ |
这个功能在进行测试的时候十分方便,比如用户可以放置一些程序到本地目录中,来查看容器是否正常工作。本地目录的路径必须是绝对路径
1 | $ docker run -d -P \ |
增加只读权限
--mount
标记也可以从主机挂载单个文件到容器中
1 | $ docker run --rm -it \ |
rm是退出后自己删除
使用网络
外部访问容器
容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P
或 -p
参数来指定端口映射。
当使用 -P
标记时,Docker 会随机映射一个端口到内部容器开放的网络端口
1 | $ docker run -d -P nginx:alpine |
本地主机的 32768 被映射到了容器的 80 端口。此时访问本机的 32768 端口即可访问容器内 NGINX 默认页面
通过docker logs去查看访问记录
映射所有接口地址
不加-p的话,只能开发端口,但是没有映射
1 | $ docker run -d -p 80:80 nginx:alpine |
映射到指定地址的指定端口
1 | $ docker run -d -p 127.0.0.1:80:80 nginx:alpine |
映射到指定地址的任意端口
1 | $ docker run -d -p 127.0.0.1::80 nginx:alpine |
查看映射端口配置
使用 docker port
来查看当前映射的端口配置,也可以查看到绑定的地址
1 | $ docker port fa 80 |
容器互联
下面先创建一个新的 Docker 网络
1 | $ docker network create -d bridge my-net |
-d
参数指定 Docker 网络类型,有 bridge
overlay
。其中 overlay
网络类型用于 Swarm mode,在本小节中你可以忽略它
如果你只是在单个主机上运行Docker容器,使用bridge
网络即可;如果你在设置Docker Swarm集群,或者需要在多个主机上运行的容器之间进行网络通信,那么你应该使用overlay
网络。
连接容器
运行一个容器并连接到新建的 my-net
网络
1 | $ docker run -it --rm --name busybox1 --network my-net busybox sh |
打开新的终端,再运行一个容器并加入到 my-net
网络
1 | $ docker run -it --rm --name busybox2 --network my-net busybox sh |
能够相互ping通就行
Docker Compose
如果你有多个容器之间需要互相连接,推荐使用 Docker Compose
配置 DNS
如何自定义配置容器的主机名和 DNS 呢?秘诀就是 Docker 利用虚拟文件来挂载容器的 3 个相关配置文件。自动挂载
1 | $ mount |
这种机制可以让宿主主机 DNS 信息发生更新后,所有 Docker 容器的 DNS 配置通过 /etc/resolv.conf
文件立刻得到更新。
- /etc/resolv.conf : 记录了容器的 DNS 配置信息,DNS服务器的地方。
- /etc/hostname : 记录了容器的主机名。
- /etc/hosts : 记录了容器的 IP 地址和主机名的映射
配置全部容器的 DNS ,也可以在 /etc/docker/daemon.json
文件中增加以下内容来设置
如果在容器启动时没有指定最后两个参数,Docker 会默认用主机上的 /etc/resolv.conf
来配置容器
高级网络配置
Docker 中的 “docker0” 虚拟网桥是 Docker 网络功能的核心组件之一,它负责在 Docker 主机和 Docker 容器之间以及 Docker 容器之间传递网络数据包。
这是 “docker0” 虚拟网桥的主要职责:
- 连接容器网络:每个 Docker 容器都会有一个网卡与 “docker0” 虚拟网桥连接,使得互相之间可以通信。
- 与主机网络交互:”docker0” 虚拟网桥还可以与 Docker 主机的其他网络接口(例如物理网卡)进行交互,使得 Docker 容器可以与 Docker 主机或 Docker 主机所在网络的其他设备通信。
- 分配 IP 地址:当一个新的 Docker 容器启动时,”docker0” 虚拟网桥会为该容器的网卡分配一个 IP 地址。
通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在主机和所有容器之间一个虚拟共享网络
快速配置指南
下面是一个跟 Docker 网络相关的命令列表。其中有些命令选项只有在 Docker 服务启动的时候才能配置,而且不能马上生效
-b BRIDGE
或 --bridge=BRIDGE
指定容器挂载的网桥
1 | dockerd --bridge=my_bridge |
--bip=CIDR
定制 docker0 的掩码
-H SOCKET...
或 --host=SOCKET...
Docker 服务端接收命令的通道:Docker 服务端接收命令的通道,即 Docker API
--icc=true|false
是否支持容器之间进行通信
--ip-forward=true|false
请看下文容器之间的通信
--iptables=true|false
是否允许 Docker 添加 iptables 规则:iptables 规则被用来实现网络隔离、端口映射等功能。例如,当你使用 -p
选项启动一个 Docker 容器并映射端口时,Docker 后台会自动添加 iptables 规则来将主机的端口流量转发到 Docker 容器的端口
--mtu=BYTES
容器网络中的 MTU:MTU(Maximum Transmission Unit,最大传输单元)
下面2个命令选项既可以在启动服务时指定,也可以在启动容器时指定。在 Docker 服务启动的时候指定则会成为默认值,后面执行 docker run
时可以覆盖设置的默认值。
--dns=IP_ADDRESS...
使用指定的DNS服务器
--dns-search=DOMAIN...
指定DNS搜索域,如果你在一个宿主机上输入 ping myhost
,而 DNS 无法直接找到 “myhost” 这个主机名的记录,如果你的搜索域包含 example.com
,那么 DNS 将尝试查询 myhost.example.com
。
1 | docker run --dns-search=example.com --dns-search=another.com -d my_image |
最后这些选项只有在 docker run
执行时使用,因为它是针对容器的特性内容。
-h HOSTNAME
或 --hostname=HOSTNAME
配置容器主机名
1 | docker run -h myhostname my_image |
--link=CONTAINER_NAME:ALIAS
添加到另一个容器的连接
--net=bridge|none|container:NAME_or_ID|host
配置容器的桥接模式
-p SPEC
或 --publish=SPEC
映射容器端口到宿主主机
-P or --publish-all=true|false
映射容器所有端口到宿主主机
容器访问控制
iptables
防火墙来进行管理和实现。iptables
是 Linux 上默认的防火墙软件,在大部分发行版中都自带。
容器访问外部网络
容器要想访问外部网络,需要本地系统的转发支持。在Linux 系统中,检查转发是否打开
转发,容器原本不能够访问外网,但是通过主机转发就可以进行访问
1 | $sysctl net.ipv4.ip_forward |
容器之间访问
容器之间相互访问,需要两方面的支持。
容器的网络拓扑是否已经互联。默认情况下,所有容器都会被连接到 docker0
网桥上。
本地系统的防火墙软件 – iptables
是否允许通过。