📘 第19课:环境变量

Docker Compose

🔧 环境变量管理

环境变量是容器配置的核心机制,让同一镜像在不同环境(dev/staging/prod)中表现不同行为。

📝 环境变量配置方式

# 方式1:environment直接设置 ✅
services:
  app:
    environment:
      - NODE_ENV=production
      - DB_HOST=db
      - DB_PORT=5432

# 方式2:env_file文件加载 ✅
services:
  app:
    env_file:
      - .env
      - .env.local

# 方式3:从宿主环境变量引用 ✅
services:
  app:
    environment:
      - DB_PASSWORD=${DB_PASSWORD}

📄 .env文件

# .env(项目根目录)✅
COMPOSE_PROJECT_NAME=myapp
POSTGRES_USER=admin
POSTGRES_PASSWORD=secret
POSTGRES_DB=myapp
APP_PORT=3000
IMAGE_TAG=v1.0.0

# .env.production
NODE_ENV=production
LOG_LEVEL=warn
REDIS_MAXMEMORY=512mb

# .env.development
NODE_ENV=development
LOG_LEVEL=debug
REDIS_MAXMEMORY=128mb
# docker-compose.yml使用变量 ✅
services:
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes:
      - pgdata:/var/lib/postgresql/data

  api:
    build:
      context: .
      args:
        VERSION: ${IMAGE_TAG}
    environment:
      NODE_ENV: ${NODE_ENV:-production}     # 默认值
      DB_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}

volumes:
  pgdata:

🔐 敏感信息管理

# Docker Secrets(Swarm模式)✅
services:
  db:
    secrets:
      - db_password
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password

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

# 使用外部密钥管理
# 通过CI/CD在部署时注入环境变量
docker compose --env-file .env.production up -d
⚠️ 安全提醒:①.env文件不要提交到Git——加入.gitignore ②提供.env.example作为模板 ③生产密钥使用专业密钥管理系统(Vault、云KMS)④docker compose config会展开所有变量,注意不要泄露。

🔧 变量优先级

# 优先级从高到低 ✅
1. docker compose run -e VAR=value    # 命令行指定
2. Shell环境变量 export VAR=value     # 宿主环境
3. .env文件                            # 项目根目录
4. docker-compose.yml中的environment   # 文件内定义
5. Dockerfile中的ENV                   # 镜像内定义

# 查看解析后的配置 ✅
docker compose config

❓ 常见问题

❓ .env和env_file有什么区别?.env在项目根目录,用于Compose变量替换(如${VAR}),自动加载。env_file是服务级配置,将变量注入容器环境。两者用途不同:.env配置Compose行为,env_file配置应用运行时。
❓ 如何在不同环境使用不同配置?方案一:多个docker-compose.{env}.yml文件 + docker compose -f docker-compose.yml -f docker-compose.prod.yml up。方案二:多个.env文件 + --env-file参数。推荐方案一,更灵活。

🏆 本课成就

📚 深度补充:环境变量进阶要点

【Compose编排阶段】生产环境注意事项

要点说明最佳实践
资源规划根据业务负载合理分配CPU/内存先压测再上线,设置requests和limits
监控告警设置关键指标阈值和告警规则Prometheus + AlertManager,5分钟P99延迟告警
备份策略定期备份关键数据和配置自动化备份脚本 + 异地存储 + 定期恢复演练
灰度发布新版本逐步放量降低风险金丝雀发布5%→20%→50%→100%
回滚预案部署前确认回滚方案和步骤保留前一版本镜像,数据库迁移向前兼容
文档更新配置变更必须同步更新文档GitOps管理配置,变更即文档
安全基线遵循CIS Docker Benchmark非root运行、只读FS、最小能力
日志规范结构化日志,统一格式JSON格式日志,包含traceId

常见误区与避坑指南

  1. 过度配置:不是所有服务都需要高可用,根据实际需求选择架构复杂度,避免过度工程
  2. 忽略日志:日志是排障的关键,确保日志格式统一、级别合理、采集完整
  3. 资源超卖:容器资源限制不是摆设,超卖会导致性能下降甚至OOM Kill
  4. 安全忽视:默认配置不等于安全配置,生产环境必须加固(非root、只读FS、最小能力)
  5. 监控缺失:没有监控等于盲飞,至少要有基础的健康检查和资源监控
  6. 手动运维:能自动化的绝不手动,手动操作容易出错且不可追溯
  7. 忽略网络策略:默认所有容器互通不安全,应按最小权限原则配置网络

