Dockerfile 是一种用于构建 Docker 镜像的文本配置文件,其中逐条记录了构建所需的指令与参数。它通过明确的命令序列,指导 Docker 将应用程序及其运行环境逐层打包,最终生成一个可用的自定义镜像。可以说,Dockerfile 就是构建镜像的“蓝图”或“自动化脚本”。
Dockerfile 文件默认没有后缀名,纯文本文件,首字母大写,无扩展名,在执行 docker build 命令时,如果未指定文件名,Docker 会自动在当前目录下寻找名为 Dockerfile 的文件进行构建。
如果需要区分不同环境(如开发、测试、生产),可以使用带后缀或特定名称的文件,例如:Dockerfile.dev,使用非默认名称时,必须在构建命令中通过 -f 参数显式指定文件路径:docker build -f Dockerfile.dev -t my-app:dev . 日常开发中,直接创建名为 Dockerfile(无后缀)的文件是最标准、最通用的做法。
Dockerfile 中的指令虽然在文件中按顺序书写,但它们的执行时机和作用阶段有所不同。为了更清晰地理解,下表按照构建与运行时的逻辑执行顺序对 Dockerfile 的核心指令进行了汇总和排序:
| 执行阶段 | 指令 | 具体含义与作用 | 使用示例 |
|---|---|---|---|
| 1. 基础定义 | FROM | 指定基础镜像。必须是 Dockerfile 的第一条有效指令。它定义了后续所有操作基于哪个操作系统或环境层进行。支持多阶段构建命名。 | FROM python:3.9-slim AS builder |
| ARG | 定义构建参数。仅在镜像构建期间有效的变量。可以通过 docker build --build-arg 传入值,用于动态控制构建过程(如版本号)。容器运行时不可见。 | ARG VERSION=1.0 FROM python:${VERSION} | |
| LABEL | 添加元数据。以键值对形式为镜像添加描述信息(如作者、版本、描述),替代已废弃的 MAINTAINER。 | LABEL maintainer="anyfork" version="2.0" | |
| 2. 环境配置 | ENV | 设置环境变量。在构建期和运行期都有效。后续指令(如 RUN, COPY)可以使用这些变量,容器启动后应用也可以读取。 | ENV APP_HOME=/appENV DEBUG=true |
| WORKDIR | 设置工作目录。为后续的 RUN, CMD, ENTRYPOINT, COPY, ADD 指令指定执行或操作的目录。若目录不存在则自动创建。 | WORKDIR /usr/src/app | |
| USER | 指定用户。指定后续 RUN, CMD, ENTRYPOINT 指令执行时的用户身份(UID/GID)。出于安全考虑,建议最后切换为非 root 用户。 | USER nobodyUSER 1001:1001 | |
| 3. 文件操作 | COPY | 复制文件。将宿主机文件或目录复制到镜像中。行为简单透明,是推荐的文件复制方式。 | COPY requirements.txt .COPY . /usr/src/app |
| ADD | 高级复制。功能比 COPY 强,支持自动解压 tar 包或从 URL 下载文件。因行为复杂,官方建议优先使用 COPY。 | ADD app.tar.gz /opt/ | |
| VOLUME | 创建挂载点。声明容器运行时的数据卷挂载点,用于持久化数据或共享数据,避免数据写入联合文件系统层。 | VOLUME "/data" | |
| 4. 构建执行 | RUN | 执行命令。在镜像构建阶段执行 Shell 命令。每执行一条 RUN 指令会生成一个新的镜像层。常用于安装依赖、编译代码。 | RUN apt-get update && apt-get install -y curlRUN pip install -r requirements.txt |
| 5. 网络与端口 | EXPOSE | 声明端口。文档化地声明容器运行时监听的端口,并不实际映射端口。实际映射需在 docker run -p 中指定。 | EXPOSE 80EXPOSE 8080/tcp |
| 6. 健康检查 | HEALTHCHECK | 健康检查。定义周期性检查容器健康状态的命令。如果检查失败,容器状态变为 unhealthy。 | `HEALTHCHECK --interval=30s CMD curl -f http://localhost/ |
| 7. 启动配置 | STOPSIGNAL | 停止信号。设置发送给容器以使其退出的系统调用信号。默认是 SIGTERM。 | STOPSIGNAL SIGQUIT |
| ENTRYPOINT | 入口命令。配置容器启动时的主程序。它不会被 docker run 的参数直接覆盖,而是将参数追加其后。常与 CMD 配合使用。 | ENTRYPOINT "nginx", "-g", "daemon off;" | |
| CMD | 默认启动命令。指定容器启动时默认执行的命令或参数。如果用户运行 docker run 时指定了其他命令,CMD 会被覆盖。每个 Dockerfile 只能有一个生效的 CMD。 | CMD "python", "app.py"CMD "--help" (作为 ENTRYPOINT 的参数) | |
| 8. 触发器 | ONBUILD | 触发器。当当前镜像被用作其他 Dockerfile 的 FROM 基础镜像时,才会执行指定的指令。常用于构建通用基础镜像。 | ONBUILD COPY . /appONBUILD RUN npm install |
| SHELL | 指定 Shell。覆盖默认的 Shell(Linux 默认为 /bin/sh -c,Windows 为 cmd /S /C)。影响后续 RUN, CMD, ENTRYPOINT 的执行方式。 | SHELL "/bin/bash", "-c" |
关键逻辑说明
优化 Dockerfile 以提高构建速度,核心在于最大化利用 Docker 的层缓存机制、减小构建上下文体积以及减少不必要的指令执行。以下是经过验证的最佳实践策略:
基于前文关于 Dockerfile 指令、构建优化技巧,以下是为 Nuxt 4(基于 Nitro 引擎)生成生产级 Docker 镜像的完整方案。Nuxt 4 通常采用 SSR(服务端渲染)或静态生成,下面分别介绍2种模式下Dockerfile配置。
为了实现最小化镜像体积和最快启动速度,推荐使用 多阶段构建(Multi-stage Builds)。
# 阶段 1:构建依赖与编译
FROM node:20-alpine AS builder
# 1. 安装 pnpm (Alpine 镜像默认不含 pnpm)
RUN npm install -g pnpm
WORKDIR /app
# 2. 复制 pnpm 锁文件和 package.json
COPY package.json pnpm-lock.yaml ./
# 3. 安装依赖 (使用 --frozen-lockfile 确保一致性)
RUN pnpm install --frozen-lockfile
# 4. 复制源代码并构建
COPY . .
RUN pnpm run build
# 阶段 2:生产运行环境
FROM node:20-alpine AS runner
# 1. 安装 pnpm (若启动脚本依赖 pnpm,否则可省略,但建议保留以保持一致性)
RUN npm install -g pnpm
WORKDIR /app
ENV NODE_ENV=production
ENV HOST=0.0.0.0
ENV PORT=3000
# 2. 仅复制构建产物
COPY --from=builder /app/.output ./
EXPOSE 3000
# 3. 启动命令 (Nuxt/Nitro 标准入口)
CMD ["node", "server/index.mjs"]
在静态模式下,Nuxt 会预渲染所有页面为 HTML/CSS/JS 文件,无需 Node.js 运行时服务器,因此推荐使用 Nginx 作为轻量级 Web 服务器托管这些静态资源。
# 阶段 1:构建静态资源
FROM node:20-alpine AS builder
WORKDIR /app
# 1. 安装 pnpm (若使用 npm/yarn 请调整对应指令)
RUN npm install -g pnpm
# 2. 复制依赖文件并安装
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
# 3. 复制源码并生成静态文件
COPY . .
# Nuxt 静态生成命令通常为 generate,输出目录默认为 .output/public 或 dist
RUN pnpm run generate
# 阶段 2:Nginx 托管静态文件
FROM nginx:alpine AS runner
# 1. 移除 Nginx 默认配置
RUN rm /etc/nginx/conf.d/default.conf
# 2. 复制自定义 Nginx 配置 (可选,见下方说明)
COPY nginx.conf /etc/nginx/conf.d/default.conf
# 3. 将构建产物复制到 Nginx 默认网页目录
# 注意:Nuxt 4 (Nitro) 静态输出通常在 .output/public
COPY --from=builder /app/.output/public /usr/share/nginx/html
# 4. 暴露 80 端口
EXPOSE 80
# 5. 启动 Nginx
CMD ["nginx", "-g", "daemon off;"]
配套 Nginx 配置 (nginx.conf),为了确保 SPA(单页应用)或预渲染页面在刷新时不出现 404,建议添加以下 nginx.conf 文件到项目根目录:
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# 启用 Gzip 压缩
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# 处理 SPA 路由回退:如果文件不存在,返回 index.html
location / {
try_files $uri $uri/ /index.html;
}
# 缓存静态资源
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
在项目根目录执行以下命令:
docker build -t nuxt4-app:latest .
docker run -d -p 3000:3000 --name my-nuxt-app nuxt4-app:latest
访问 http://localhost:3000 即可看到 Nuxt 应用。
务必在项目根目录创建 .dockerignore,排除 node_modules、.git、.nuxt 等无关文件,加速构建上下文传输。
node_modules
.git
.nuxt
.output
dist
*.md
.env