Open qianlei90 opened 7 years ago
Tags: 印象笔记 Docker
docker官方文档Best practices for writing Dockerfiles的笔记。
[toc]
.gitignore
Label
ENV
apt-get install -y
--no-cache=true
针对单条指令的建议。
尽可能的使用官方镜像,推荐使用Debian Image。如果追求镜像的大小,可以考虑alpine或scratch。
在一个Label指令内添加多个标签。如:
LABEL vendor=ACME\ Incorporated \ com.example.is-beta= \ com.example.is-production="" \ com.example.version="0.0.1-beta" \ com.example.release-date="2015-02-12"
为了增加Dockerfile的可读性和可维护性,将复杂的RUN指令分行写,不要全部写在一行。
RUN
apt-get upgrade
dist-upgrade
RUN apt-get update && apt-get install -y package
apt-get install -y package
apt-get clean
/var/lib/apt/lists
带管带的命令,其返回值是最后一条命令的返回值。所以如果管道前的命令出错而管道后的指令正常执行,则docker不会认为这条指令有问题。如果需要所有的管道命令都正常执行,可以增加set -o pipefail,如:
set -o pipefail
RUN set -o pipefail && wget -O - https://some.site | wc -l > /number
部分shell不支持set -o pipefail,所以需要指定shell。如:
RUN ["/bin/bash", "-c", "set -o pipefail && wget -O - https://some.site | wc -l > /number"]
使用exec格式,如CMD ["executable", "param1", "param2"]。 如果用户不清楚镜像的ENTRYPOINT是什么,不要和ENTRYPOINT配合使用,不要使用CMD ["param1", "param2"]。
CMD ["executable", "param1", "param2"]。 如果用户不清楚镜像的ENTRYPOINT是什么,不要和
配合使用,不要使用
如果你的镜像是个服务,如Apache这样的,使用正常的、通用的端口,如80端口。
可以修改PATH环境变量来优先使用自己的可执行文件。 可以当做变量来使用,控制Dockerfile中的其他指令,使Dockerfile更易维护。如:
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
这两个指令类似,但如果只是复制文件到镜像内,仍然推荐使用COPY,因为COPY在功能上更单一,而ADD指令有更多的特性(如远程文件、自动解压等)。 ADD指令使用的最好时机是想镜像内添加压缩包,ADD会自动解压。强烈不建议使用ADD来添加远程文件。如果确实需要远程文件,应该使用RUN wget或RUN curl。
COPY
ADD
RUN wget
RUN curl
ENTRYPOINT指令的主要用途是把容器当做命令来用,此时CMD指令来指定默认参数。可以自己写脚本来当做ENTRYPOINT。
ENTRYPOINT
CMD
强烈建议使用该指令为用户数据创建数据卷,如数据的存储位置、配置文件的存储位置或用户自己创建的文件/目录等。
如果镜像的服务不用授权就能使用,那应该新增用户和组,以新用户来执行,如:
RUN groupadd -r postgres && useradd -r -g postgres postgres
需要注意的是,UID/GID是顺着镜像中已存在的UID/GID创建的,如果对这个有严格要求,应该自己显式定义UID/GID。 不要在镜像内安装或使用sudo,如果需要类似的功能,可以使用gosu。 也不要来来回回的切换用户,这样会增加图层层数。
sudo
gosu
只使用绝对路径。切换工作目录只使用WORKDIR而不是RUN cd ... && do-something。
WORKDIR
RUN cd ... && do-something
在运行docker build命令时,在执行任何指令前,先执行父Dockerfile中定义的ONBUILD指令。 在打标签时应该添加这些信息,如:ruby:1.9-onbuild。 谨慎使用COPY和ADD,因为有可能在子构建中并不存在对应的文件或目录。
docker build
ONBUILD
ruby:1.9-onbuild
两种方式:
debootstrap
$ sudo debootstrap raring raring > /dev/null $ sudo tar -C raring -c . | docker import - raring a29c15f1bf7a $ docker run raring cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=13.04 DISTRIB_CODENAME=raring DISTRIB_DESCRIPTION="Ubuntu 13.04"
FROM scratch ADD hello / CMD ["/hello"]
- 完 - 2017/03/10
深入Dockerfile(二):最佳实践
Tags: 印象笔记 Docker
docker官方文档Best practices for writing Dockerfiles的笔记。
[toc]
一、Dockerfile
1.1 原则与建议
.gitignore
。在大部分情况下,Dockerfile会和构建所需的文件放在同一个目录中,为了提高构建的性能,应该使用.gitignore
来过滤掉不需要的文件和目录。Label
、ENV
等标签,参考1.2。apt-get install -y
安装包的时候。--no-cache=true
来强制重新生成中间镜像。关于缓存的寻找机制,可以参考之前的<Dockerfile语法指南>。1.2 Dockerfile指令的最佳实践
针对单条指令的建议。
1.2.1 FROM
尽可能的使用官方镜像,推荐使用Debian Image。如果追求镜像的大小,可以考虑alpine或scratch。
1.2.2 LABEL
在一个
Label
指令内添加多个标签。如:1.2.3 RUN
为了增加Dockerfile的可读性和可维护性,将复杂的
RUN
指令分行写,不要全部写在一行。apt-get upgrade
或dist-upgrade
,这会更新大量不必要的系统包,增加了镜像大小。如果需要更新包,简单的使用RUN apt-get update && apt-get install -y package
就好。记得,如果package很多的话,分行并按字母表排序。apt-get upgrade
和apt-get install -y package
要在一个RUN
指令内,如果在多个RUN
指令内,docker会使用缓存,具体的参考之前的<Dockerfile语法指南>。apt-get clean
语句。如果是其他镜像,手动执行该指令,或删除/var/lib/apt/lists
下的文件。带管带的命令,其返回值是最后一条命令的返回值。所以如果管道前的命令出错而管道后的指令正常执行,则docker不会认为这条指令有问题。如果需要所有的管道命令都正常执行,可以增加
set -o pipefail
,如:部分shell不支持
set -o pipefail
,所以需要指定shell。如:1.2.4 CMD
使用exec格式,如
CMD ["executable", "param1", "param2"]。 如果用户不清楚镜像的ENTRYPOINT是什么,不要和
ENTRYPOINT配合使用,不要使用
CMD ["param1", "param2"]。1.2.5 EXPOSE
如果你的镜像是个服务,如Apache这样的,使用正常的、通用的端口,如80端口。
1.2.6 ENV
可以修改PATH环境变量来优先使用自己的可执行文件。 可以当做变量来使用,控制Dockerfile中的其他指令,使Dockerfile更易维护。如:
1.2.7 ADD和COPY
这两个指令类似,但如果只是复制文件到镜像内,仍然推荐使用
COPY
,因为COPY
在功能上更单一,而ADD
指令有更多的特性(如远程文件、自动解压等)。ADD
指令使用的最好时机是想镜像内添加压缩包,ADD
会自动解压。强烈不建议使用ADD
来添加远程文件。如果确实需要远程文件,应该使用RUN wget
或RUN curl
。1.2.8 ENTRYPOINT
ENTRYPOINT
指令的主要用途是把容器当做命令来用,此时CMD
指令来指定默认参数。可以自己写脚本来当做ENTRYPOINT。1.2.9 VOLUME
强烈建议使用该指令为用户数据创建数据卷,如数据的存储位置、配置文件的存储位置或用户自己创建的文件/目录等。
1.2.10 USER
如果镜像的服务不用授权就能使用,那应该新增用户和组,以新用户来执行,如:
需要注意的是,UID/GID是顺着镜像中已存在的UID/GID创建的,如果对这个有严格要求,应该自己显式定义UID/GID。 不要在镜像内安装或使用
sudo
,如果需要类似的功能,可以使用gosu
。 也不要来来回回的切换用户,这样会增加图层层数。1.2.11 WORKDIR
只使用绝对路径。切换工作目录只使用
WORKDIR
而不是RUN cd ... && do-something
。1.2.12 ONBUILD
在运行
docker build
命令时,在执行任何指令前,先执行父Dockerfile中定义的ONBUILD
指令。 在打标签时应该添加这些信息,如:ruby:1.9-onbuild
。 谨慎使用COPY
和ADD
,因为有可能在子构建中并不存在对应的文件或目录。二、创建自己的新镜像
两种方式:
debootstrap
类似的工具来生成一个基础的OS,然后导入到docker中:- 完 - 2017/03/10