当前位置: 首页 > article >正文

Docker Compose实战指南

本文基于 Docker Compose V2所有内容均来自 Docker 官方文档和生产环境实践。全文约 14800 字建议收藏后阅读。读完本文你将从 Docker Compose 新手成长为能够独立部署复杂多容器应用的专家。一、Docker Compose 核心概念与底层原理1.1 什么是 Docker ComposeDocker Compose 是 Docker 官方推出的多容器应用编排工具它允许你使用一个 YAML 文件来定义和运行多个 Docker 容器组成的应用程序。简单来说如果你需要同时运行一个 Web 应用、一个数据库、一个缓存和一个消息队列传统方式需要手动执行多个docker run命令并且还要处理它们之间的网络连接、依赖关系等问题。而 Docker Compose 让你可以在一个文件中定义所有这些服务然后用一条命令启动整个应用栈。Docker Compose 的核心价值一键部署一条命令启动/停止整个应用环境一致性开发、测试、生产环境使用相同的配置依赖管理自动处理服务之间的启动顺序和依赖关系可重复性相同的配置在任何地方都能得到相同的结果声明式配置描述想要什么而不是怎么做1.2 Docker Compose V1 vs V2为什么必须升级到 V2重要提醒Compose V1docker-compose命令已于 2023 年 7 月停止接收更新并且不再包含在新的 Docker Desktop 版本中。所有新的开发和部署都应该使用 Compose V2docker compose命令。特性Compose V1Compose V2命令格式docker-compose带连字符docker compose空格分隔实现语言PythonGo集成方式独立二进制文件Docker CLI 插件性能较慢显著提升特别是构建速度容器命名使用下划线分隔project_service_1使用连字符分隔project-service-1支持状态已弃用官方推荐持续更新BuildKit 支持有限原生支持默认启用升级方法Windows/macOS升级到最新版 Docker Desktop 即可自动获得 Compose V2Linux通过 Docker 官方仓库安装或手动下载二进制文件到$HOME/.docker/cli-plugins/目录1.3 Docker Compose 工作原理Docker Compose 本身不创建容器它只是一个客户端工具通过 Docker API 与 Docker Engine 通信将 Compose 文件中的声明转换为一系列 Docker API 调用。关键底层细节项目ProjectCompose 将一个应用视为一个项目默认使用当前目录的名称作为项目名称。你可以通过--project-name标志或COMPOSE_PROJECT_NAME环境变量覆盖。服务Service项目由多个服务组成每个服务对应一个或多个相同配置的容器。网络隔离Compose 会为每个项目创建一个独立的桥接网络同一项目中的所有服务默认都连接到这个网络并且可以通过服务名称互相访问。数据卷管理Compose 会自动管理命名数据卷确保数据在容器重启或重建时不会丢失。1.4 Docker Compose 的适用场景与局限性适用场景开发环境快速搭建一致的开发环境测试环境自动化测试的环境准备小型到中型生产环境单节点部署CI/CD 流水线构建和测试应用演示和原型快速展示应用功能局限性仅支持单节点部署不支持多节点集群没有内置的服务发现和负载均衡需要配合反向代理没有滚动更新和蓝绿部署功能需要手动实现不适合超大规模应用部署注意对于大规模生产环境应该使用 Kubernetes 而不是 Docker Compose。但对于 90% 的中小型应用Docker Compose 已经足够强大且简单易用。二、docker-compose.yml 文件详解Compose Specification2.1 文件格式与基本结构Compose 文件使用 YAML 格式编写默认文件名是compose.yaml或docker-compose.yml两者都支持推荐使用compose.yaml。重要更新自 Docker Compose v1.27 起version字段已被弃用。现在所有新的 Compose 文件都应该省略version字段直接使用最新的 Compose Specification。基本结构# 顶级元素services必需 services: # 服务1定义 service-name-1: # 服务配置 image: nginx:alpine ports: - 80:80 # 服务2定义 service-name-2: # 服务配置 build: . depends_on: - service-name-1 # 顶级元素networks可选 networks: # 自定义网络定义 my-network: driver: bridge # 顶级元素volumes可选 volumes: # 自定义数据卷定义 my-volume: # 顶级元素configs可选 configs: # 配置文件定义 my-config: file: ./config.conf # 顶级元素secrets可选 secrets: # 敏感信息定义 my-secret: file: ./secret.txt2.2 services 顶级元素详解services是 Compose 文件中唯一必需的顶级元素用于定义应用中的所有服务。每个服务对应一个或多个容器。2.2.1 基本配置image指定服务使用的镜像。services: nginx: image: nginx:1.25-alpine # 推荐使用具体版本不要使用 latestcontainer_name指定容器名称。services: nginx: image: nginx:alpine container_name: my-nginx # 自定义容器名称注意如果指定了container_name则该服务不能进行扩容scale因为容器名称必须是唯一的。command覆盖容器默认的 CMD 指令。services: app: image: node:20-alpine command: npm start # 字符串形式 # 或者数组形式推荐避免 shell 解析问题 command: [npm, start]entrypoint覆盖容器默认的 ENTRYPOINT 指令。services: app: image: node:20-alpine entrypoint: [/app/entrypoint.sh]working_dir设置容器内的工作目录。services: app: image: node:20-alpine working_dir: /appuser指定运行容器内进程的用户。services: app: image: node:20-alpine user: 1000:1000 # UID:GID2.2.2 构建配置build指定从 Dockerfile 构建镜像。# 简单形式指定上下文路径 services: app: build: . # 使用当前目录下的 Dockerfile 构建 # 完整形式 services: app: build: context: ./app # 构建上下文路径 dockerfile: Dockerfile.prod # 指定 Dockerfile 名称 args: # 构建参数 NODE_ENV: production VERSION: 1.0.0 target: production # 多阶段构建的目标阶段 cache_from: # 构建缓存源 - myapp:latest network: host # 构建时使用的网络重要提示构建上下文是 Docker 守护进程可以访问的文件和目录的集合。Docker 会将上下文中的所有文件发送给守护进程因此应该尽量减小上下文大小将不需要的文件添加到.dockerignore中。2.2.3 端口配置ports将容器端口映射到主机端口。services: nginx: image: nginx:alpine ports: - 80:80 # 主机端口:容器端口 - 443:443 - 127.0.0.1:8080:80 # 只绑定到 localhost - 8000-8010:8000-8010 # 端口范围映射 - 9000 # 随机映射主机端口到容器 9000 端口expose暴露端口给同一网络中的其他服务但不映射到主机。services: db: image: postgres:16-alpine expose: - 5432 # 同一网络中的服务可以通过 db:5432 访问2.2.4 环境变量配置environment设置环境变量。services: db: image: postgres:16-alpine environment: # 数组形式 - POSTGRES_DBmyapp - POSTGRES_USERpostgres - POSTGRES_PASSWORDsecret # 或者对象形式推荐 POSTGRES_DB: myapp POSTGRES_USER: postgres POSTGRES_PASSWORD: secretenv_file从文件中加载环境变量。services: app: image: node:20-alpine env_file: - .env # 默认加载 - .env.production # 额外的环境文件最佳实践永远不要在 Compose 文件中硬编码敏感信息如密码、API 密钥等。应该使用.env文件并将.env添加到.gitignore中。对于高度敏感的数据应该使用 Docker Secrets。2.2.5 数据卷配置volumes挂载数据卷或主机目录到容器。services: db: image: postgres:16-alpine volumes: # 命名数据卷推荐由 Docker 管理 - postgres_data:/var/lib/postgresql/data # 绑定挂载主机目录 - ./config:/etc/postgresql/config:ro # 只读挂载 - ./logs:/var/log/postgresql:rw # 读写挂载默认 # tmpfs 挂载临时文件系统存储在内存中 - type: tmpfs target: /tmp tmpfs: size: 100M # 必须在顶级 volumes 中声明命名数据卷 volumes: postgres_data:三种挂载类型对比类型语法特点适用场景命名数据卷volume_name:/container/pathDocker 管理性能好数据持久化数据库数据、应用状态绑定挂载/host/path:/container/path主机目录直接挂载开发时方便开发环境代码挂载、配置文件tmpfstype: tmpfs内存中存储速度快数据不持久临时文件、缓存2.2.6 网络配置networks指定服务连接的网络。services: web: image: nginx:alpine networks: - frontend - backend app: image: node:20-alpine networks: - backend db: image: postgres:16-alpine networks: - backend networks: frontend: backend:重要默认情况下Compose 会创建一个名为{project_name}_default的网络所有服务都会连接到这个网络。只有当你需要网络隔离时才需要自定义网络。network_mode指定网络模式。services: app: image: node:20-alpine network_mode: bridge # 默认 # network_mode: host # 使用主机网络 # network_mode: none # 禁用网络 # network_mode: service:web # 共享另一个服务的网络命名空间2.2.7 依赖关系与启动顺序depends_on指定服务之间的依赖关系决定启动顺序。services: web: image: nginx:alpine depends_on: - app - db app: image: node:20-alpine depends_on: - db - redis db: image: postgres:16-alpine redis: image: redis:7-alpine非常重要的注意事项depends_on只保证容器的启动顺序不保证服务的就绪顺序。也就是说它只会等待容器启动而不会等待容器内的应用程序完全启动并准备好接受请求。例如上面的配置中app服务会在db和redis容器启动后立即启动但此时 PostgreSQL 可能还在初始化过程中无法接受数据库连接导致app服务启动失败。解决方案应用层重试在应用程序中实现数据库连接重试逻辑健康检查使用healthcheck配合depends_on的条件语法等待脚本使用wait-for-it.sh等工具等待依赖服务就绪健康检查配合 depends_on推荐services: app: image: node:20-alpine depends_on: db: condition: service_healthy redis: condition: service_healthy db: image: postgres:16-alpine healthcheck: test: [CMD-SHELL, pg_isready -U postgres] interval: 5s timeout: 5s retries: 5 redis: image: redis:7-alpine healthcheck: test: [CMD, redis-cli, ping] interval: 5s timeout: 5s retries: 52.2.8 重启策略restart指定容器的重启策略。services: app: image: node:20-alpine restart: no # 默认不重启 # restart: always # 总是重启 # restart: on-failure # 仅在失败时重启 # restart: unless-stopped # 除非手动停止否则总是重启**生产环境推荐使用restart: unless-stopped**这样容器在崩溃或 Docker 重启时会自动重启但如果你手动停止了容器它不会自动重启。2.2.9 健康检查healthcheck配置容器的健康检查用于判断容器内的应用是否正常运行。services: web: image: nginx:alpine healthcheck: test: [CMD, curl, -f, http://localhost/health] interval: 30s # 检查间隔 timeout: 10s # 超时时间 retries: 3 # 重试次数 start_period: 30s # 启动后等待多久开始检查 disable: false # 是否禁用健康检查test 命令的三种形式[CMD, command, arg1, arg2]直接执行命令不通过 shell[CMD-SHELL, command arg1 arg2]通过 shell 执行命令command arg1 arg2等同于[CMD-SHELL, command arg1 arg2]2.2.10 资源限制deploy.resources配置容器的资源限制和预留。services: app: image: node:20-alpine deploy: resources: limits: # 资源上限 cpus: 1.0 # 最多使用 1 个 CPU 核心 memory: 512M # 最多使用 512MB 内存 reservations: # 资源预留 cpus: 0.25 # 预留 0.25 个 CPU 核心 memory: 128M # 预留 128MB 内存生产环境必须配置资源限制防止单个容器占用所有主机资源导致其他服务无法运行。2.3 networks 顶级元素详解networks用于定义自定义网络。默认情况下Compose 会创建一个桥接网络但你可以自定义网络的驱动、IP 地址范围等。networks: frontend: driver: bridge # 默认驱动 driver_opts: com.docker.network.bridge.enable_icc: true # 启用容器间通信 backend: driver: bridge ipam: # IP 地址管理 config: - subnet: 172.20.0.0/16 gateway: 172.20.0.1 external-network: external: true # 使用已存在的外部网络 name: my-existing-network # 外部网络的实际名称2.4 volumes 顶级元素详解volumes用于定义命名数据卷。volumes: postgres_data: driver: local # 默认驱动 driver_opts: type: none o: bind device: /data/postgres # 绑定到主机指定目录 redis_data: external: true # 使用已存在的外部数据卷 name: my-existing-redis-volume2.5 configs 与 secrets 顶级元素详解configs和secrets用于管理配置文件和敏感信息避免将它们硬编码在镜像或 Compose 文件中。configs 示例services: nginx: image: nginx:alpine configs: - source: nginx-config target: /etc/nginx/nginx.conf mode: 0444 configs: nginx-config: file: ./nginx.conf # 从文件加载配置secrets 示例services: db: image: postgres:16-alpine secrets: - postgres-password environment: POSTGRES_PASSWORD_FILE: /run/secrets/postgres-password secrets: postgres-password: file: ./postgres-password.txt # 从文件加载密码注意在单机 Docker 环境中secrets 只是简单地将文件挂载到容器的/run/secrets/目录并没有加密。但它仍然比硬编码密码要好因为密码不会出现在 Compose 文件或镜像中。2.6 变量替换与 .env 文件Docker Compose 支持在 Compose 文件中使用环境变量进行变量替换。基本语法services: db: image: postgres:${POSTGRES_VERSION:-16}-alpine environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}变量修饰符${VAR:-default}如果 VAR 未设置或为空使用 default${VAR-default}如果 VAR 未设置使用 default${VAR:?error}如果 VAR 未设置或为空抛出错误并退出${VAR?error}如果 VAR 未设置抛出错误并退出.env 文件Compose 会自动从当前目录下的.env文件加载环境变量。# .env 文件示例 POSTGRES_VERSION16 POSTGRES_DBmyapp POSTGRES_USERpostgres POSTGRES_PASSWORDsupersecretpassword最佳实践提供一个.env.example文件作为模板包含所有必需的环境变量将.env添加到.gitignore中不要提交到版本控制使用不同的.env文件对应不同的环境.env.dev,.env.prod使用${VAR:?error}语法验证必需的环境变量实现快速失败三、Docker Compose 常用命令详解3.1 基本生命周期命令docker compose up创建并启动所有服务。# 前台运行显示所有日志 docker compose up # 后台运行守护进程模式 docker compose up -d # 启动前重新构建镜像 docker compose up --build # 强制重新创建所有容器 docker compose up --force-recreate # 只启动指定的服务 docker compose up -d web dbdocker compose down停止并删除所有服务容器、网络。# 停止并删除容器和网络 docker compose down # 同时删除数据卷谨慎使用会丢失所有数据 docker compose down -v # 同时删除镜像 docker compose down --rmi all # 删除孤立的容器不在 Compose 文件中定义的容器 docker compose down --remove-orphansdocker compose start/stop/restart启动、停止或重启已存在的服务。# 启动所有服务 docker compose start # 启动指定服务 docker compose start web # 停止所有服务 docker compose stop # 停止指定服务 docker compose stop db # 重启所有服务 docker compose restart # 重启指定服务 docker compose restart app3.2 查看与调试命令docker compose ps列出所有服务及其状态。# 列出运行中的服务 docker compose ps # 列出所有服务包括已停止的 docker compose ps -adocker compose logs查看服务日志。# 查看所有服务的日志 docker compose logs # 查看指定服务的日志 docker compose logs web # 实时跟踪日志 docker compose logs -f # 显示最后 N 行日志 docker compose logs --tail100 # 显示日志时间戳 docker compose logs -tdocker compose exec在运行中的容器内执行命令。# 在 app 容器中启动 bash docker compose exec app bash # 以 root 用户执行命令 docker compose exec -u root app bash # 执行一次性命令 docker compose exec db psql -U postgres myappdocker compose run运行一个一次性的服务容器。# 运行 app 服务并执行 npm test docker compose run app npm test # 运行时不启动依赖服务 docker compose run --no-deps app npm test # 运行后自动删除容器 docker compose run --rm app npm testdocker compose exec vs docker compose runexec在已经运行的容器中执行命令run创建一个新的容器并执行命令执行完后容器会停止3.3 构建与镜像命令docker compose build构建服务镜像。# 构建所有服务的镜像 docker compose build # 构建指定服务的镜像 docker compose build app # 不使用缓存构建 docker compose build --no-cache # 构建并拉取最新的基础镜像 docker compose build --pulldocker compose pull拉取服务使用的镜像。# 拉取所有服务的镜像 docker compose pull # 拉取指定服务的镜像 docker compose pull dbdocker compose push推送服务镜像到镜像仓库。# 推送所有服务的镜像 docker compose push # 推送指定服务的镜像 docker compose push app3.4 其他常用命令docker compose config验证并查看合并后的 Compose 配置。# 验证配置是否正确 docker compose config # 查看合并后的完整配置 docker compose config --no-interpolatedocker compose top显示服务容器中运行的进程。# 显示所有服务的进程 docker compose top # 显示指定服务的进程 docker compose top appdocker compose stats显示服务容器的资源使用情况。# 显示所有服务的资源使用情况 docker compose stats # 显示指定服务的资源使用情况 docker compose stats app dbdocker compose scale扩容服务。# 将 app 服务扩容到 3 个实例 docker compose up --scale app3 -d # 或者 docker compose scale app3注意如果服务指定了container_name或ports映射到固定主机端口则不能进行扩容。docker compose watch自动监控文件变化并重新构建和重启服务Compose V2.22。# 启动文件监控 docker compose watch这是开发环境的一个非常有用的功能可以实现代码热重载。四、实战案例从简单到复杂的应用部署4.1 案例一最简单的 Nginx 静态网站文件结构. ├── docker-compose.yml └── html └── index.htmldocker-compose.ymlservices: nginx: image: nginx:1.25-alpine ports: - 80:80 volumes: - ./html:/usr/share/nginx/html:ro restart: unless-stoppedhtml/index.html!DOCTYPE html html head titleHello Docker Compose/title /head body h1Hello Docker Compose!/h1 /body /html启动命令docker compose up -d访问http://localhost即可看到页面。4.2 案例二Node.js PostgreSQL Redis 应用文件结构. ├── .env ├── docker-compose.yml └── app ├── Dockerfile ├── package.json └── server.js.envPOSTGRES_DBmyapp POSTGRES_USERpostgres POSTGRES_PASSWORDsupersecretpassword REDIS_URLredis://redis:6379 DATABASE_URLpostgres://postgres:supersecretpassworddb:5432/myappdocker-compose.ymlservices: app: build: ./app ports: - 3000:3000 environment: DATABASE_URL: ${DATABASE_URL} REDIS_URL: ${REDIS_URL} depends_on: db: condition: service_healthy redis: condition: service_healthy restart: unless-stopped deploy: resources: limits: cpus: 1.0 memory: 512M db: image: postgres:16-alpine environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: [CMD-SHELL, pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}] interval: 5s timeout: 5s retries: 5 restart: unless-stopped redis: image: redis:7-alpine volumes: - redis_data:/data healthcheck: test: [CMD, redis-cli, ping] interval: 5s timeout: 5s retries: 5 restart: unless-stopped volumes: postgres_data: redis_data:app/DockerfileFROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --onlyproduction COPY . . EXPOSE 3000 CMD [node, server.js]启动命令docker compose up -d4.3 案例三带 Nginx 反向代理和 HTTPS 的完整应用文件结构. ├── .env ├── docker-compose.yml ├── nginx │ ├── Dockerfile │ └── nginx.conf ├── certs │ ├── fullchain.pem │ └── privkey.pem └── app ├── Dockerfile └── ...docker-compose.ymlservices: nginx: build: ./nginx ports: - 80:80 - 443:443 volumes: - ./certs:/etc/nginx/certs:ro depends_on: - app restart: unless-stopped networks: - frontend - backend app: build: ./app environment: DATABASE_URL: ${DATABASE_URL} REDIS_URL: ${REDIS_URL} depends_on: db: condition: service_healthy redis: condition: service_healthy restart: unless-stopped networks: - backend deploy: resources: limits: cpus: 1.0 memory: 512M db: image: postgres:16-alpine environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: [CMD-SHELL, pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}] interval: 5s timeout: 5s retries: 5 restart: unless-stopped networks: - backend redis: image: redis:7-alpine volumes: - redis_data:/data healthcheck: test: [CMD, redis-cli, ping] interval: 5s timeout: 5s retries: 5 restart: unless-stopped networks: - backend networks: frontend: backend: volumes: postgres_data: redis_data:nginx/nginx.confevents {} http { server { listen 80; server_name example.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl; server_name example.com; ssl_certificate /etc/nginx/certs/fullchain.pem; ssl_certificate_key /etc/nginx/certs/privkey.pem; location / { proxy_pass http://app:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } }4.4 案例四多环境配置开发/生产使用多个 Compose 文件实现不同环境的配置。基础配置docker-compose.ymlservices: app: build: ./app environment: DATABASE_URL: ${DATABASE_URL} REDIS_URL: ${REDIS_URL} db: image: postgres:16-alpine environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data redis: image: redis:7-alpine volumes: - redis_data:/data volumes: postgres_data: redis_data:开发环境覆盖docker-compose.override.yml默认自动加载services: app: ports: - 3000:3000 volumes: - ./app:/app - /app/node_modules environment: NODE_ENV: development command: npm run dev db: ports: - 5432:5432 redis: ports: - 6379:6379生产环境覆盖docker-compose.prod.ymlservices: nginx: image: nginx:1.25-alpine ports: - 80:80 - 443:443 volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./certs:/etc/nginx/certs:ro depends_on: - app restart: unless-stopped app: environment: NODE_ENV: production restart: unless-stopped deploy: resources: limits: cpus: 1.0 memory: 512M db: restart: unless-stopped healthcheck: test: [CMD-SHELL, pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}] interval: 5s timeout: 5s retries: 5 redis: restart: unless-stopped healthcheck: test: [CMD, redis-cli, ping] interval: 5s timeout: 5s retries: 5启动开发环境docker compose up -d启动生产环境docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d五、高级特性与最佳实践5.1 使用 Profiles 管理可选服务Profiles 允许你定义哪些服务在特定环境下应该启动。services: app: image: node:20-alpine # 总是启动 db: image: postgres:16-alpine # 总是启动 redis: image: redis:7-alpine profiles: [with-redis] # 只有指定 with-redis profile 时才启动 adminer: image: adminer:latest ports: - 8080:8080 profiles: [debug] # 只有指定 debug profile 时才启动启动命令# 只启动 app 和 db docker compose up -d # 启动 app、db 和 redis docker compose --profile with-redis up -d # 启动所有服务 docker compose --profile * up -d5.2 使用 extends 共享配置extends允许你从另一个 Compose 文件或同一文件中的另一个服务继承配置。# base.yml services: base-app: build: ./app environment: NODE_ENV: production restart: unless-stopped deploy: resources: limits: cpus: 1.0 memory: 512M# docker-compose.yml services: app1: extends: file: base.yml service: base-app environment: APP_NAME: app1 app2: extends: file: base.yml service: base-app environment: APP_NAME: app25.3 日志配置最佳实践配置日志驱动和日志轮转services: app: image: node:20-alpine logging: driver: json-file # 默认驱动 options: max-size: 10m # 单个日志文件最大大小 max-file: 3 # 最多保留 3 个日志文件生产环境推荐配置x-logging: default-logging driver: json-file options: max-size: 10m max-file: 3 services: app: image: node:20-alpine logging: *default-logging db: image: postgres:16-alpine logging: *default-logging redis: image: redis:7-alpine logging: *default-logging5.4 安全最佳实践不要以 root 用户运行容器services: app: image: node:20-alpine user: 1000:1000 # 使用非 root 用户使用只读文件系统services: app: image: node:20-alpine read_only: true tmpfs: - /tmp - /app/tmp删除不必要的 capabilitiesservices: app: image: node:20-alpine cap_drop: - ALL不要暴露不必要的端口使用具体的镜像标签不要使用 latest定期更新基础镜像扫描镜像漏洞5.5 性能优化最佳实践使用多阶段构建减小镜像大小合理配置资源限制使用命名数据卷而不是绑定挂载避免在容器中运行多个进程使用缓存加速构建使用 .dockerignore 减小构建上下文六、生产环境部署与运维6.1 生产环境部署清单在将应用部署到生产环境之前请确保你已经完成了以下检查[ ] 所有服务都配置了restart: unless-stopped[ ] 所有关键服务都配置了健康检查[ ] 所有服务都配置了资源限制[ ] 所有持久化数据都使用了命名数据卷[ ] 没有硬编码任何敏感信息[ ] 日志配置了轮转[ ] 应用运行在非 root 用户下[ ] 只暴露了必要的端口[ ] 配置了 HTTPS[ ] 有备份策略[ ] 有监控和告警6.2 备份与恢复备份数据卷# 创建备份容器将数据卷内容打包 docker run --rm \ -v myapp_postgres_data:/data \ -v $(pwd):/backup \ alpine tar czf /backup/postgres_backup_$(date %Y%m%d).tar.gz -C /data .恢复数据卷# 停止相关服务 docker compose stop db # 创建恢复容器将备份内容解压到数据卷 docker run --rm \ -v myapp_postgres_data:/data \ -v $(pwd):/backup \ alpine tar xzf /backup/postgres_backup_20260420.tar.gz -C /data # 启动服务 docker compose start db6.3 滚动更新Docker Compose 本身不支持真正的滚动更新但你可以通过以下方式实现类似的效果# 构建新镜像 docker compose build app # 启动新的容器实例 docker compose up -d --scale app2 --no-recreate # 等待新容器健康检查通过 sleep 30 # 停止旧容器 docker compose stop app-old # 删除旧容器 docker compose rm -f app-old # 缩容回原来的数量 docker compose up -d --scale app1 --no-recreate对于更复杂的更新需求建议使用 Kubernetes。6.4 监控与告警使用 docker stats 监控资源使用docker compose stats使用 Prometheus Grafana 进行全面监控services: prometheus: image: prom/prometheus:latest ports: - 9090:9090 volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml restart: unless-stopped grafana: image: grafana/grafana:latest ports: - 3000:3000 volumes: - grafana_data:/var/lib/grafana restart: unless-stopped volumes: grafana_data:七、常见问题排查与解决方案7.1 端口冲突问题错误信息Error response from daemon: driver failed programming external connectivity on endpoint ...: Bind for 0.0.0.0:80 failed: port is already allocated解决方案查找占用端口的进程sudo lsof -i :80停止占用端口的进程或者修改 Compose 文件中的端口映射7.2 服务启动顺序问题问题描述应用服务在数据库服务准备好之前就启动了导致连接失败。解决方案使用健康检查配合depends_on的条件语法推荐在应用程序中实现重试逻辑使用等待脚本7.3 数据丢失问题问题描述执行docker compose down后数据库数据丢失。原因没有使用命名数据卷而是使用了匿名数据卷。解决方案始终使用命名数据卷存储持久化数据不要轻易使用docker compose down -v它会删除所有数据卷定期备份数据7.4 镜像拉取失败问题解决方案检查网络连接配置镜像加速器登录到私有镜像仓库检查镜像名称和标签是否正确7.5 权限问题错误信息Permission denied: /app/data解决方案确保容器内的用户对挂载的目录有读写权限使用user指令指定与主机目录权限匹配的 UID 和 GID修改主机目录的权限八、总结Docker Compose 是一个非常强大且简单易用的多容器应用编排工具。它通过声明式的配置文件让你可以轻松地定义、运行和管理复杂的多容器应用。 希望本文能够帮助你全面掌握 Docker Compose让你的开发和部署工作更加高效和轻松。如果你觉得本文对你有帮助欢迎点赞、收藏和分享。

