DevToolBox免费
博客

Docker Compose env_file vs environment:何时使用哪个(附示例)

7 分钟阅读作者 DevToolBox

Docker Compose 提供多种方式将环境变量注入容器:environment 指令、env_file 指令、根级 .env 文件和构建时 ARG 值。每种方式行为不同,具有不同的优先级规则、安全影响和使用场景。本指南详细说明何时使用哪种方式,并提供可直接复制的 docker-compose.yml 示例。

快速答案:env_file 用于密钥,environment 用于配置

如果你只需要一个快速经验法则:

  • environment: 使用 environment 设置非敏感的、服务特定的配置,这些配置你希望在 Compose 文件中可见(端口号、日志级别、功能开关)。
  • env_file: 使用 env_file 管理密钥和分组变量,将它们排除在版本控制之外(API 密钥、数据库密码、第三方凭证)。
  • .env: 使用根级 .env 文件仅用于 Compose 文件插值(镜像标签、端口映射、副本数量)。
  • ARG: 使用 ARG 设置构建时的值,这些值不应在运行时存在(构建工具版本、依赖标志)。
# Quick reference — same service using all methods:
services:
  api:
    build:
      context: .
      args:
        NODE_VERSION: 20          # ARG: build-time only
    image: myapp:${TAG:-latest}   # .env: Compose interpolation
    env_file:
      - .env.secrets              # env_file: secrets (gitignored)
    environment:
      NODE_ENV: production        # environment: inline config
      LOG_LEVEL: info
      PORT: "3000"

environment:内联和映射语法

environment 指令直接在 docker-compose.yml 中定义键值对。这些值在版本控制中可见,并覆盖 env_file 中的值。

列表语法(数组)

使用数组中的 KEY=VALUE 字符串。在教程和快速设置中最常见:

services:
  api:
    image: node:20-alpine
    environment:
      - NODE_ENV=production
      - DB_HOST=postgres
      - DB_PORT=5432
      - LOG_LEVEL=info
      - CACHE_TTL=3600

映射语法(字典)

使用 YAML 键值映射。对大型配置更清晰,支持 YAML 锚点:

# Map syntax — cleaner for large configs
services:
  api:
    image: node:20-alpine
    environment:
      NODE_ENV: production
      DB_HOST: postgres
      DB_PORT: "5432"            # Quotes needed for numeric strings
      LOG_LEVEL: info
      CACHE_TTL: "3600"

  # YAML anchors work with map syntax
  x-common-env: &common-env
    NODE_ENV: production
    LOG_LEVEL: info
    TZ: UTC

  worker:
    image: node:20-alpine
    environment:
      <<: *common-env            # Merge common variables
      QUEUE_NAME: tasks
      CONCURRENCY: "4"

覆盖行为

environment 中的值始终覆盖 env_file 中的相同键。这是设计使然,允许你在文件中设置默认值并内联覆盖特定值:

# .env.shared (loaded via env_file)
DB_HOST=shared-database
DB_PORT=5432
DB_NAME=myapp
LOG_LEVEL=warn

# docker-compose.yml
services:
  api:
    image: node:20-alpine
    env_file:
      - .env.shared              # DB_HOST=shared-database, LOG_LEVEL=warn
    environment:
      DB_HOST: custom-db         # OVERRIDES env_file! DB_HOST=custom-db
      LOG_LEVEL: debug           # OVERRIDES env_file! LOG_LEVEL=debug
      # DB_PORT and DB_NAME keep their env_file values

# Final result inside container:
#   DB_HOST=custom-db        (from environment, overrode env_file)
#   DB_PORT=5432             (from env_file, not overridden)
#   DB_NAME=myapp            (from env_file, not overridden)
#   LOG_LEVEL=debug          (from environment, overrode env_file)

Shell 透传

列出不带值的变量名,将主机 shell 变量传递到容器中:

# On your host machine:
export API_KEY=sk-abc123
export AWS_REGION=us-east-1

# docker-compose.yml
services:
  api:
    image: node:20-alpine
    environment:
      - API_KEY               # Passes host $API_KEY into container
      - AWS_REGION            # Passes host $AWS_REGION into container
      - CI                    # Empty string if $CI is not set on host
      - DEBUG                 # Empty string if $DEBUG is not set on host

