1. COPY 复制文件
格式:
COPY [--chown=<user>:<group>] <源路径>... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。
<源路径> 可以是多个,甚至可以是通配符,其通配符规则要满足 Go 的filepath.Match 规则。
源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。这个特性对于镜像定制很有用。特别是构建相关文件都在使用 Git 进行管理的时候。
2. ADD 更高级的复制文件
ADD 指令和 COPY 的格式和性质基本一致。但是在 COPY 基础上增加了一些功能。
- 比如 <源路径> 可以是一个 URL。Docker 引擎会试图去下载这个链接的文件放到 <目标路径> 去。下载后的文件权限自动设置为 600。
- 如果 <源路径> 为一个 tar 压缩文件的话,压缩格式为 gzip , bzip2 以及xz 的情况下, ADD 指令将会自动解压缩这个压缩文件到 <目标路径> 去。
但需要注意的是:
ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。
COPY 和 ADD 指令中选择的时候,可以遵循这样的原则,所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD 。
3. CMD 容器启动命令
shell 格式: CMD <命令>
exec 格式: CMD ["可执行文件", "参数1", "参数2"...]
参数列表格式: CMD ["参数1", "参数2"...] 。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。
Docker 不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。CMD 指令就是用于指定默认的容器主进程的启动命令的。
在指令格式上,一般推荐使用 exec 格式,这类格式在解析时会被解析为 JSON数组,因此一定要使用双引号,而不要使用单引号。
如果使用 shell 格式的话,实际的命令会被包装为 sh -c 的参数的形式进行
执行.比如:
CMD echo $HOME
CMD [ "sh", "-c", "echo $HOME" ]
Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用 upstart/systemd 去启动后台服务,容器内没有后台服务的概念.
CMD service nginx start
使用 service nginx start 命令,则是希望 upstart 来以后台守护进程形式启
动 nginx 服务。而刚才说了 CMD service nginx start 会被理解为 CMD [
"sh", "-c", "service nginx start"] ,因此主进程实际上是 sh 。那么当
service nginx start 命令结束后, sh 也就结束了, sh 作为主进程退出
了,自然就会令容器退出。
正确的做法是直接执行 nginx 可执行文件,并且要求以前台形式运行。
CMD ["nginx", "-g", "daemon off;"]
4. ENTRYPOINT 入口点
ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数。ENTRYPOINT 在运行时也可以替代,不过需要通过docker run 的参数 --entrypoint 来指定。
当指定了 ENTRYPOINT 后, CMD 的含义就发生了改变,不再是直接的运行其命
令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令.
<ENTRYPOINT> "<CMD>"
这个镜像在运行时,无法接受任何参数。
FROM ubuntu:18.04
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
CMD [ "curl", "-s", "https://ip.cn" ]
使用ENTRYPOINT就可以在运行镜像时,docker run myip -i 执行成功。这里 -i 是新的 CMD ,因此会作为参数传给curl。
FROM ubuntu:18.04
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl", "-s", "https://ip.cn" ]
5. ENV 设置环境
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>.
6. ARG 构建
格式: ARG <参数名>[=<默认值>]
构建参数和 ENV 的效果一样,都是设置环境变量。所不同的是, ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在的。
Dockerfile 中的 ARG 指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令 docker build 中用 --build-arg <参数名>=<值> 来覆盖。
注意:
在 1.13 之前的版本,要求 --build-arg 中的参数名,必须在 Dockerfile 中用 ARG 定义过.
7. VOLUME 定义匿名卷
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。
8. EXPOSE 声明端口
EXPOSE <端口1> [<端口2>...]
EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务.
在 Dockerfile 中写入这样的声明有两个好处:
一,是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;
二,是在运行时使用随机端口映射时,也就是 docker run -P时,会自动随机映射 EXPOSE 的端口。
9. WORKDIR 指定工作目录
WORKDIR <工作目录路径>
使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在, WORKDIR 会帮你建立目录。
10. USER 指定当前用户
USER <用户名>[:<用户组>]
USER 指令和 WORKDIR 相似,都是改变环境状态并影响以后的层。 WORKDIR是改变工作目录, USER 则是改变之后层的执行 RUN , CMD 以及ENTRYPOINT 这类命令的身份.
# 建立 redis 用户,并使用 gosu 换另一个用户执行命令
RUN groupadd -r redis && useradd -r -g redis redis
# 下载 gosu
RUN wget -O /usr/local/bin/gosu "https://github.creleases/download/1.7/gosu-amd64" \
&& chmod +x /usr/local/bin/gosu \
&& gosu nobody true
# 设置 CMD,并以另外的用户执行
CMD [ "exec", "gosu", "redis", "redis-server" ]
11. HEALTHCHECK 健康检查
HEALTHCHECK [选项] CMD <命令> :设置检查容器健康状况的命令
HEALTHCHECK NONE :如果基础镜像有健康检查指令,使用这行可以屏蔽掉
其健康检查指令
这是Docker 1.12 引入的新指令.
当在一个镜像指定了 HEALTHCHECK 指令后,用其启动容器,初始状态会为starting ,在 HEALTHCHECK 指令检查成功后变为 healthy ,如果连续一定次数失败,则会变为 unhealthy .
--interval=<间隔> :两次健康检查的间隔,默认为 30 秒;
--timeout=<时长> :健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
--retries=<次数> :当连续失败指定次数后,则将容器状态视为unhealthy ,默认 3 次
和 CMD , ENTRYPOINT 一样, HEALTHCHECK 只可以出现一次,如果写了多个,
只有最后一个生效。
命令的返回值决定了该次健康检查的成功与否: 0 :成功; 1 :失败; 2 :保留
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib
/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1
为了帮助排障,健康检查命令的输出(包括 stdout 以及 stderr )都会被存储于健康状态里,可以用 docker inspect 来查看。
$ docker inspect --format '{{json .State.Health}}' web | python -m json.tool
12. ONBUILD 为他人做嫁衣裳
ONBUILD <其它指令>
ONBUILD 是一个特殊的指令,它后面跟的是其它指令,比如 RUN , COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。