相关文章:

Docker Compose实战指南

本文基于 Docker Compose V2,所有内容均来自 Docker 官方文档和生产环境实践。全文约 14800 字,建议收藏后阅读。读完本文,你将从 Docker Compose 新手成长为能够独立部署复杂多容器应用的专家。一、Docker Compose 核心概念与底层原理1.1 什…...

2026届必备的十大降AI率方案推荐

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 对于学术写作以及内容创作而言,要降低AI生成内容能够被识别出来的概率&#xff0…...

手把手教你为STM32移植AK09918磁力计驱动(附Linux驱动对比与源码)

从零构建STM32磁力计驱动:AK09918移植实战与Linux对比 在无人机飞控和智能穿戴设备开发中,地磁传感器是实现方向感知的核心部件。AKM公司的AK09918作为三轴磁力计中的佼佼者,以其高精度和低功耗特性受到嵌入式开发者的青睐。但将这颗传感器成…...

STM32CubeMX LL库串口通信避坑指南:从配置到中断处理的完整流程(基于STM32F103)

STM32CubeMX LL库串口通信避坑指南:从配置到中断处理的完整流程(基于STM32F103) 当你第一次用STM32CubeMX生成LL库串口通信代码时,是否遇到过这样的场景:代码编译一切正常,下载到板子后却发现串口死活不工作…...