env_file:外部文件加载

env_file 指令从一个或多个外部文件加载变量到容器环境中。与 environment 不同,这些文件可以被 gitignore,从而将密钥排除在版本控制之外。

.env 文件格式规则

# .env.api — env_file format rules

# Lines starting with # are comments
# Blank lines are ignored

# Basic KEY=VALUE (no spaces around =)
DB_HOST=postgres
DB_PORT=5432

# Values with spaces — use quotes
APP_NAME="My API Service"
GREETING='Hello World'

# No variable substitution! This is LITERAL:
# BASE_URL=${DOMAIN}        # WRONG — will be literal "${DOMAIN}"
BASE_URL=https://api.example.com

# Multi-line values (double quotes only)
RSA_KEY="-----BEGIN RSA KEY-----
MIIEpAIBAAKCAQEA...
-----END RSA KEY-----"

# export prefix is stripped (compatible with shell source)
export SECRET_KEY=mysecretkey

# Empty values
EMPTY_VAR=
ALSO_EMPTY=''

多文件和合并顺序

你可以指定多个文件。后面的文件会覆盖前面文件中的相同键:

# .env.defaults
DB_HOST=localhost
DB_PORT=5432
LOG_LEVEL=info

# .env.overrides
DB_HOST=production-db         # Overrides .env.defaults
LOG_LEVEL=error               # Overrides .env.defaults

# docker-compose.yml
services:
  api:
    image: node:20-alpine
    env_file:
      - .env.defaults           # Loaded first
      - .env.overrides          # Loaded second, overrides duplicates

# Final result:
#   DB_HOST=production-db     (from .env.overrides)
#   DB_PORT=5432              (from .env.defaults, not overridden)
#   LOG_LEVEL=error           (from .env.overrides)

路径解析

env_file 中的文件路径相对于 docker-compose.yml 文件的位置,而非当前工作目录。这是一个常见的混淆源:

# Project structure:
my-project/
  docker-compose.yml            # Compose file lives here
  .env.api                      # Same directory — OK
  config/
    .env.db                     # Subdirectory — relative to compose file
  ../shared/
    .env.common                 # Parent directory — also relative

# docker-compose.yml
services:
  api:
    env_file:
      - .env.api                # ./my-project/.env.api
      - config/.env.db          # ./my-project/config/.env.db
      - ../shared/.env.common   # ./shared/.env.common

# WRONG: Paths are NOT relative to where you run docker compose from!
# If you run "docker compose up" from a different directory,
# paths are still relative to the docker-compose.yml location.

可选 env_file(Compose v2.24+)

默认情况下,缺失的 env_file 会导致错误。使用 required 字段使其可选:

# docker-compose.yml
services:
  api:
    image: node:20-alpine
    env_file:
      - .env.shared                       # Required — error if missing
      - path: .env.local
        required: false                   # Optional — no error if missing
      - path: .env.secrets
        required: false                   # Optional — useful for dev

# Use case: .env.local exists only on developer machines
# for personal overrides, never committed to git.

.env 文件(根级):Docker Compose 自动加载

Docker Compose 自动读取与 docker-compose.yml 同目录(或项目目录)下名为 .env 的文件。这个文件有一个经常被误解的特殊用途。

.env 实际做什么

  • YES: .env 文件为 docker-compose.yml 内部的 ${VARIABLE} 替换提供值。
  • NO: 它不会自动将变量注入容器。
  • TIP: 要将 .env 的值传入容器,你必须同时使用 environment 或 env_file。

.env 如何工作(以及不如何工作)

# .env (root level, auto-loaded)
TAG=3.2.1
EXTERNAL_PORT=8080
REPLICAS=3
DB_PASSWORD=supersecret

