> For the complete documentation index, see [llms.txt](https://yeasy.gitbook.io/docker_practice/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yeasy.gitbook.io/docker_practice/di-er-bu-fen-jin-jie-pian/07_dockerfile/7.7_arg.md).

# 7.7 ARG 构建参数

## 7.7.1 基本语法

```docker
ARG <参数名>[=<默认值>]
```

`ARG` 指令定义构建时的变量，可以在 `docker build` 时通过 `--build-arg` 传入。

***

## 7.7.2 ARG vs ENV

| 特性       | ARG                        | ENV                 |
| -------- | -------------------------- | ------------------- |
| **生效时间** | 仅构建时                       | 构建时 + 运行时           |
| **持久性**  | 构建后消失                      | 写入镜像                |
| **覆盖方式** | `docker build --build-arg` | `docker run -e`     |
| **适用场景** | 构建参数（版本号等）                 | 应用配置                |
| **可见性**  | `docker history` 可见        | `docker inspect` 可见 |

```dockerfile
构建时                         运行时
├─ ARG VERSION=1.0             │ （ARG 已消失）
├─ ENV APP_ENV=prod            │ APP_ENV=prod（仍存在）
└─ RUN echo $VERSION           │
```

> ⚠️ **安全提示**：不要用 ARG 传递密码等敏感信息，`docker history` 可以查看所有 ARG 值。

***

## 7.7.3 基本用法

### 定义和使用

```docker
## 定义有默认值的 ARG
## 建议使用主版本号，如 20 而非 20.10.0，这样可以自动获取最新的补丁版本

ARG NODE_VERSION=20

## 使用 ARG

FROM node:${NODE_VERSION}-alpine
RUN echo "Using Node.js $NODE_VERSION"
```

### 构建时覆盖

```bash
## 使用默认值

$ docker build -t myapp .

## 覆盖默认值

$ docker build --build-arg NODE_VERSION=18 -t myapp .
```

***

## 7.7.4 ARG 的作用域

### FROM 之前的 ARG

```docker
## FROM 之前的 ARG 只能用于 FROM 指令

ARG REGISTRY=docker.io
ARG IMAGE_NAME=node

FROM ${REGISTRY}/${IMAGE_NAME}:20

## ❌ 这里无法使用上面的 ARG

RUN echo $REGISTRY  # 输出空
```

### FROM 之后重新声明

```docker
ARG NODE_VERSION=20

FROM node:${NODE_VERSION}-alpine

## 需要再次声明才能使用

ARG NODE_VERSION
RUN echo "Node version: $NODE_VERSION"
```

### 多阶段构建中的 ARG

```docker
ARG BASE_VERSION=alpine

FROM node:22-${BASE_VERSION} AS builder

## 需要重新声明

ARG NODE_VERSION=20
RUN echo "Building with Node $NODE_VERSION"

FROM node:22-${BASE_VERSION}

## 每个阶段都需要重新声明

ARG NODE_VERSION=20
RUN echo "Running with Node $NODE_VERSION"
```

***

## 7.7.5 常见使用场景

### 1. 控制基础镜像版本

```docker
# 推荐使用主版本号（如 3），或指定次版本号（如 3.19），避免指定完整补丁版本
ARG ALPINE_VERSION=3
FROM alpine:${ALPINE_VERSION}
```

```bash
$ docker build --build-arg ALPINE_VERSION=3.19 .
```

### 2. 设置软件版本

```docker
# 使用次版本号 (1.30) 而非完整版本号 (1.30.0)，以便自动更新到最新补丁版本
ARG NGINX_VERSION=1.30

RUN curl -fsSL https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz | tar -xz
```

### 3. 配置构建环境

```docker
ARG BUILD_ENV=production
ARG ENABLE_DEBUG=false

RUN if [ "$ENABLE_DEBUG" = "true" ]; then \
        npm install --include=dev; \
    else \
        npm install --production; \
    fi
```

### 4. 配置私有仓库

不要用 `ARG` 或 `ENV` 传递仓库 token。Docker 官方构建检查会把这类写法视为不安全，因为构建参数和环境变量可能进入镜像元数据或历史记录。使用 BuildKit secret mount 只在单条 `RUN` 指令期间暴露凭据：

```docker
RUN --mount=type=secret,id=npm_token \
    NPM_TOKEN="$(cat /run/secrets/npm_token)" && \
    printf "//registry.npmjs.org/:_authToken=%s\n" "$NPM_TOKEN" > ~/.npmrc && \
    npm install && \
    rm ~/.npmrc
```

```bash
## 构建时传入 token

$ docker build --secret id=npm_token,env=NPM_TOKEN .
```

***

## 7.7.6 将 ARG 传递给 ENV

如果需要在运行时使用 ARG 的值：

```docker
ARG VERSION=1.0.0

## 将 ARG 传递给 ENV

ENV APP_VERSION=$VERSION

## 运行时可用

CMD echo "App version: $APP_VERSION"
```

***

## 7.7.7 预定义 ARG

Docker 提供了一些预定义的 ARG，无需声明即可使用：

| ARG           | 说明       |
| ------------- | -------- |
| `HTTP_PROXY`  | HTTP 代理  |
| `HTTPS_PROXY` | HTTPS 代理 |
| `NO_PROXY`    | 不使用代理的地址 |
| `FTP_PROXY`   | FTP 代理   |

```bash
## 构建时使用代理

$ docker build --build-arg HTTP_PROXY=http://proxy:8080 .
```

***

## 7.7.8 最佳实践

### 1. 为 ARG 提供合理默认值

```docker
## ✅ 好：有默认值，建议使用主或次版本号而非完整版本号

ARG NODE_VERSION=20

## ⚠️ 需要每次传入

ARG NODE_VERSION
```

### 2. 不要用 ARG 存储敏感信息

```docker
## ❌ 错误：密码会被记录在镜像历史中

ARG DB_PASSWORD
RUN echo "password=$DB_PASSWORD" > /app/.env

## ✅ 正确：使用 secrets 或运行时环境变量

...
```

### 3. 使用 ARG 提高构建灵活性

```docker
# 推荐使用次版本号标签，允许Docker自动拉取最新的补丁版本
ARG BASE_IMAGE=python:3.12-slim
FROM ${BASE_IMAGE}

## 可以构建不同基础镜像的版本

## docker build --build-arg BASE_IMAGE=python:3-slim .

...
```

***