告别MCU直连U盘的烦恼:用CH376模块为你的Arduino/ESP32项目轻松扩展USB存储

告别MCU直连U盘的烦恼:用CH376模块为你的Arduino/ESP32项目轻松扩展USB存储 你是否遇到过这样的场景:精心设计的Arduino环境监测站运行了一周,采集了上千组温湿度数据,却因为缺乏本地存储功能而被迫丢弃?或是ESP32摄像…...

SystemVerilog里用disable fork,为啥总把隔壁进程也“误杀”了?

SystemVerilog中disable fork的"误杀"陷阱与精准控制策略 在芯片验证和FPGA开发领域,SystemVerilog的并发进程管理是构建高效测试平台的核心技能之一。许多工程师在使用disable fork时都遭遇过这样的困境:明明只想终止某个特定分支的进程&…...

如何通过Universal Android Debloater实现手机性能翻倍?终极指南揭秘

如何通过Universal Android Debloater实现手机性能翻倍?终极指南揭秘 【免费下载链接】universal-android-debloater Cross-platform GUI written in Rust using ADB to debloat non-rooted android devices. Improve your privacy, the security and battery life …...

从内存泄漏到数据错乱:调试Linux共享内存(shm)程序的3个常见坑与解决方案

从内存泄漏到数据错乱:调试Linux共享内存(shm)程序的3个常见坑与解决方案 在分布式系统和高性能计算领域,共享内存(Shared Memory)作为进程间通信(IPC)的最高效方式之一,被广泛应用于需要低延迟…...

