Docker 学习之旅(二):Dockerfile 命令

本篇是对 Dockerfile 文件的一个介绍,在了解完相关知识后,可以用 Dockerfile 文件创建一个简单的镜像。

参考和推荐

文档链接:https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#general-guidelines-and-recommendations

更详细的 Dockerfile 参考链接:https://docs.docker.com/engine/reference/builder/,同样适用于下文。

  • 容器的生命应该是短暂的
  • 可以使用 .dockerignore 文件来排除文件
  • 避免安装不需要的包
  • 每个容器都应该只有一个关注点
  • 最小化层的数量
  • 整理多行参数
  • Build 缓存

都是一些阅读理解的内容,详细见官方文档。

Dockerfile 指南

文档链接:https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#the-dockerfile-instructions

仅列出各命令简单用法,详细请参照上文列出的官方详细文档。

FROM

你可以在现有镜像的基础上构建自己的镜像。

FROM <image>

Or

FROM <image>:<tag>

Or

FROM <image>@<digest>

LABEL

LABEL 命令用来给镜像添加元数据,可以更好地管理镜像等。

用法:

1
LABEL <key>=<value> <key>=<value> <key>=<value> ...

可在一个命令中使用多个键值对,也可只使用一个。若镜像是以其他镜像 FROM 为基础的,相同的标签将会覆盖原有标签。

RUN

RUN指令将在当前映像之上的新层中执行任何命令,并提交执行结果,这个提交的的执行后的镜像将被 Dockerfile 的其余步骤使用。

RUN 指令有两种形式:

  • RUN <command>(shell 形式,命令在 shell 中运行,对于 Linux 默认为 /bin/sh -c,而对于 Windows 默认为 cmd /S /C)
  • RUN ["executable", "param1", "param2"](执行形式)

APT-GET

这可能是 RUN 命令的最多使用情况,但是你应该避免使用 RUN apt-get upgrade 或是 dist-upgrade,因为许多“必要”的包将不会在无特权的容器内部被升级。如果一个镜像所包含的基础镜像过期,请联系管理员。

记得将 RUN apt-get update 命令与 apt-get install 命令放在同一个 RUN 声明中,例如:

1
2
3
4
RUN apt-get update && apt-get install -y \
package-bar \
package-baz \
package-foo

在一个单独的 RUN 声明中使用 apt-get update 将会导致缓存问题和之后的 apt-get install 命令失败。

使用管道

有一些 RUN 命令使用和 Linux 中同样的管道来将一个命令的输入导入到另一个命令当中,符号同样为 |

CMD

CMD 命令的主要作用是给可执行容器提供默认的参数。

CMD 命令有三种形式:

  • CMD ["executable","param1","param2"](执行形式,最推荐的形式)
  • CMD ["param1","param2"](入口点的默认参数)
  • CMD command param1 param2(shell 形式)

在一个 Dockerfile 文件中,只能有一个 CMD 指令,如果你列出超过一个的 CMD 指令,只有最后一条会起作用。

EXPOSE

EXPOSE 命令用于开放容器的内部端口,支持环境变量(例如,MYSQL_PORT_3306_TCP)。但是EXPOSE 命令并不能使内部端口对宿主可见,你必须使用 -p 命令来开放特定端口或是使用 -P 命令来开放所有的 EXPOSE 的端口。

EXPOSE <port> [<port>...]

ENV

ENV 命令用来更新 PATH 环境变量。

ENV <key> <value>
ENV <key>=<value> ...

这是ENV 命令的两种使用形式,推荐使用第二种形式。

ADD or COPY

ADDCOPY 命令拥有相似的功能,通常而言,COPY 因其更加透明而被推荐。但是 COPY 只能拷贝本地文件而 ADD 拥有更多的特性(比如本地 tar 提取和远程 URL 支持)。

ADD/COPY <src>... <dest>
ADD/COPY ["<src>",... "<dest>"]

省略众多详细介绍,详见文档。

ENTRYPOINT

ENTRYPOINT ["executable", "param1", "param2"](执行形式,推荐)
ENTRYPOINT command param1 param2(shell 形式)

ENTRYPOINT 命令允许你配置容器使其变成可执行容器。

USER

USER 可以使容器改变运行用户,通过在 Dockerfile 文件中使用类似 RUN groupadd -r postgres && useradd -r -g postgres postgres 的命令来创建用户和组。

WORKDIR

WORKDIR /path/to/workdir

WORKDIR 指令可以设置 RUNCMDENTRYPOINTCOPYADD 指令的工作目录。即使后续并不会使用到 WORKDIR 指令,它仍然会被创建。

WORKDIR 指令可在一个 Dockerfile 文件中使用多次。如果给定一个相对路径,那么它会相对于之前的 WORKDIR 指令。例如:

1
2
3
4
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

pwd 的输出将为 /a/b/c

WORKDIR 指令也可解析在之前通过 ENV 指令设置的环境变量。例如:

1
2
3
ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd

pwd 的输出将为 /path/$DIRNAME

ONBUILD

ONBUILD [INSTRUCTION]

ONBUILD 命令在当前 Dockerfile 文件构建完成后执行,也就是该镜像最为其他镜像的父镜像时。它会在子镜像的 Dockerfile 文件中的 FROM 指令后立即被执行。