# docker-compose.yml
services:
  api:
    image: myapp:${TAG}                # WORKS: Interpolated to myapp:3.2.1
    ports:
      - "${EXTERNAL_PORT}:3000"        # WORKS: Interpolated to 8080:3000
    deploy:
      replicas: ${REPLICAS}            # WORKS: Interpolated to 3
    environment:
      - DB_PASSWORD                     # DOES NOT WORK the way you think!
      # This passes the HOST $DB_PASSWORD, not the .env value.
      # If host has no $DB_PASSWORD, the container gets an empty string.

      # To pass .env values into the container, do one of these:
      - DB_PASSWORD=${DB_PASSWORD}     # Option 1: Explicit interpolation
    # OR:
    # env_file:
    #   - .env                          # Option 2: Load entire .env file

使用 --env-file 覆盖

你可以让 Compose 指向不同的插值文件:

# Default: reads .env from project directory
docker compose up

# Use a different file for Compose interpolation:
docker compose --env-file .env.staging up

# Multiple env files (Compose v2.24+):
docker compose --env-file .env --env-file .env.local up

# This affects ONLY ${} interpolation in docker-compose.yml.
# It does NOT affect env_file directives or container variables.

对比表:env_file vs environment vs .env vs ARG

以下是四种方法的并排对比:

特性environmentenv_file.env(根级)ARG(构建)
用途直接设置容器环境变量从文件加载环境变量Compose 文件插值构建时变量
作用域运行时(容器)运行时(容器)仅 Compose 文件仅构建时(除非传递给 ENV)
在 docker-compose.yml 中?
可被 gitignore?
适合存密钥?部分
优先级最高最低(仅插值)仅构建时
支持 ${} 语法?仅在值中文件内部不支持不适用不适用

变量替换:${VAR:-default}、${VAR:?error}

Docker Compose 支持 shell 风格的变量替换,具有强大的默认值和错误处理语法。这些在 docker-compose.yml 的值中使用 .env 或主机 shell 的变量。

语法结果示例
${VAR}VAR 的值,未设置则为空字符串image: myapp:${TAG}
${VAR:-default}VAR 的值,未设置/为空则使用 "default"image: myapp:${TAG:-latest}
${VAR-default}VAR 的值,未设置则使用 "default"(允许空值)LOG_LEVEL: ${LOG:-}
${VAR:?error msg}VAR 的值,未设置/为空则退出并报错DB_HOST: ${DB_HOST:?Must set DB_HOST}
${VAR?error msg}VAR 的值,未设置则退出并报错(允许空值)API_KEY: ${API_KEY?Missing API_KEY}
${VAR:+replacement}如果 VAR 已设置且非空则为 "replacement",否则为空DEBUG: ${DEBUG:+true}

带默认值和验证的实际示例

# .env
TAG=3.2.1
# DB_HOST is intentionally NOT set

# docker-compose.yml
services:
  api:
    image: myapp:${TAG:-latest}                         # -> myapp:3.2.1
    environment:
      DB_HOST: ${DB_HOST:?Error: DB_HOST is required}   # -> exits with error!
      DB_PORT: ${DB_PORT:-5432}                          # -> 5432 (default)
      LOG_LEVEL: ${LOG_LEVEL:-info}                      # -> info (default)
      DEBUG: ${DEBUG:+true}                              # -> empty (DEBUG not set)
      REPLICAS: ${REPLICAS:-1}                           # -> 1 (default)

  db:
    image: postgres:${PG_VERSION:-16}                    # -> postgres:16 (default)
    environment:
      POSTGRES_DB: ${DB_NAME:-myapp}                     # -> myapp (default)
      POSTGRES_PASSWORD: ${DB_PASSWORD:?Set DB_PASSWORD}  # -> exits with error!

优先级顺序:environment > env_file > .env > Dockerfile ENV

当同一变量在多个位置定义时,Docker Compose 应用严格的优先级顺序。理解这一点可以避免数小时的调试。

从最高到最低优先级:

  1. 1. docker compose run -e KEY=VALUE(CLI 覆盖)
  2. 2. 主机 shell 环境变量
  3. 3. docker-compose.yml 中的 environment 指令
  4. 4. env_file 指令(后面的文件覆盖前面的文件)
  5. 5. .env 文件(仅用于 Compose 插值)
  6. 6. Dockerfile ENV 指令

优先级演示

# Dockerfile
ENV DB_HOST=dockerfile-db          # Priority 6 (lowest)

# .env (root)
DB_HOST=dotenv-db                  # Priority 5 (Compose interpolation only)