BilibiliDown:三分钟学会下载B站视频的跨平台神器

BilibiliDown:三分钟学会下载B站视频的跨平台神器 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/bi/Bi…...

OBS Advanced Timer终极指南:6种专业计时模式快速上手

OBS Advanced Timer终极指南:6种专业计时模式快速上手 【免费下载链接】obs-advanced-timer 项目地址: https://gitcode.com/gh_mirrors/ob/obs-advanced-timer OBS Advanced Timer是一款功能强大的OBS计时器插件,专门为直播主和内容创作者设计&…...

WarcraftHelper深度解析:专业级魔兽争霸III兼容性与性能优化方案

WarcraftHelper深度解析:专业级魔兽争霸III兼容性与性能优化方案 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 魔兽争霸III作为经典的即…...

Qt Creator项目里集成工业相机SDK,手把手教你配置.pro文件(附避坑点)

Qt Creator工业相机SDK集成实战:从配置到团队协作的最佳实践 工业视觉系统的开发往往需要将硬件厂商提供的相机SDK与Qt框架深度整合。不同于普通的第三方库集成,工业相机SDK通常涉及复杂的设备通信、图像采集和内存管理机制。本文将分享在Qt Creator中高…...

ITK-SNAP医学图像分割:当传统算法遇上现代交互的深度技术融合

