📜  编写 Dockerfile 的最佳实践(1)

📅  最后修改于: 2023-12-03 15:41:18.954000             🧑  作者: Mango

编写 Dockerfile 的最佳实践

Dockerfile 是定义 Docker 镜像的一种方式。它由一系列指令组成,每个指令生成一层新的文件系统。了解 Dockerfile 的最佳实践,可以帮助你创建高质量的镜像并为部署提供更好的基础。

在本文中,我们将分享一些 Dockerfile 的最佳实践,包括如何减小镜像大小、优化构建速度和保证镜像的可重复性。

1. 尽量使用官方镜像作为基础镜像

官方镜像是由 Docker 官方制作和维护的镜像,它们是开源的、经过优化的,并包含了许多最佳实践。推荐尽量使用官方镜像作为基础镜像,以确保最佳的兼容性、稳定性和安全性。

具体使用方式如下:

FROM official_image:tag

其中,official_image 是官方镜像的名称,tag 是标签。

2. 尽量不要使用 latest 标签

在 Docker 中,latest 标签表示最新版。在构建镜像时,使用 latest 标签可能会导致以下问题:

  • 可能获取到 显式或隐式fetch的最新版本在多个构建之间不一致
  • 当构建时没有使用显示版本号,该版本会默认指向 “latest” ,这个这个版本会在所有环境中更新,并可能导致下游的不可预见的错误。可能会和你的应用程序中使用的其他组件发生冲突。

针对以上问题,建议在 Dockerfile 中指定确切的版本,而不是使用 latest 标签,如下所示:

FROM official_image:1.2.3
3. 每个镜像只包含应用程序所需的内容

应用程序的镜像尽量小,只包含应用程序所需的内容。保持镜像尽可能小,可以减小部署时的网络传输时间,加快容器的启动时间,节省磁盘存储空间。

有几个常见的方法可以减小镜像大小:

  • 当前目录下只复制必需的文件,而不是整个目录。
  • 使用 .dockerignore 文件排除那些不需要添加到镜像中的文件和目录。
  • 多使用一些像 Alpine 的基础镜像作为基础镜像,它们比标准的 Ubuntu 或 CentOS 镜像更小巧。

具体使用方式如下:

FROM alpine:3.13.5
COPY ./app /app
4. 使用多个 RUN 命令,避免构建缓存问题

在 Dockerfile 中使用多个 RUN 命令,可以避免构建缓存问题。

在 Dockerfile 中,每一个指令都会生成一个新的镜像层。如果 Dockerfile 中的某个指令更改了其中一个文件,那么在构建下一个镜像层时,之前的缓存将无法使用。这会导致构建过程变慢并增加镜像的大小。

通过将多个 RUN 命令合并到一个中,可以避免这个问题,如下所示:

RUN apt-get update && \
    apt-get install -y package-1 \
                       package-2 && \
    apt-get clean
5. 建议使用 WORKDIR 命令设置工作目录

WORKDIR 命令在 Dockerfile 中设置工作目录。在容器启动时,会自动创建该目录,如果目录不存在的话,RUNCMDENTRYPOINT 指令会在 WORKDIR 中执行。

具体使用方式如下:

WORKDIR /path/to/working/directory

建议使用 WORKDIR 命令设置工作目录,这样可以避免在每个命令前都使用绝对路径。

6. 使用 COPY 命令代替 ADD 命令

COPY 命令和 ADD 命令都可以将指定的文件或目录复制到 Docker 镜像中。但是,使用 ADD 命令时,如果被复制的文件是一个 URL 或者是一个 tar 压缩文件,那么 Docker 会尝试自动解压缩该文件。

建议尽量不要使用 ADD 命令,在大多数情况下,COPY 命令都足以完成工作,如下所示:

COPY source destination
7. 使用 ENTRYPOINT 命令定义容器启动命令

ENTRYPOINT 命令用于指定容器的启动命令。它可以是一个可执行文件,也可以是一个脚本文件。

建议在 Dockerfile 中使用 ENTRYPOINT 命令来定义容器的启动命令。在启动容器时,可以将任何命令传递给容器所执行的命令的参数列表,如下所示:

ENTRYPOINT ["executable","param1","param2"]
结论

本文分享了一些 Dockerfile 的最佳实践,包括尽量使用官方镜像、避免使用 latest 标签、每个镜像只包含必需的内容、使用多个 RUN 命令以避免构建缓存问题、使用 WORKDIR 命令设置工作目录、使用 COPY 命令代替 ADD 命令、使用 ENTRYPOINT 命令定义容器启动命令等内容。希望本文对你编写 Dockerfile 有所启发。