mirror of
https://github.com/yeasy/docker_practice.git
synced 2026-10-21 10:16:38 +00:00
全书此前是真·五五开:含中文的括号 336 处半角 : 336 处全角,而且**在同一文件 内混用**——`18_security/18.1_kernel_ns.md` 第 11/17/20 行写 `(如 runC)`, 第 31 行写 `(用户命名空间映射)`。这不是体例问题,是它自己跟自己不一致。 集群里其余 13 本都一边倒(llm_internals 5 : 1049、oc_guide 2 : 713、 forward_deployed_engineering_guide 0 : 108),blockchain_guide 已在 2026-08-05 按同一方向统一过 97 处,故取全角,而非另立新规。全角括号前后不留空格, 原先 `概念 (镜像、容器、仓库) 和` 两侧的空格一并收掉。 **纯拉丁内容的半角括号一个没动**——`新建一个层 (Layer)`、`项目 (project)` 保持原样:改动前后「半角且内容纯拉丁」的数量都是 **1163**,而「半角且含中文」 从 **336 变成 0**。 其余验证:改动前后各自抹掉全部空白与圆括号后**逐字节相同**(两侧均 19559 字符); 左右括号总数改动前后都是 399 : 399,证明没有吞括号也没有配错对。 `check_project_rules` 202/202、`check_emphasis` 202/202、37 tests OK、 根 `format_checker` 与 `validate_codeblocks` 干净、`git diff --check` 干净。
4.9 KiB
4.9 KiB
7.6 ENV 设置环境变量
7.6.1 基本语法
## 格式一:单个变量
ENV <key>=<value>
## 格式二:多个变量
ENV <key1>=<value1> <key2>=<value2> ...
⚠️ 用空格分隔的旧写法
ENV <key> <value>(ARG同理)虽然仍能构建,但已被官方弃用。BuildKit 的 LegacyKeyValueFormat 构建检查会报"ENV key=value" should be used instead of legacy "ENV key value" format,docker buildx build --check(见 10.2)会直接把它标出来。一律用等号。
7.6.2 基本用法
设置单个变量
ENV NODE_VERSION=20
ENV APP_ENV=production
设置多个变量
ENV NODE_VERSION=20 \
APP_ENV=production \
APP_NAME="My Application"
💡 包含空格的值用双引号括起来。
7.6.3 环境变量的作用
1. 后续指令中使用
ENV NODE_VERSION=20.10.0
## 在 RUN 中使用
RUN curl -fsSL https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.xz \
| tar -xJ -C /usr/local --strip-components=1
## 在 WORKDIR 中使用
ENV APP_HOME=/app
WORKDIR $APP_HOME
## 在 COPY 中使用
COPY . $APP_HOME
2. 容器运行时使用
ENV DATABASE_URL=postgres://localhost/mydb
应用代码中可以读取:
import os
db_url = os.environ.get('DATABASE_URL')
const dbUrl = process.env.DATABASE_URL;
7.6.4 支持环境变量的指令
以下指令可以使用 $变量名 或 ${变量名} 格式:
| 指令 | 示例 |
|---|---|
RUN |
RUN echo $VERSION |
CMD |
CMD ["sh", "-c", "echo $HOME"] |
ENTRYPOINT |
同上 |
COPY |
COPY . $APP_HOME |
ADD |
ADD app.tar.gz $APP_HOME |
WORKDIR |
WORKDIR $APP_HOME |
EXPOSE |
EXPOSE $PORT |
VOLUME |
VOLUME $DATA_DIR |
USER |
USER $USERNAME |
LABEL |
LABEL version=$VERSION |
FROM |
FROM node:$NODE_VERSION |
注意:
FROM是上表中的特例——它只能引用在第一条FROM之前用ARG声明的变量,无法使用ENV定义的环境变量(ENV要进入构建阶段后才生效)。其余指令才能引用ENV环境变量。
7.6.5 运行时覆盖
使用 -e 或 --env 覆盖 Dockerfile 中定义的环境变量:
## 覆盖单个变量
$ docker run -e APP_ENV=development myimage
## 覆盖多个变量
$ docker run -e APP_ENV=development -e DEBUG=true myimage
## 从环境变量文件读取
$ docker run --env-file .env myimage
.env 文件格式
## .env
APP_ENV=development
DEBUG=true
DATABASE_URL=postgres://localhost/mydb
7.6.6 ENV vs ARG
| 特性 | ENV | ARG |
|---|---|---|
| 生效时间 | 构建时 + 运行时 | 仅构建时 |
| 持久性 | 写入镜像,运行时可用 | 构建后消失 |
| 覆盖方式 | docker run -e |
docker build --build-arg |
| 适用场景 | 应用配置 | 构建参数(如版本号) |
组合使用
## ARG 接收构建时参数
ARG NODE_VERSION=20
## ENV 保存到运行时
ENV NODE_VERSION=$NODE_VERSION
## 后续指令使用
RUN curl -fsSL https://nodejs.org/dist/v${NODE_VERSION}/...
## 构建时指定版本
$ docker build --build-arg NODE_VERSION=18 -t myapp .
7.6.7 最佳实践
1. 统一管理版本号
## ✅ 好:版本集中管理
ENV NGINX_VERSION=1.30 \
NODE_VERSION=22 \
PYTHON_VERSION=3.12
RUN apt-get install nginx=${NGINX_VERSION}
## ❌ 差:版本分散在各处
RUN apt-get install nginx=1.30
2. 不要存储敏感信息
## ❌ 错误:密码写入镜像
ENV DB_PASSWORD=secret123
## ✅ 正确:运行时传入
## docker run -e DB_PASSWORD=xxx myimage
...
3. 为应用提供合理默认值
ENV APP_ENV=production \
APP_PORT=8080 \
LOG_LEVEL=info
4. 使用有意义的变量名
## ✅ 好:清晰的命名
ENV REDIS_HOST=localhost \
REDIS_PORT=6379
## ❌ 差:模糊的命名
ENV HOST=localhost \
PORT=6379
7.6.8 常见问题
Q:环境变量在 CMD 中不展开
exec 格式不会自动执行 shell 展开,因此命令参数里的 $PORT 会按字面值传给进程;但环境变量本身仍会注入进程环境,应用可以通过语言运行时读取。
## ❌ 不会展开 $PORT
CMD ["python", "app.py", "--port", "$PORT"]
## ✅ 使用 shell 格式或显式调用 sh
CMD ["sh", "-c", "python app.py --port $PORT"]
Q:如何查看容器的环境变量
$ docker inspect mycontainer --format '{{json .Config.Env}}'
$ docker exec mycontainer env
Q:多行 ENV 还是多个 ENV
## ✅ 推荐:减少层数
ENV VAR1=value1 \
VAR2=value2 \
VAR3=value3
## ⚠️ 多个 ENV 会创建多层
ENV VAR1=value1
ENV VAR2=value2
ENV VAR3=value3