# .env.file (loaded via env_file)
DB_HOST=envfile-db                 # Priority 4

# docker-compose.yml
services:
  api:
    build: .
    env_file:
      - .env.file                  # DB_HOST=envfile-db
    environment:
      DB_HOST: compose-db          # Priority 3 — WINS over env_file

# On host shell:
export DB_HOST=shell-db            # Priority 2 — WINS over environment

# CLI override:
docker compose run -e DB_HOST=cli-db api   # Priority 1 — WINS over everything

# Result with all defined:
#   docker compose run -e  ->  DB_HOST=cli-db
#   Without CLI override   ->  DB_HOST=shell-db
#   Without shell export   ->  DB_HOST=compose-db
#   Without environment:   ->  DB_HOST=envfile-db
#   Without env_file:      ->  DB_HOST=dockerfile-db

实际设置:开发、预发布、生产

这是一个完整的、经过生产测试的多环境设置,使用了上述所有技术。

项目结构

my-project/
  docker-compose.yml              # Base config (shared across environments)
  docker-compose.override.yml     # Dev overrides (auto-loaded)
  docker-compose.staging.yml      # Staging overrides
  docker-compose.prod.yml         # Production overrides
  .env                            # Dev defaults (Compose interpolation)
  .env.staging                    # Staging defaults
  .env.prod                       # Production defaults
  .env.secrets                    # Secrets (gitignored)
  .env.secrets.example            # Template for secrets (committed)
  .gitignore                      # Ignores .env.secrets, .env.local, etc.

基础 docker-compose.yml

# docker-compose.yml — shared base config
services:
  api:
    build:
      context: .
      args:
        NODE_VERSION: ${NODE_VERSION:-20}
    image: myapp:${TAG:-latest}
    ports:
      - "${API_PORT:-3000}:3000"
    env_file:
      - path: .env.secrets
        required: false
    environment:
      NODE_ENV: ${NODE_ENV:-development}
      DB_HOST: ${DB_HOST:-postgres}
      DB_PORT: ${DB_PORT:-5432}
      DB_NAME: ${DB_NAME:-myapp}
      REDIS_URL: redis://redis:6379
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_started

  postgres:
    image: postgres:${PG_VERSION:-16}
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: ${DB_NAME:-myapp}
      POSTGRES_USER: ${DB_USER:-myapp}
    env_file:
      - path: .env.secrets
        required: false
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-myapp}"]
      interval: 5s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    volumes:
      - redisdata:/data

volumes:
  pgdata:
  redisdata:

开发环境:docker-compose.override.yml

此文件在开发环境中由 docker compose up 自动加载:

# docker-compose.override.yml — auto-loaded in dev
services:
  api:
    build:
      target: development
    volumes:
      - .:/app                          # Hot reload
      - /app/node_modules
    environment:
      NODE_ENV: development
      LOG_LEVEL: debug
      DEBUG: "true"
    ports:
      - "9229:9229"                     # Node.js debugger

  postgres:
    ports:
      - "5432:5432"                     # Expose DB for local tools
    environment:
      POSTGRES_PASSWORD: devpassword    # OK for dev only!

# .env (dev defaults)
TAG=latest
API_PORT=3000
NODE_ENV=development
DB_HOST=postgres
DB_NAME=myapp_dev

预发布环境:docker-compose.staging.yml

# docker-compose.staging.yml
services:
  api:
    build:
      target: production
    environment:
      NODE_ENV: staging
      LOG_LEVEL: info
    deploy:
      replicas: 2
      resources:
        limits:
          memory: 512M
          cpus: "0.5"

  postgres:
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt

# .env.staging
TAG=3.2.1-rc.1
API_PORT=3000
NODE_ENV=staging
DB_NAME=myapp_staging

生产环境:docker-compose.prod.yml

# docker-compose.prod.yml
services:
  api:
    build:
      target: production
    restart: unless-stopped
    environment:
      NODE_ENV: production
      LOG_LEVEL: warn
    deploy:
      replicas: 4
      resources:
        limits:
          memory: 1G
          cpus: "1.0"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  postgres:
    restart: unless-stopped
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password
    deploy:
      resources:
        limits:
          memory: 2G

  redis:
    restart: unless-stopped
    command: redis-server --requirepass ${REDIS_PASSWORD}

