Dockerfile 是创建容器的蓝图。它们是简单的文本文件,包含了创建容器镜像所需的命令,这些命令通常是您手动执行的。Dockerfile 就是您容器的源代码。
编写 Dockerfile 很容易,但它们可能很快变得复杂。以下是一些有助于编写更好的 Dockerfile 的技巧。
我将分享我多年来学到的 3 个技巧。这些技巧将有助于您编写更好的 Dockerfile。它们将使您的容器更稳定和安全。它们还将使您的容器更小更快。希望您会发现它们有用。
如果您的 Dockerfile 如下所示,可以进行改进:
代码语言:shell复制FROM node:lts-alpine
WORKDIR /app
COPY . .
RUN npm install
CMD ["npm", "run", "start"]
1- 选择正确的基础镜像
基础镜像是容器的起点。它是 Dockerfile 中的第一行。基础镜像是容器的基础,它是用于构建容器的操作系统和软件。
Alpine 是 Docker 容器最流行的基础镜像。它是为容器优化的轻量级 Linux 发行版。它小巧、快速和安全。对于大多数容器来说,它是一个不错的选择。但是… 它不是 Docker 官方支持的镜像,而是由 Alpine Linux 社区维护的。
更好的选择是使用 bullseye 基础镜像。这是 Docker 的官方 Debian 基础镜像。由 Debian 社区维护。对于大多数容器来说,这是一个不错的选择。它小巧、快速,如果选择 slim 变体,也更安全和更轻量级。
代码语言:shell复制FROM node:20.9.0-bullseye-slim
同时,请指定基础镜像的版本。这将确保您的容器始终使用相同版本的基础镜像。这将使您的容器更稳定和安全。lts 不是一个版本,而是一个标签。不建议使用基础镜像的标签,而是使用版本号。
2- 是否需要复制全部内容?
可能不需要,我很确定您在生产 Docker 容器中不需要 .prettierignore 或 .gitignore 等文件。
您可以通过两种方式解决这个问题:
- 为每个文件/文件夹指定一系列
COPY
指令。 - 在 .dockerignore 文件中指定不想要复制的内容列表。
我更喜欢指定我想要复制到镜像中的文件/文件夹列表。尽管如此,我建议您使用 .dockerignore 文件来避免将不必要的文件复制到镜像中,因为这是一个良好的做法。
此外,出于安全原因,您应该使用比 root 权限更少的用户,默认情况下 Docker 镜像是由 root 用户运行的(取决于您正在使用的基础镜像)。您可以在 Dockerfile 中运行 whoami
来检查这一点。
RUN echo "whoami: $(whoami)" # <--- whoami: root
在 node 和其他一些镜像中(包括 Alpine 基础镜像),我们有一个名为 node 的用户,我们可以使用它代替 root,权限更少。我们应该将此用户添加到镜像中,并尽可能使用它代替 root。
代码语言:shell复制RUN echo "whoami: $(whoami)" # <--- whoami: root
USER node
RUN echo "whoami: $(whoami)" # <--- whoami: node
# 现在我们使用 'node' 用户而不是 root 用户进行 Dockerfile 的后续操作。
--chown=node:node
选项确保复制的文件的所有权设置为 node 用户和组。
COPY --chown=node:node ./src ./src
COPY --chown=node:node ./package*.json ./
请记住,如果将 WORKDIR
设置为 /app
,这意味着 COPY
指令(以及其他指令)将文件复制到 WORKDIR
,您可以使用 .
来指定。
3- 多阶段构建
为什么?安全性和大小。
大小:您的最终镜像是否需要包含 package-lock.json,甚至 package.json?可能不需要,NodeJS 应用程序需要的是 node_modules 文件夹和位于 src 文件夹中的 JS 源代码,通常在 JS 项目中,如果是 TS 项目,则位于 dist 文件夹中,那是从 TS 编译为 JS 的编译后代码。
如果您的 NodeJS 应用程序是用 TypeScript 编写的,您可能会考虑:
代码语言:shell复制RUN apt-get update && apt-get install -y # <-- 对您的应用程序可能有用
WORKDIR /app
COPY . /app
RUN npm ci --only=production
RUN npm run build # 编译 TS 到 JS
RUN rm -rf /app/src # <------- 简单修复
CMD ["node", "dist/index.js"]
如果运行 docker history <image-name>
,您将看到 NPM_TOKEN
。当然,您可以始终运行 RUN export NPM_TOKEN=123
来从最终镜像中删除它,但这不是最佳做法,而且仍将在 docker history 中可见。
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!