进阶阅读与参考

Docker命令速查卡

# 容器生命周期
docker create/start/stop/restart/rm/pause/unpause
docker logs/top/stats/inspect/exec diff

# 镜像构建
docker build/pull/push/tag/rmi/images/history
docker save/load/import/manifest

# 网络与存储
docker network create/ls/inspect/connect/disconnect/rm/prune
docker volume create/ls/inspect/rm/prune

# Docker Compose
docker compose up/down/ps/logs/build/exec
docker compose config/stop/start/scale/top/cp

# 系统维护
docker system df/prune/info
docker builder prune
docker container/prune/image prune

# K8s常用命令
kubectl get/describe/logs/exec/apply/delete
kubectl rollout status/undo/history
kubectl scale/autoscale/set

本阶段知识脉络

Compose编排阶段知识体系: 核心概念实操演练最佳实践故障排查 每一课都遵循:概念讲解 → 命令实操 → 代码示例 → 常见问题 → 练习巩固 确保学完即能上手,理论实践并重。

Compose文件完整结构

version: "3.8"            # Compose文件版本

services:                  # 服务定义(必填)
  web:
    image: nginx:alpine    # 或 build: .
    ports:
      - "8080:80"
    environment:
      - KEY=VALUE
    volumes:
      - ./html:/usr/share/nginx/html:ro
    networks:
      - frontend
    depends_on:
      - api
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/"]
      interval: 30s
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: '0.5'
          memory: 256M
    restart: unless-stopped

networks:                  # 网络定义
  frontend:
    driver: bridge

volumes:                   # 卷定义
  db-data:

secrets:                   # 密钥定义
  db_password:
    file: ./db_password.txt

configs:                   # 配置定义
  nginx_config:
    file: ./nginx.conf

Compose项目生命周期

开发流程 编写代码 → docker compose up -d --build → 测试 → 修改 → 重建 ↑ ↓ └──────────── 热更新(bind mount)──────────────┘ 部署流程 docker compose build → 推送镜像 → 生产环境 docker compose up -d 清理流程 docker compose down -v ← 清理所有(包括数据卷) docker compose down ← 清理容器和网络(保留数据卷) docker system prune ← 清理所有未使用资源

实战案例:故障排查流程

# Step 1: 检查容器状态
docker ps -a                          # 查看所有容器
docker inspect <container>            # 查看详细配置

# Step 2: 查看日志
docker logs --tail 100 <container>    # 最近100行日志
docker logs --since 1h <container>    # 最近1小时

# Step 3: 进入容器排查
docker exec -it <container> sh        # 进入容器shell

# Step 4: 检查资源
docker stats --no-stream              # 资源使用概览
docker system df                      # 磁盘使用

# Step 5: 网络排查
docker network ls                     # 网络列表
docker exec <c> ping <target>        # 网络连通性
docker exec <c> nslookup <svc>       # DNS解析

# Step 6: 检查健康状态
docker inspect --format '{{.State.Health}}' <c>
docker inspect --format '{{.State.ExitCode}}' <c>
docker inspect --format '{{.State.OOMKilled}}' <c>

Dockerfile模板:多语言通用

# 通用最佳实践模板
FROM alpine:3.19 AS builder
# ... 构建步骤 ...

FROM alpine:3.19
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY --from=builder /app/output .
USER appuser
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD wget -qO- http://localhost:8080/health || exit 1
EXPOSE 8080
CMD ["./app"]

Docker Compose健康检查模板

services:
  app:
    build: .
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:8080/health"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 30s
    restart: unless-stopped
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 512M

性能调优要点

调优方向具体措施预期效果
镜像构建多阶段构建+缓存优化构建时间减少50%+
容器启动小镜像+健康检查优化启动时间减少30%+
网络性能host模式或优化bridge延迟降低20%+
存储性能Volume替代bind mountIO性能提升10-30%
内存使用限制+请求合理配置避免OOM和资源浪费
CPU调度cpuset绑定+shares权重关键服务优先调度