ITK-SNAP医学图像分割:当传统算法遇上现代交互的深度技术融合 【免费下载链接】itksnap ITK-SNAP medical image segmentation tool 项目地址: https://gitcode.com/gh_mirrors/it/itksnap 你是否曾面对复杂的医学影像数据,在手动标注的耗时与自动…...

如何在Windows上获得原生级苹果触控板体验:mac-precision-touchpad完整指南

如何在Windows上获得原生级苹果触控板体验:mac-precision-touchpad完整指南 【免费下载链接】mac-precision-touchpad Windows Precision Touchpad Driver Implementation for Apple MacBook / Magic Trackpad 项目地址: https://gitcode.com/gh_mirrors/ma/mac-p…...

3分钟掌握浏览器音高检测:PitchDetect让音乐分析触手可及

3分钟掌握浏览器音高检测:PitchDetect让音乐分析触手可及 【免费下载链接】PitchDetect Pitch detection in Web Audio using autocorrelation 项目地址: https://gitcode.com/gh_mirrors/pi/PitchDetect 在音乐学习、乐器调音或音频分析中,实时获…...

FanControl传感器异常终极解决方案:三步诊断与高效修复指南

FanControl传感器异常终极解决方案:三步诊断与高效修复指南 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trendi…...

避坑指南:解决Docker运行ROS时Gazebo/Rviz黑屏或无法显示的5个关键配置