secrets:
  db_password:
    file: ./secrets/db_password.txt

# .env.prod
TAG=3.2.1
API_PORT=3000
NODE_ENV=production
DB_NAME=myapp_prod

各环境命令

# Development (auto-loads docker-compose.override.yml)
docker compose up

# Staging
docker compose -f docker-compose.yml -f docker-compose.staging.yml \
  --env-file .env.staging up -d

# Production
docker compose -f docker-compose.yml -f docker-compose.prod.yml \
  --env-file .env.prod up -d

# Verify resolved config before deploying:
docker compose -f docker-compose.yml -f docker-compose.prod.yml \
  --env-file .env.prod config

安全最佳实践

环境变量对敏感数据本质上不安全。遵循以下实践来最小化风险。

1. 始终 .gitignore 你的 .env 文件

# .gitignore
.env.secrets
.env.local
.env.*.local
secrets/
*.pem
*.key

2. 提交模板,而非真实文件

# .env.secrets.example (committed to git)
# Copy this file to .env.secrets and fill in real values
DB_PASSWORD=
API_KEY=
JWT_SECRET=
SMTP_PASSWORD=
AWS_SECRET_ACCESS_KEY=

# .env.secrets (gitignored — never committed)
DB_PASSWORD=RealSuperSecretP@ssw0rd
API_KEY=sk-prod-abc123xyz789
JWT_SECRET=your-256-bit-secret-here
SMTP_PASSWORD=sendgrid-api-key
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCY

3. 生产环境使用 Docker Secrets

Docker secrets 将敏感数据以文件形式挂载到 /run/secrets/,而不是作为环境变量暴露:

# docker-compose.yml with Docker secrets
services:
  api:
    image: myapp:latest
    secrets:
      - db_password
      - api_key
    environment:
      # App reads secrets from files instead of env vars
      DB_PASSWORD_FILE: /run/secrets/db_password
      API_KEY_FILE: /run/secrets/api_key

  postgres:
    image: postgres:16
    secrets:
      - db_password
    environment:
      # PostgreSQL natively supports _FILE suffix
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt
  api_key:
    file: ./secrets/api_key.txt

4. 注意 docker inspect

环境变量通过 docker inspect 可见。任何有 Docker 访问权限的人都能读取:

# Anyone with Docker access can see ALL environment variables:
docker inspect myapp-api-1 --format '{{range .Config.Env}}{{println .}}{{end}}'

# Output includes secrets if passed via environment:
# DB_PASSWORD=RealSuperSecretP@ssw0rd    <-- EXPOSED!
# API_KEY=sk-prod-abc123xyz789           <-- EXPOSED!

# Docker secrets are NOT visible via inspect.
# They only exist as files inside the container at /run/secrets/

5. 按环境轮换密钥

永远不要在开发、预发布和生产环境使用相同的密码、API 密钥或令牌。为每个环境生成唯一值。

# Generate unique secrets per environment:
# Dev
openssl rand -base64 32 > secrets/dev/db_password.txt
openssl rand -hex 32 > secrets/dev/jwt_secret.txt

# Staging
openssl rand -base64 32 > secrets/staging/db_password.txt
openssl rand -hex 32 > secrets/staging/jwt_secret.txt

# Production
openssl rand -base64 32 > secrets/prod/db_password.txt
openssl rand -hex 32 > secrets/prod/jwt_secret.txt

调试:docker compose config、docker inspect

当环境变量未按预期工作时,使用这些系统化的调试步骤。

步骤1:查看解析后的 Compose 文件

docker compose config 显示所有变量解析后的完整 Compose 文件:

# See the fully resolved docker-compose.yml:
docker compose config

# With a specific env file:
docker compose --env-file .env.prod config

# Show only specific service:
docker compose config --services
docker compose config api

# Output shows all variables with their final values,
# so you can verify interpolation worked correctly.

步骤2:检查容器环境

查看运行中容器内实际设置的所有环境变量:

# List all env vars in a running container:
docker compose exec api env

