DOCKERFILE 注意事项
准则
-
尽量将 Dockerfile 放在空目录中,如果目录中必须有其他文件,则使用.dockerignore 文件。
-
避免安装不必须的包。
-
每个容器应该只关注一个功能点。
-
最小化镜像的层数。
-
多行参数时应该分类。这样更清晰直白,便于阅读和 review,另外,在每个换行符\前都增加一个空格。
-
对构建缓存要有清楚的认识。
指令注意事项
FROM
Dockerfile reference for the FROM instruction
任何时候,尽量使用官方镜像源作为你镜像的基础镜像。我们建议使用 Debian Image,因为其被很好地管理着,并且作为一个完整的发布包,但体积却保持着最小化(当前不足 150MB)。
1. FROM 必须是除了注释以外的第一行;
2. 可以有多个 FROM 语句,来创建多个 image;
3.
LABEL
Dockerfile reference for the LABEL instruction
RUN
Dockerfile reference for the RUN instruction
RUN 语句有两种格式:
1. RUN
apt-get
尽量避免使用 RUN apt-get upgrade 或者 dist-upgrade,因为基础镜像的很多核心包不会再未授权的容器中升级。
要结合 RUN apt-get update 和 apt-get install 在同一个 RUN 语句下一起使用。如:
RUN apt-get update && apt-get install -y \
package-bar \
package-baz \
package-foo
如果将 update 和 install 分开使用,执行多个 Dockerfile 时,会引起缓存问题,导致后面执行的 install 语句会失败。
另外,执行完 apt-get 语句后,最后最好加上删除安装包的语句,以减小镜像的体积。如:
RUN apt-get update && apt-get install -y \
aufs-tools \
automake \
build-essential \
&& rm -rf /var/lib/apt/lists/*
注意:官方的 Debian 和 Ubuntu 镜像会自动执行“RUN apt-get clean”,所以不需要明确地删除指令。
管道使用
很多 RUN 命令都需要使用到管道,如:
RUN wget -O - https://some.site | wc -l > /number
Docker 使用/bin/sh -c 解释器来执行这些命令,该解释器只评估管道最后一个操作的返回值来判断整个命令是否成功。在上面的例子中,只要 wc -l 命令成功了,即使 wget 命令失败了,也会创建一个新镜像。为了避免上述情况,可以在语句首部加上 set -o pipefail &&。比如:
RUN set -o pipefail && wget -O - https://some.site | wc -l > /number
注意:并非所有的 shell 都支持-o pipefail 选项,比如说基于 Debian 的镜像下的模式 shell:dash shell。这种情况下,我们可以使用 exec 格式的 RUN 命令来显示地选择 shell 来支持 pipefail 选项。如:
RUN ["/bin/bash", "-c", "set -o pipefail && wget -O - https://some.site | wc -l > /number"]
CMD
Dockerfile reference for the CMD instruction
CMD 语句与 RUN 不同,RUN 是在 build 镜像的时候运行,而 CMD 语句是在 build 结束后运行。一个 Dockerfile 钟可以有多个 RUN 语句,虽然也可以有多个 CMD 语句,但是却只有最后一条 CMD 语句会执行。CMD 语句格式为:
CMD [“executable”, “param1”, “param2”…]
EXPOSE
Dockerfile reference for the EXPOSE instruction
EXPOSE 指令指明容器会监听链接的端口。因此,最好使用常用的、传统的应用端口。比如,Apache web 服务器使用 EXPOSE 80 等。
为了给外部链接使用,你需要使用 docker run 命令来制定容器端口和 host 端口的映射。
ENV
Dockerfile reference for the ENV instruction
用于设置环境变量,设置后,后面的 RUM 指令就可以使用之前的环境变量了。同时,还可以通过 docker run –env key=value,在容器启动时设置环境变量。如:
ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && …
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
ADD 和 COPY
Dockerfile reference for the ADD instruction
Dockerfile reference for the COPY instruction
虽然 ADD 和 COPY 功能相似,但一般来讲,更建议使用 COPY。因为 COPY 比 ADD 更透明,COPY 只支持从本地文件到容器的拷贝,但是 ADD 还有一些其他不明显的特性(比如本地 tar 包解压缩和远程 URL 支持)。因此,ADD 的最优用处是本地 tar 包自动解压缩到镜像中。如:ADD rootfs.tar.xz /。
如果有多个 Dockerfile 步骤用于处理不同的文件,建议分开 COPY 它们,而不是一次性拷贝。这可以保证每个步骤的 build 缓存只在对应的文件改变时才无效。比如:
COPY requirements.txt /tmp/
RUN pip install --requirement /tmp/requirements.txt
COPY . /tmp/
镜像的大小很重要,因此不鼓励使用 ADD 从远端 URL 获取包;可以使用 curl 或者 wget 来代替。这种方式你可以删除不再需要的文件,如解压缩后的 tar 包,从而不需要再添加额外的 layer 到镜像中。比如,你应该避免这样使用:
ADD http://example.com/big.tar.xz /usr/src/things/
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
RUN make -C /usr/src/things all
而应该如此:
RUN mkdir -p /usr/src/things \
&& curl -SL http://example.com/big.tar.xz \
| tar -xJC /usr/src/things \
&& make -C /usr/src/things all
对于不需要使用 ADD 命令 tar 包自动解压缩功能的文件和目录,你应该总是使用 COPY。
ENTRYPOINT
Dockerfile reference for the ENTRYPOINT instruction
使用 ENTRYPOINT 来设置镜像的主命令,就像这个镜像运行时就是这条命令一样(然后再使用 CMD 作为默认的 flag)。
我们使用 s3cmd 命令作为镜像的主命令。
ENTRYPOINT ["s3cmd"]
CMD ["--help"]
VOLUME
Dockerfile reference for the VOLUME instruction
VOLUME 指令一般用于数据库的存储区域,配置存储,或者 docker 容器创建的文件和目录。
USER
Dockerfile reference for the USER instruction
如果服务可以在不需要特权的情况下运行,那么就应该使用 USER 来切换用户至非 root 用户。可以用 RUN 命令创建用户组和用户如:
RUN groupadd -r postgres && useradd -r -g postgres postgres
应该避免安装和使用 sudo,因为它有不可预知的 TTY 和信号转移特性,会产生很多问题。如果的确一定要使用类似 sudo 的功能(如 root 下初始化 daemon,非 root 下运行),可以使用“gosu”。
WORKDIR
Dockerfile reference for the WORKDIR instruction
为了 Dockerfile 内容更加清晰和可靠,最好总是使用绝对路径。同样地,应该使用 WORKDIR,而不是使用类似“cd … && do-something”这样的指令,因为那样会导致难以阅读、查找错误和维护。
ONBUILD
Dockerfile reference for the ONBUILD instruction
其他资源
Dockerfile Best Practices
Dockerfile Reference
https://github.com/docker-library/buildpack-deps/blob/master/jessie/Dockerfile
.dockerignore file
http://dockone.io/article/2034
https://docs.resin.io/deployment/build-optimisation/
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于