避坑指南:解决Docker运行ROS时Gazebo/Rviz黑屏或无法显示的5个关键配置 当你在Docker容器中运行ROS时,最令人沮丧的莫过于Gazebo或Rviz窗口无法正常显示。这就像准备了一场精彩的机器人演示,却发现观众席一片漆黑。本文将深入剖析这个常见问…...

如何快速自动化获取和安装Boot Camp驱动:Brigadier终极指南

如何快速自动化获取和安装Boot Camp驱动:Brigadier终极指南 【免费下载链接】brigadier Fetch and install Boot Camp ESDs with ease. 项目地址: https://gitcode.com/gh_mirrors/bri/brigadier Brigadier是一款跨平台智能驱动管理工具,专为Mac设…...

Android虚拟摄像头终极配置指南:5分钟实现视频替换与隐私保护

Android虚拟摄像头终极配置指南:5分钟实现视频替换与隐私保护 【免费下载链接】com.example.vcam 虚拟摄像头 virtual camera 项目地址: https://gitcode.com/gh_mirrors/co/com.example.vcam 还在为直播画面单调而烦恼?想要保护隐私又需要摄像头…...

如何突破Windows应用程序的尺寸限制?WindowResizer的底层技术解析与应用实践

如何突破Windows应用程序的尺寸限制?WindowResizer的底层技术解析与应用实践 【免费下载链接】WindowResizer 一个可以强制调整应用程序窗口大小的工具 项目地址: https://gitcode.com/gh_mirrors/wi/WindowResizer 在Windows生态系统中,应用程序…...

