Dockerfile 作用与运行阶段

60 阅读2分钟

什么是 Dockerfile?

Dockerfile 是一个构建指令文件,用于定义如何构建 Docker 镜像。它包含了一系列指令,告诉 Docker 如何:

  • 选择基础镜像
  • 安装依赖
  • 复制文件
  • 设置环境变量
  • 运行命令
  • 配置容器启动方式

多阶段构建(Multi-Stage Build)

为什么使用多阶段构建?

传统单阶段构建:

源代码 + 构建工具 + 依赖 + 构建产物 = 大镜像(~1GB+)

多阶段构建:

[阶段1] 源代码 + 构建工具 + 依赖 → 构建产物

[阶段2] 只复制构建产物 → 小镜像(~200MB)

优势:

✅ 减小镜像体积:最终镜像不包含构建工具和源代码

✅ 提高安全性:运行时不包含构建工具和源代码

✅ 优化构建缓存:依赖安装和代码构建分离,缓存更高效

两个阶段

阶段作用包含内容最终产物
构建阶段 (builder)编译和打包应用Node.js、pnpm、源代码、依赖.next/standalone、 .next/static
运行阶段 (runner)运行应用Node.js、构建产物可运行的容器

构建阶段(Builder Stage)

基础镜像选择

FROM ${REGISTRY}/open-source/node:18-alpine as builder

作用

  • 选择 Node.js 18 作为基础镜像
  • 使用 Alpine Linux(体积小,~5MB)
  • as builder 给这个阶段命名,后续可以引用

构建时环境变量

ARG NEXT_PUBLIC_MAGIC_OFFICIAL_DEFAULT_LANG

ARG NEXT_PUBLIC_MAGIC_OFFICIAL_CDN_DOMAIN

ARG NEXT_PUBLIC_MAGIC_OFFICIAL_PUBLIC_CDN_DOMAIN

ARG NEXT_PUBLIC_MAGIC_OFFICIAL_ENV

ARG NEXT_PUBLIC_MAGIC_OFFICIAL_SERVICE_URL

ENV NEXT_PUBLIC_MAGIC_OFFICIAL_DEFAULT_LANG=${NEXT_PUBLIC_MAGIC_OFFICIAL_DEFAULT_LANG}

ENV NEXT_PUBLIC_MAGIC_OFFICIAL_CDN_DOMAIN=${NEXT_PUBLIC_MAGIC_OFFICIAL_CDN_DOMAIN}

ENV NEXT_PUBLIC_MAGIC_OFFICIAL_PUBLIC_CDN_DOMAIN=${NEXT_PUBLIC_MAGIC_OFFICIAL_PUBLIC_CDN_DOMAIN}

ENV NEXT_PUBLIC_MAGIC_OFFICIAL_ENV=${NEXT_PUBLIC_MAGIC_OFFICIAL_ENV}

ENV NEXT_PUBLIC_MAGIC_OFFICIAL_SERVICE_URL=${NEXT_PUBLIC_MAGIC_OFFICIAL_SERVICE_URL}

作用

  • ARG(构建参数)

    作用域:仅在构建阶段(Builder Stage)有效

    生命周期:构建完成后消失,不会保留在最终镜像中

    用途:传递构建时的参数

  • ENV(环境变量)

    作用域:构建阶段和运行阶段都有效

    生命周期:会保留在最终镜像中,容器运行时也可用

    用途:设置应用运行时的环境变量

  • 注意:这些值会被"烧录"到构建产物中,导致镜像与环境耦合

    • “烧录” = 构建时将值写入镜像,运行时无法更改

      优点:客户端静态配置可以提前确定

      缺点:环境相关配置不应烧录,否则会导致镜像与环境耦合

    烧录的解决方案:运行容器时通过-e传入环境变量

运行容器时传入环境变量,覆盖镜像内的ENV

docker run -e NEXT_PUBLIC_CDN_DOMAIN=https://cdn.prod.example.com your-image:latest
//这种方式既保留了 ENV 的可用性,又避免了镜像与环境耦合,是生产环境的常用最佳实践。

运行阶段(Runner Stage):从 “构建产物” 到 “可运行容器”

仅保留应用运行必需的内容(Node.js 运行时 + 构建产物),剔除所有构建相关的依赖 / 源码,最终生成轻量、安全的可运行镜像。


常见模式 ARG:允许构建时传入不同的值 + ENV:确保值保留在镜像中,运行时可用
1. 定义 ARG(构建参数)

ARG NEXT_PUBLIC_CDN_DOMAIN

2. 将 ARG 转换为 ENV(保留在镜像中)

ENV NEXT_PUBLIC_CDN_DOMAIN=${NEXT_PUBLIC_CDN_DOMAIN}

构建时

docker build --build-arg NEXT_PUBLIC_CDN_DOMAIN=https://cdn.example.com .

结果:

- 构建时:ARG 的值传递给 ENV

- 构建后:ENV 的值保留在镜像中

- 运行时:容器可以访问 $NEXT_PUBLIC_CDN_DOMAIN

例子

code.png