dockerfile最佳实践

一般指南和建议

1、使用.dockerignore文件
早多数情况下,最好把dockerfile放在一个空的目录中,然后在该目录中添加所需要的文件,为了提高构建的性能,可以通过添加.dockerignore来排除一些文件
怎么创建一个.dockerignore文件,可以参考该文档.dockerignore
2、避免安装不必要文件包
3、每个容器都应该只实现一个功能
4、最小化层
5、对多行参数进行排序

RUN apt-get update && apt-get install -y \
  bzr \
  cvs \
  git \
  mercurial \
  subversion

6、构建缓存

dockerfile结构

1、from
使用官方库作为基础镜像,建议使用debian镜像,因为他是非常严格控制和保持镜像最小,而且它又是完整的发行版。
2、lable
可以通过添加lable的方式来根据项目组织镜像,记录许可信息,以帮助自动化。设置镜像的元数据信息
LABEL指令拥有为镜像添加一些描述的元数据。LABEL是一系列的键值对,它的格式如下:对于每个label,用LABLE标志开始一行,并添加一个或多个键值对,例如:

# Set one or more individual labels
LABEL com.example.version="0.0.1-beta"
LABEL vendor="ACME Incorporated"
LABEL com.example.release-date="2015-02-12"
LABEL com.example.version.is-production=""

# Set multiple labels on one line
LABEL com.example.version="0.0.1-beta" com.example.release-date="2015-02-12"

# Set multiple labels at once, using line-continuation characters to break long lines
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"

通过docker inspect命令,可以查看镜像中的标签信息。

3、run
为了使得镜像文件更加易读,易于理解和更可维护性,可以在使用反斜杠分隔的多行上拆分或复杂的RUN语句,始终将软件包更新和安装命令结合在同一个语句中。最好将不同命令使用&&结合在同一个命令中

RUN apt-get update && apt-get install -y \
    aufs-tools \
    automake \
    build-essential \
    curl \
    dpkg-sig \
    libcap-dev \
    libsqlite3-dev \
    mercurial \
    reprepro \
    ruby1.9.1 \
    ruby1.9.1-dev \
    s3cmd=1.1.* \
 && rm -rf /var/lib/apt/lists/*

4、cmd
CMD指令应该伴随其他参数被用来运行镜像中的软件容器,CMD大都这样使用 CMD [“executable”, “param1”, “param2”…],cmd即容器在跑起来时执行的命令
5、expose
将容器中的某端口暴露出来。
6、env
为了使新的软件能够更加便利的运行,我们能够使用ENV指令来更新PATH的环境变量,例如定义ENV PATH /usr/local/nginx/bin:$PATH 之后才可以确保CMD [“nginx”]的正常运行
最后ENV还可以设置通用的版本号以防版本波动

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

7、add or copy
尽管ADD和COPY在功能上相似,但一般来说,COPY是优选的。那是因为它比ADD更透明。 COPY仅支持将本地文件基本复制到容器中,而ADD具有一些功能(如仅限本地的tar提取和远程URL支持),这些功能并不是很明显。因此,ADD的最佳用途是将本地tar文件自动提取到图像中,如ADD rootfs.tar.xz /中所示。

如果您有多个使用上下文中不同文件的Dockerfile步骤,请单独复制它们,而不是一次复制它们。这将确保每个步骤的构建缓存仅在特定需要的文件更改时失效(强制重新执行该步骤)。

COPY requirements.txt /tmp/
RUN pip install --requirement /tmp/requirements.txt
COPY . /tmp/

与放置COPY相比,RUN步骤的缓存失效次数更少。 / tmp /之前。

由于图像大小很重要,因此强烈建议不要使用ADD从远程URL中提取包。你应该使用curl或wget代替。这样,您可以删除提取后不再需要的文件,也不必在图像中添加其他图层。例如,你应该避免做以下事情:

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

8、entrypoint
ENTRYPOINT的最佳用途是设置镜像的主命令,允许该镜像像该命令一样运行(然后使用CMD作为默认标志)。
ENTRYPOINT指令也可以与辅助脚本结合使用,使其能够以与上述命令类似的方式运行,即使启动该工具可能需要多个步骤。ENTRYPOINT是个命令入口,可以在容器运行的时候传入参数,
9、volume
VOLUME指令应用于公开由docker容器创建的任何数据库存储区域,配置存储或文件/文件夹。强烈建议您将VOLUME用于镜像的任何可变和/或用户可维修部分。
10、user
您应该避免安装或使用sudo,因为它具有不可预测的TTY和信号转发行为,可能导致比它解决的问题更多的问题。如果你绝对需要类似于sudo的功能(例如,以root身份初始化守护进程但是以非root运行它),你可以使用“gosu”。
11、workdir
指定工作目录,为了清晰和可靠,您应该始终使用WORKDIR的绝对路径。此外,你应该使用WORKDIR而不是像RUN cd那样激增指令…… && do-something,这些指令难以阅读,故障排除和维护。
12、onbuild
在当前Dockerfile构建完成后执行ONBUILD命令。 ONBUILD在从当前图像派生的任何子图像中执行。将ONBUILD命令视为父Dockerfile为子Dockerfile提供的指令。

猜你喜欢

转载自blog.csdn.net/qxxhjy/article/details/81542278