第09章:Docker Compose 编排

第09章:Docker Compose 编排 第09章Docker Compose 编排本章目标掌握 Docker Compose 的语法和使用学会编排多容器应用实现一键部署和管理。9.1 Docker Compose 是什么9.1.1 定义与价值Docker Compose 是一个用于定义和运行多容器 Docker 应用的工具。通过一个 YAML 文件你可以配置应用的所有服务、网络和存储卷然后用一个命令创建并启动所有服务。传统方式多个终端分别操作 终端1: docker run -d --name db mysql 终端2: docker run -d --name redis redis 终端3: docker run -d --name app myapp 终端4: docker network connect ... 终端5: docker run -d --name nginx nginx Docker Compose 方式一个文件一条命令 docker compose up -d9.1.2 Compose 的优势优势说明声明式配置一个 YAML 文件描述整个应用架构一键启停docker compose up/down管理所有服务环境隔离每个 compose 项目独立的网络和卷开发/测试/生产同一配置适配不同环境可版本控制compose 文件可以纳入 Git 管理9.2 Compose 文件语法详解9.2.1 文件结构# docker-compose.yml 完整结构version:3.8# Compose 文件版本services:# 服务定义容器配置web:# ... 服务配置db:# ... 服务配置networks:# 自定义网络frontend:backend:volumes:# 声明命名卷db-data:cache-data:configs:# 配置对象app-config:file:./config.ymlsecrets:# 敏感信息db-password:file:./secrets/db_password.txt9.2.2 services 配置详解services:# 服务名称 web-app:# 基本配置image:myapp:latest# 使用镜像# 或从 Dockerfile 构建build:context:.# 构建上下文dockerfile:Dockerfile# Dockerfile 文件名args:# 构建参数VERSION:1.0.0target:production# 多阶段构建的目标阶段container_name:my-web-app# 容器名称hostname:web-server# 主机名restart:unless-stopped# 重启策略# 环境变量environment:-APP_ENVproduction-DB_HOSTdb-DB_PORT3306-REDIS_HOSTredis# 从文件加载环境变量env_file:-.env-.env.production# 端口映射ports:-80:80-443:443# - 127.0.0.1:8080:80 # 仅本地访问# - 8080:80/tcp # 指定协议# 卷挂载volumes:-./src:/app/src:ro# 只读挂载-app-logs:/app/logs# 命名卷-/data/images:/app/images# 绝对路径# 网络networks:-frontend-backend# 资源限制deploy:resources:limits:cpus:2.0memory:1Greservations:cpus:0.5memory:256Mreplicas:2# 副本数restart_policy:condition:on-failuremax_attempts:3# 健康检查healthcheck:test:[CMD,curl,-f,http://localhost:80/health]interval:30stimeout:5sretries:3start_period:10s# 依赖关系depends_on:db:condition:service_healthy# 等待依赖服务健康redis:condition:service_started# 链接旧语法不推荐links:-db-redis# 别名DNS 名称aliases:-web-application# 日志配置logging:driver:json-fileoptions:max-size:10mmax-file:3# 安全选项security_opt:-no-new-privileges:trueread_only:true# 只读文件系统tmpfs:-/tmp-/var/run# 容器内命令command:[python3,app.py]# 或# command: python3 app.py# 入口点entrypoint:[/app/entrypoint.sh]# 工作目录working_dir:/app# 用户user:1000:1000# 其他容器extra_hosts:-other-host:192.168.1.100# PID 模式pid:host# 配置文件configs:-source:app-configtarget:/app/config.ymlmode:04449.2.3 networks 配置详解networks:# 默认 bridge 网络default:driver:bridge# 自定义网络frontend:driver:bridgedriver_opts:com.docker.network.bridge.name:frontend-bripam:driver:defaultconfig:-subnet:192.168.100.0/24gateway:192.168.100.1labels:-com.example.network.frontendtrue# Overlay 网络用于 Swarmbackend:driver:overlayattachable:true# 外部网络使用已存在的网络existing-network:external:true9.2.4 volumes 配置详解volumes:# 命名卷Docker 管理db-data:driver:localdriver_opts:type:nonedevice:/data/mysqlo:bind# 带标签的卷app-logs:labels:com.example.description:Application logscom.example.department:Operations# 外部卷使用已存在的卷existing-volume:external:true# tmpfs 卷temp-cache:driver:localdriver_opts:type:tmpfsdevice:tmpfso:size100m,uid10009.3 Compose 常用命令9.3.1 服务管理# 启动所有服务dockercompose up# 后台启动dockercompose up-d# 重建并启动有变更时dockercompose up-d--build# 停止并删除容器dockercompose down# 停止并删除容器和卷dockercompose down-v# 查看服务状态dockercomposeps# 查看服务日志dockercompose logs# 实时跟踪日志dockercompose logs-f# 查看特定服务日志dockercompose logs-fweb-app# 查看服务资源使用dockercomposetop9.3.2 单个服务操作# 启动特定服务dockercompose up-ddb# 停止特定服务dockercompose stop web-app# 重启特定服务dockercompose restart web-app# 进入服务容器dockercomposeexecweb-appbashdockercomposeexecdb mysql-uroot-p# 查看服务进程dockercomposetopweb-app9.3.3 构建相关# 构建所有服务dockercompose build# 构建特定服务dockercompose build web-app# 不使用缓存构建dockercompose build --no-cache# 拉取最新镜像dockercompose pull# 推送镜像dockercompose push9.3.4 镜像和卷管理# 列出项目中的镜像dockercompose images# 删除停止的容器dockercomposerm# 列出项目中的卷dockercompose volumels# 删除未使用的卷dockercompose down-v9.4 环境变量管理9.4.1 多种设置方式services:web-app:# 方式1直接在 compose 文件中设置environment:APP_ENV:productionDB_HOST:db# 方式2从文件加载env_file:-.env# 方式3使用变量替换compose 文件中image:myapp:${VERSION:-latest}# 方式4在容器内使用command:python3 app.py9.4.2 .env 文件示例# .env 文件APP_ENVproductionAPP_VERSION1.0.0DB_ROOT_PASSWORDsupersecretDB_NAMEmyappDB_USERappuserDB_PASSWORDapppass123REDIS_PASSWORDredis1239.4.3 多环境配置# 项目结构project/ ├── docker-compose.yml# 基础配置├── docker-compose.override.yml# 开发环境覆盖├── docker-compose.prod.yml# 生产环境配置├── .env# 默认环境变量├── .env.dev# 开发环境变量└── .env.prod# 生产环境变量# 开发环境默认dockercompose up-d# 生产环境dockercompose-fdocker-compose.yml-fdocker-compose.prod.yml up-d# 或使用环境变量COMPOSE_FILEdocker-compose.yml:docker-compose.prod.ymldockercompose up-d9.5 完整的多容器应用示例9.5.1 LAMP 架构Linux Apache MySQL PHP# docker-compose.ymlversion:3.8services:# Web 服务器apache:image:php:8.2-apachecontainer_name:lamp-apacheports:-80:80-443:443volumes:-./src:/var/www/html-./apache/conf.d:/etc/apache2/sites-enablednetworks:-lamp-networkdepends_on:mysql:condition:service_healthyenvironment:-DB_HOSTmysql-DB_NAME${DB_NAME:-laravel}-DB_USER${DB_USER:-user}-DB_PASSWORD${DB_PASSWORD:-password}restart:unless-stopped# MySQL 数据库mysql:image:mysql:8.0container_name:lamp-mysqlenvironment:MYSQL_ROOT_PASSWORD:${DB_ROOT_PASSWORD:-rootpassword}MYSQL_DATABASE:${DB_NAME:-laravel}MYSQL_USER:${DB_USER:-user}MYSQL_PASSWORD:${DB_PASSWORD:-password}volumes:-mysql-data:/var/lib/mysql-./mysql/initdb:/docker-entrypoint-initdb.dnetworks:-lamp-networkhealthcheck:test:[CMD,mysqladmin,ping,-h,localhost]interval:10stimeout:5sretries:5restart:unless-stopped# Redis 缓存redis:image:redis:7-alpinecontainer_name:lamp-rediscommand:redis-server--requirepass ${REDIS_PASSWORD:-redis123}volumes:-redis-data:/datanetworks:-lamp-networkhealthcheck:test:[CMD,redis-cli,ping]interval:10stimeout:5sretries:5restart:unless-stoppednetworks:lamp-network:driver:bridgevolumes:mysql-data:redis-data:9.5.2 Python Nginx Gunicorn PostgreSQL Redis# docker-compose.ymlversion:3.8services:# Nginx 反向代理nginx:image:nginx:alpinecontainer_name:app-nginxports:-80:80-443:443volumes:-./nginx/conf.d:/etc/nginx/conf.d:ro-./nginx/ssl:/etc/nginx/ssl:ro-static-files:/app/static:ronetworks:-app-networkdepends_on:-webrestart:unless-stopped# Python Web 应用web:build:context:.dockerfile:Dockerfiletarget:productioncontainer_name:app-webvolumes:-static-files:/app/static-./logs:/app/logsenvironment:-APP_ENVproduction-DATABASE_URLpostgresqlasyncpg://${DB_USER}:${DB_PASSWORD}postgres:5432/${DB_NAME}-REDIS_URLredis://:${REDIS_PASSWORD}redis:6379/0networks:-app-networkdepends_on:postgres:condition:service_healthyredis:condition:service_healthyhealthcheck:test:[CMD,curl,-f,http://localhost:8000/health]interval:30stimeout:5sretries:3restart:unless-stopped# PostgreSQL 数据库postgres:image:postgres:15-alpinecontainer_name:app-postgresenvironment:POSTGRES_DB:${DB_NAME:-myapp}POSTGRES_USER:${DB_USER:-appuser}POSTGRES_PASSWORD:${DB_PASSWORD:-apppass123}PGDATA:/var/lib/postgresql/data/pgdatavolumes:-postgres-data:/var/lib/postgresql/datanetworks:-app-networkhealthcheck:test:[CMD-SHELL,pg_isready -U ${DB_USER:-appuser}]interval:10stimeout:5sretries:5restart:unless-stopped# Redis 缓存redis:image:redis:7-alpinecontainer_name:app-rediscommand:redis-server--requirepass ${REDIS_PASSWORD:-redis123}volumes:-redis-data:/datanetworks:-app-networkhealthcheck:test:[CMD,redis-cli,-a,${REDIS_PASSWORD:-redis123},ping]interval:10stimeout:5sretries:5restart:unless-stoppednetworks:app-network:driver:bridgevolumes:static-files:postgres-data:redis-data:9.5.3 Node.js MongoDB Redis# docker-compose.ymlversion:3.8services:# Node.js 应用app:build:context:.dockerfile:Dockerfilecontainer_name:node-appports:-3000:3000environment:-NODE_ENVproduction-MONGODB_URImongodb://mongo:27017/myapp-REDIS_URLredis://redis:6379volumes:-./uploads:/app/uploadsnetworks:-node-networkdepends_on:mongo:condition:service_healthyredis:condition:service_healthyhealthcheck:test:[CMD,curl,-f,http://localhost:3000/health]interval:30stimeout:5sretries:3restart:unless-stopped# MongoDB 数据库mongo:image:mongo:6container_name:node-mongoenvironment:MONGO_INITDB_ROOT_USERNAME:${MONGO_USER:-admin}MONGO_INITDB_ROOT_PASSWORD:${MONGO_PASSWORD:-password}volumes:-mongo-data:/data/db-mongo-config:/data/configdbnetworks:-node-networkhealthcheck:test:[CMD,mongosh,--eval,db.adminCommand(ping)]interval:10stimeout:5sretries:5restart:unless-stopped# Redis 缓存redis:image:redis:7-alpinecontainer_name:node-rediscommand:redis-server--requirepass ${REDIS_PASSWORD:-redis123}volumes:-redis-data:/datanetworks:-node-networkhealthcheck:test:[CMD,redis-cli,-a,${REDIS_PASSWORD:-redis123},ping]interval:10stimeout:5sretries:5restart:unless-stoppednetworks:node-network:driver:bridgevolumes:mongo-data:mongo-config:redis-data:9.6 Compose 高级特性9.6.1 服务扩缩容# 扩容服务启动多个实例dockercompose up-d--scaleweb3# 缩容dockercompose up-d--scaleweb1# 注意使用 scale 时不要映射固定端口# 应该使用随机端口或负载均衡器9.6.2 服务依赖与启动顺序services:db:image:mysql:8.0# ...redis:image:redis:7# ...web:image:myappdepends_on:db:condition:service_healthy# 等待数据库健康redis:condition:service_started# 只需 Redis 启动# ...9.6.3 配置文件挂载services:nginx:image:nginx:alpineconfigs:-source:nginx-conftarget:/etc/nginx/conf.d/default.confmode:0444configs:nginx-conf:file:./nginx/default.conf9.6.4 敏感信息管理services:db:image:mysql:8.0secrets:-db-passwordenvironment:MYSQL_PASSWORD_FILE:/run/secrets/db-passwordsecrets:db-password:file:./secrets/db_password.txt9.7 动手实验实验 9.1WordPress 一键部署# 创建项目目录mkdir-p~/docker-lab/wordpresscd~/docker-lab/wordpress# 创建 docker-compose.ymlcatdocker-compose.ymlEOF version: 3.8 services: db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: rootpassword MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress volumes: - db-data:/var/lib/mysql healthcheck: test: [CMD, mysqladmin, ping, -h, localhost] interval: 10s timeout: 5s retries: 5 restart: unless-stopped wordpress: image: wordpress:latest ports: - 8080:80 environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DB_NAME: wordpress volumes: - wp-data:/var/www/html depends_on: db: condition: service_healthy restart: unless-stopped volumes: db-data: wp-data: EOF# 启动dockercompose up-d# 访问 http://localhost:8080 完成 WordPress 安装实验 9.2多服务应用# 使用上面的 Python Nginx PostgreSQL Redis 示例cd~/docker-lab# 创建项目结构mkdir-pnginx/conf.d# 创建 Nginx 配置catnginx/conf.d/default.confEOF upstream web { server web:8000; } server { listen 80; server_name localhost; location /static/ { alias /app/static/; } location / { proxy_pass http://web; 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; } } EOF# 启动所有服务dockercompose up-d# 查看服务状态dockercomposeps# 查看日志dockercompose logs-f9.8 本章小结命令说明docker compose up -d后台启动所有服务docker compose down停止并删除所有服务docker compose ps查看服务状态docker compose logs -f实时跟踪日志docker compose exec svc bash进入服务容器docker compose restart svc重启指定服务docker compose build构建服务镜像docker compose pull拉取最新镜像9.9 课后练习基础题使用 Docker Compose 部署 WordPress MySQL。进阶题编写一个包含 Web、数据库、缓存、反向代理的完整 compose 文件。实践题使用多环境配置dev/prod管理不同的部署环境。 下一章企业级镜像仓库 —— 搭建和管理私有镜像仓库