# Search for a specific variable:
docker compose exec api env | grep DB_HOST

# Or using printenv:
docker compose exec api printenv DB_HOST

步骤3:检查已停止的容器

检查已退出容器的环境变量:

# Inspect a stopped/exited container:
docker inspect myapp-api-1 --format '{{range .Config.Env}}{{println .}}{{end}}'

# Or as JSON:
docker inspect myapp-api-1 --format '{{json .Config.Env}}' | jq .

步骤4:验证 .env 文件位置

.env 文件必须在项目目录中(docker-compose.yml 所在位置)。验证方法:

# Check that .env exists in the right directory:
ls -la .env

# Check Compose project directory:
docker compose ls

# Explicitly specify the env file:
docker compose --env-file ./my-custom.env config

步骤5:检查覆盖

主机 shell 变量会覆盖 .env 值。检查你的 shell 设置了什么:

# Check host shell for conflicting variables:
echo $DB_HOST
echo $NODE_ENV
printenv | grep -i db_

# Unset a conflicting variable:
unset DB_HOST

# Then re-run:
docker compose config

调试命令速查表

CommandPurpose
docker compose configShow resolved Compose file with all variables
docker compose config --format jsonResolved config as JSON (pipe to jq)
docker compose exec <svc> envList env vars inside running container
docker compose exec <svc> printenv VARGet specific variable value
docker inspect <container> --format '{{.Config.Env}}'Env vars of any container (running or stopped)
docker compose --env-file FILE configTest with a specific .env file
docker compose logs <svc> 2>&1 | headCheck for startup errors related to missing vars

常见问题

Docker Compose 中 env_file 和 .env 有什么区别?

env_file 是一个指令,从外部文件将变量直接加载到容器环境中。.env 文件(根级)由 Docker Compose 自动读取,用于 docker-compose.yml 内部的变量替换,但不会将变量注入容器。它们用途不同:env_file 用于容器配置,.env 用于 Compose 文件模板化。

同一服务可以同时使用 environment 和 env_file 吗?

可以,这是一种常见模式。env_file 的变量先加载,然后 environment 的值覆盖任何重复的键。这让你可以在文件中保留默认值,并在行内覆盖特定值。例如,通过 env_file 在 .env.shared 中设置共享配置,然后在 environment 中为特定服务覆盖 DB_HOST。

为什么我的 .env 变量没有到达容器?

根级 .env 文件仅用于 docker-compose.yml 中的 ${} 插值。它不会自动在容器内设置变量。要将 .env 值传入容器,你必须:(1) 使用 env_file 显式指向 .env 文件,或 (2) 使用 environment 配合 ${VAR} 语法进行插值。这是 Docker Compose 环境变量混淆的第一大来源。

如何在 Docker Compose 中不使用环境变量处理密钥?

使用 Docker secrets。在 docker-compose.yml 中定义指向本地文件的密钥,然后授予服务访问权限。密钥以文件形式挂载在容器内的 /run/secrets/<name>。许多官方镜像支持 _FILE 后缀约定(如 POSTGRES_PASSWORD_FILE=/run/secrets/db_password)。这防止密钥出现在 docker inspect、进程列表或日志中。

env_file 支持像 ${VAR} 这样的变量替换吗?

不支持。与 docker-compose.yml 不同,通过 env_file 加载的文件不支持 ${} 变量替换。每行都被视为字面的 KEY=VALUE 对。如果你需要变量展开,请在 environment 指令中使用 ${VAR} 语法定义变量,这些变量会从 .env 或主机 shell 变量中插值。

𝕏 Twitterin LinkedIn
这篇文章有帮助吗?

保持更新

获取每周开发技巧和新工具通知。

无垃圾邮件,随时退订。

试试这些相关工具

\Escape / Unescape🐳Docker Compose GeneratorYMLYAML Validator & Formatter

相关文章

Docker Compose 速查表:服务、卷和网络

Docker Compose 核心参考:服务定义、卷挂载、网络配置、环境变量和常见栈示例。

Docker Compose 密钥和环境变量:正确的做法

掌握 Docker Compose 中的环境变量。.env 文件、env_file 指令、Docker secrets、变量替换和多环境模式。