如何高效解锁二手iPhone?applera1n智能激活锁绕过方案深度解析

如何高效解锁二手iPhone?applera1n智能激活锁绕过方案深度解析 【免费下载链接】applera1n icloud bypass for ios 15-16 项目地址: https://gitcode.com/gh_mirrors/ap/applera1n 当您满怀期待地打开新购买的二手iPhone,却遭遇"激活锁"…...

角色设计效率翻倍:Nunchaku FLUX.1 CustomV3实战,快速迭代不同发型与肤质的角色原型

角色设计效率翻倍:Nunchaku FLUX.1 CustomV3实战,快速迭代不同发型与肤质的角色原型 1. 为什么角色设计师需要关注Nunchaku FLUX.1 CustomV3? 在角色设计领域,我们经常面临一个核心挑战:如何在有限时间内快速验证不同…...

CLAP音频分类降本提效:相比微调方案节省90%标注与训练成本

CLAP音频分类降本提效:相比微调方案节省90%标注与训练成本 1. 音频分类的新选择 传统音频分类需要大量标注数据和长时间训练,现在有了更简单的方法。CLAP音频分类技术让你不用标注一张标签,不用训练一分钟模型,就能完成专业级的…...

AGI落地最后一公里卡在哪?SITS2026揭示真相:87.4%的“准AGI”系统在反事实规划任务中F1骤降42.6%,附3步对齐优化路径

第一章:SITS2026发布:AGI能力基准测试 2026奇点智能技术大会(https://ml-summit.org) SITS2026(Singularity Intelligence Test Suite 2026)是首个面向通用人工智能(AGI)系统设计的多模态、跨任务、可演化…...

高效AI专著生成:实测4款工具,3天完成20万字专著写作!

在学术界,撰写一本专著对于研究者来说,绝不是一时冲动的结果,而是需要几年努力的“耐力赛”。从最早的选题阶段,到构建一个逻辑条理清晰的章节结构,再到逐步填充具体内容和校对文献引用,每一步都充满不小的…...

Camera Shakify深度剖析:从真实拍摄到数字动画的抖动艺术

Camera Shakify深度剖析:从真实拍摄到数字动画的抖动艺术 【免费下载链接】camera_shakify 项目地址: https://gitcode.com/gh_mirrors/ca/camera_shakify 在Blender动画创作中,相机运动的真实性往往是区分业余作品与专业作品的关键分水岭。你是…...

瑞芯微(EASY EAI)RV1126B 应用依赖库安装

1. 文件系统依赖库安装 1.1 前言 用户在进行Linux开发的过程中,经常会遇到找不到命令,或者找不到依赖库的问题,这是系统没有预装导致的。 1.2 安装前准备 进入板卡环境,通过命令对板卡进行操作。具体方法可查看《入门指南/调试…...

SAP ABAP开发避坑:用BAPI_OUTB_DELIVERY_CONFIRM_DEC发货过账后,为什么VL09冲销不了?

SAP ABAP开发实战:BAPI发货过账后VL09冲销失败的深度解析与修复方案 在SAP SD/MM模块的日常开发中,交货单的发货过账和冲销操作是供应链管理的关键环节。许多ABAP开发者在实现自定义发货过账逻辑时,会遇到一个令人头疼的问题:使用…...

瑞芯微(EASY EAI)RV1126B 固件版本查询

1. 固件版本查询 在开发板环境执行以下命令,可直接查看当前的固件版本: cat /etc/version 通过此日期,可以找到网盘上发布的,与之一一对应的【固件包】。 固件包可以通过“《固件烧录与更新》1.固件下载”中找到。 2. 固件Id …...

AOT发布失败?Dify API调用崩溃?C# 14原生AOT部署Dify客户端全链路排错手册,含17个IL trimming关键配置项

第一章:C# 14 原生 AOT 部署 Dify 客户端的背景与挑战随着 .NET 8 引入稳定版原生 AOT(Ahead-of-Time)编译能力,C# 14(作为 .NET 9 的配套语言版本)进一步强化了对无运行时依赖、零 GC、超快启动场景的支持…...