Docker Compose教程#
技术介绍#
Docker Compose是一个用于定义和运行多容器Docker应用程序的工具。通过Docker Compose,您可以使用YAML文件来配置应用程序的服务,然后使用单个命令创建和启动所有服务。Docker Compose简化了多容器应用的开发、测试和部署过程。
Docker Compose核心概念#
- 服务:一个服务对应一个容器,是Docker Compose的基本单位
- 网络:服务之间的通信网络
- 卷:服务的持久化存储
- 环境变量:服务的配置参数
- 配置文件:定义服务、网络和卷的YAML文件
Docker Compose架构#
- Docker Compose CLI:命令行工具,用于管理多容器应用
- Docker Compose文件:YAML格式的配置文件,定义应用的服务、网络和卷
- Docker Engine:Docker引擎,负责运行容器
入门级使用#
安装Docker Compose#
在不同操作系统上安装Docker Compose:
# Linux
curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
# macOS
brew install docker-compose
# Windows
# Docker Desktop for Windows 已经包含了Docker Compose
# 验证安装
docker-compose --version基本Docker Compose命令#
使用Docker Compose的基本命令:
# 查看Docker Compose版本
docker-compose --version
# 启动服务
docker-compose up
# 后台启动服务
docker-compose up -d
# 停止服务
docker-compose down
# 查看服务状态
docker-compose ps
# 查看服务日志
docker-compose logs
# 构建服务
docker-compose build
# 拉取服务镜像
docker-compose pull
# 重启服务
docker-compose restart
# 停止服务
docker-compose stop
# 启动服务
docker-compose start基本Docker Compose文件#
创建基本的Docker Compose文件:
# docker-compose.yml
version: '3'
services:
web:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html
restart: always
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: mydb
MYSQL_USER: user
MYSQL_PASSWORD: password
volumes:
- db_data:/var/lib/mysql
restart: always
volumes:
db_data:运行应用:
# 启动应用
docker-compose up -d
# 查看服务状态
docker-compose ps
# 访问应用
curl http://localhost
# 停止应用
docker-compose down初级使用#
Docker Compose服务配置#
配置Docker Compose服务:
# docker-compose.yml
version: '3'
services:
web:
# 使用构建上下文
build: .
# 或使用指定的Dockerfile
# build:
# context: .
# dockerfile: Dockerfile.dev
# 镜像名称
image: myapp:latest
# 容器名称
container_name: myapp-web
# 端口映射
ports:
- "8080:80"
# 环境变量
environment:
- DEBUG=1
- APP_ENV=development
# 环境变量文件
env_file:
- .env
# 卷挂载
volumes:
- .:/app
- node_modules:/app/node_modules
# 网络
networks:
- mynetwork
# 依赖关系
depends_on:
- db
# 重启策略
restart: unless-stopped
# 资源限制
deploy:
resources:
limits:
cpus: '0.50'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
db:
image: postgres:12
environment:
POSTGRES_DB: mydb
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- mynetwork
volumes:
node_modules:
postgres_data:
networks:
mynetwork:
driver: bridgeDocker Compose网络配置#
配置Docker Compose网络:
# docker-compose.yml
version: '3'
services:
web:
image: nginx:latest
ports:
- "80:80"
networks:
- frontend
api:
image: node:14
networks:
- frontend
- backend
db:
image: mysql:5.7
networks:
- backend
networks:
frontend:
driver: bridge
ipam:
config:
- subnet: 172.18.0.0/16
backend:
driver: bridge
ipam:
config:
- subnet: 172.19.0.0/16Docker Compose卷配置#
配置Docker Compose卷:
# docker-compose.yml
version: '3'
services:
web:
image: nginx:latest
volumes:
# 绑定挂载
- ./html:/usr/share/nginx/html
# 命名卷
- static_files:/app/static
# 临时文件系统
- type: tmpfs
target: /tmp
db:
image: postgres:12
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
static_files:
postgres_data:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/path/to/postgres/data'中级使用#
Docker Compose多环境配置#
使用Docker Compose配置多环境:
# docker-compose.yml (基础配置)
version: '3'
services:
web:
image: myapp:latest
ports:
- "80:80"
volumes:
- .:/app
depends_on:
- db
db:
image: postgres:12
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
# docker-compose.override.yml (开发环境配置)
version: '3'
services:
web:
build: .
environment:
- DEBUG=1
- APP_ENV=development
db:
environment:
- POSTGRES_PASSWORD=dev_password
# docker-compose.prod.yml (生产环境配置)
version: '3'
services:
web:
image: myapp:latest
environment:
- DEBUG=0
- APP_ENV=production
db:
environment:
- POSTGRES_PASSWORD=prod_password
# 使用开发环境配置
docker-compose up -d
# 使用生产环境配置
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -dDocker Compose健康检查#
配置Docker Compose健康检查:
# docker-compose.yml
version: '3'
services:
web:
image: nginx:latest
ports:
- "80:80"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
db:
image: postgres:12
environment:
POSTGRES_PASSWORD: password
healthcheck:
test: ["CMD", "pg_isready", "-U", "postgres"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40sDocker Compose环境变量#
使用Docker Compose环境变量:
# docker-compose.yml
version: '3'
services:
web:
image: myapp:latest
environment:
- DEBUG=${DEBUG:-0}
- APP_ENV=${APP_ENV:-development}
- DATABASE_URL=${DATABASE_URL}
ports:
- "${PORT:-8080}:80"
# .env 文件
DEBUG=1
APP_ENV=development
DATABASE_URL=postgres://user:password@db:5432/mydb
PORT=8080
# 使用环境变量启动服务
docker-compose up -d中上级使用#
Docker Compose构建配置#
配置Docker Compose构建选项:
# docker-compose.yml
version: '3'
services:
web:
build:
context: .
dockerfile: Dockerfile
args:
- NODE_ENV=production
- BUILD_DATE=${BUILD_DATE}
- BUILD_VERSION=${BUILD_VERSION}
image: myapp:${BUILD_VERSION:-latest}
ports:
- "80:80"
# Dockerfile
FROM node:14-alpine
ARG NODE_ENV=production
ARG BUILD_DATE
ARG BUILD_VERSION
ENV NODE_ENV=${NODE_ENV}
LABEL org.label-schema.build-date=${BUILD_DATE}
LABEL org.label-schema.version=${BUILD_VERSION}
WORKDIR /app
COPY package*.json ./
RUN npm install --only=production
COPY . .
EXPOSE 80
CMD ["npm", "start"]
# 构建服务
docker-compose build --build-arg BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") --build-arg BUILD_VERSION=1.0.0Docker Compose网络高级配置#
配置Docker Compose网络高级选项:
# docker-compose.yml
version: '3'
services:
web:
image: nginx:latest
networks:
frontend:
aliases:
- web.local
api:
image: node:14
networks:
frontend:
aliases:
- api.local
backend:
aliases:
- api.backend
db:
image: postgres:12
networks:
backend:
aliases:
- db.backend
networks:
frontend:
driver: bridge
ipam:
config:
- subnet: 172.18.0.0/16
backend:
driver: bridge
internal: true
ipam:
config:
- subnet: 172.19.0.0/16Docker Compose服务扩展#
扩展Docker Compose服务:
# docker-compose.yml
version: '3'
services:
web:
image: nginx:latest
ports:
- "80:80"
deploy:
replicas: 3
worker:
image: myapp:worker
deploy:
replicas: 5
restart_policy:
condition: on-failure
# 使用Docker Swarm部署
docker swarm init
docker-compose up -d
# 扩展服务
docker service scale web=5 worker=10高级使用#
Docker Compose与CI/CD集成#
将Docker Compose与CI/CD集成:
# .gitlab-ci.yml
stages:
- build
- test
- deploy
build:
stage: build
script:
- docker-compose build
- docker-compose push
test:
stage: test
script:
- docker-compose up -d
- docker-compose exec web npm test
- docker-compose down
deploy:
stage: deploy
script:
- docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
only:
- main
# .travis.yml
language: bash
services:
- docker
script:
- docker-compose build
- docker-compose up -d
- docker-compose exec web npm test
- docker-compose down
deploy:
provider: script
script: docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
on:
branch: mainDocker Compose监控#
监控Docker Compose服务:
# docker-compose.yml
version: '3'
services:
web:
image: nginx:latest
ports:
- "80:80"
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
volumes:
grafana_data:
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'docker'
static_configs:
- targets: ['cadvisor:8080']
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']Docker Compose生产部署#
生产环境部署Docker Compose应用:
# docker-compose.yml
version: '3'
services:
web:
image: myapp:latest
ports:
- "80:80"
volumes:
- static_files:/app/static
- media_files:/app/media
environment:
- DEBUG=0
- APP_ENV=production
- DATABASE_URL=postgres://user:password@db:5432/mydb
restart: always
deploy:
resources:
limits:
cpus: '1.0'
memory: 1G
db:
image: postgres:12
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=password
- POSTGRES_USER=user
- POSTGRES_DB=mydb
restart: always
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
redis:
image: redis:6
volumes:
- redis_data:/data
restart: always
deploy:
resources:
limits:
cpus: '0.25'
memory: 256M
volumes:
static_files:
media_files:
postgres_data:
redis_data:
# 生产部署
docker-compose -f docker-compose.yml up -d
# 配置日志轮转
# /etc/logrotate.d/docker-compose
/var/lib/docker/containers/*/*.log {
daily
rotate 7
compress
delaycompress
missingok
copytruncate
}大师级使用#
Docker Compose多阶段部署#
使用Docker Compose进行多阶段部署:
# docker-compose.yml
version: '3'
services:
# 构建阶段
builder:
build:
context: .
dockerfile: Dockerfile.builder
volumes:
- ./dist:/app/dist
# 测试阶段
tester:
build:
context: .
dockerfile: Dockerfile.tester
depends_on:
- builder
- db
volumes:
- ./dist:/app/dist
# 部署阶段
web:
build:
context: .
dockerfile: Dockerfile.prod
ports:
- "80:80"
depends_on:
- db
volumes:
- static_files:/app/static
db:
image: postgres:12
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
static_files:
postgres_data:
# 运行构建和测试
docker-compose run builder
docker-compose run tester
# 部署应用
docker-compose up -d web dbDocker Compose与Kubernetes集成#
将Docker Compose与Kubernetes集成:
# 安装kompose
curl -L https://github.com/kubernetes/kompose/releases/download/v1.22.0/kompose-linux-amd64 -o /usr/local/bin/kompose
chmod +x /usr/local/bin/kompose
# 将Docker Compose文件转换为Kubernetes资源
kompose convert -f docker-compose.yml
# 部署到Kubernetes
kubectl apply -f ./
# 查看部署状态
kubectl get pods
# 或者使用Docker Compose for Kubernetes
docker stack deploy --compose-file docker-compose.yml myappDocker Compose安全最佳实践#
Docker Compose安全最佳实践:
# docker-compose.yml
version: '3'
services:
web:
image: myapp:latest
ports:
- "80:80"
user: "1000:1000"
read_only: true
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
security_opt:
- no-new-privileges:true
volumes:
- static_files:/app/static:ro
- /tmp:/tmp
db:
image: postgres:12
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD_FILE=/run/secrets/postgres_password
secrets:
- postgres_password
secrets:
postgres_password:
file: ./postgres_password.txt
volumes:
static_files:
postgres_data:
# 生成密码
openssl rand -base64 32 > postgres_password.txt
# 启动服务
docker-compose up -d实战案例#
案例一:部署WordPress#
场景:部署一个WordPress网站,包含WordPress和MySQL。
解决方案:使用Docker Compose部署WordPress和MySQL。
实施步骤:
创建Docker Compose文件:
# docker-compose.yml version: '3' services: wordpress: image: wordpress:latest ports: - "80:80" environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DB_NAME: wordpress volumes: - wordpress_data:/var/www/html restart: always db: image: mysql:5.7 environment: MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress MYSQL_ROOT_PASSWORD: root_password volumes: - db_data:/var/lib/mysql restart: always volumes: wordpress_data: db_data:启动服务:
docker-compose up -d访问WordPress:
- 打开浏览器,访问 http://localhost
- 按照WordPress安装向导完成安装
结果:
- 成功部署了WordPress网站
- 配置了MySQL数据库
- WordPress可以正常访问和使用
案例二:部署微服务应用#
场景:部署一个包含前端、后端和数据库的微服务应用。
解决方案:使用Docker Compose部署微服务应用。
实施步骤:
创建Docker Compose文件:
# docker-compose.yml version: '3' services: frontend: build: ./frontend ports: - "3000:3000" depends_on: - backend environment: - REACT_APP_API_URL=http://backend:8000 backend: build: ./backend ports: - "8000:8000" depends_on: - db environment: - DATABASE_URL=postgres://user:password@db:5432/mydb db: image: postgres:12 volumes: - postgres_data:/var/lib/postgresql/data environment: - POSTGRES_PASSWORD=password - POSTGRES_USER=user - POSTGRES_DB=mydb volumes: postgres_data:构建和启动服务:
docker-compose build docker-compose up -d访问应用:
- 前端:http://localhost:3000
- 后端API:http://localhost:8000/api
结果:
- 成功部署了微服务应用
- 配置了前端、后端和数据库服务
- 服务之间可以正常通信
案例三:部署ELK Stack#
场景:部署ELK Stack(Elasticsearch、Logstash、Kibana)用于日志收集和分析。
解决方案:使用Docker Compose部署ELK Stack。
实施步骤:
创建Docker Compose文件:
# docker-compose.yml version: '3' services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:7.10.0 environment: - discovery.type=single-node - ES_JAVA_OPTS=-Xms512m -Xmx512m ports: - "9200:9200" volumes: - es_data:/usr/share/elasticsearch/data logstash: image: docker.elastic.co/logstash/logstash:7.10.0 ports: - "5044:5044" volumes: - ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf depends_on: - elasticsearch kibana: image: docker.elastic.co/kibana/kibana:7.10.0 ports: - "5601:5601" depends_on: - elasticsearch volumes: es_data:创建Logstash配置文件:
# logstash.conf input { beats { port => 5044 } } filter { grok { match => { "message" => "%{COMBINEDAPACHELOG}" } } date { match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ] target => "@timestamp" } } output { elasticsearch { hosts => ["elasticsearch:9200"] index => "logs-%{+YYYY.MM.dd}" } }启动服务:
docker-compose up -d访问Kibana:
- 打开浏览器,访问 http://localhost:5601
- 配置索引模式:logs-*
结果:
- 成功部署了ELK Stack
- 配置了日志收集和分析系统
- 可以通过Kibana查看和分析日志
总结#
Docker Compose是一种强大的工具,通过本教程的学习,您已经掌握了从入门到大师级的Docker Compose使用技术。
主要技术回顾#
- 基础操作:Docker Compose的基本命令和操作
- 服务配置:配置服务的镜像、端口、卷等
- 网络配置:配置服务之间的通信网络
- 存储配置:配置服务的持久化存储
- 环境配置:配置服务的环境变量
- 多环境配置:配置开发、测试和生产环境
- 高级功能:健康检查、构建配置、CI/CD集成
- 企业级应用:生产部署、监控、安全最佳实践
最佳实践#
- 版本控制:将Docker Compose文件纳入版本控制,确保配置的一致性
- 环境变量:使用环境变量和.env文件管理配置,避免硬编码敏感信息
- 健康检查:为服务配置健康检查,确保服务的可用性
- 资源限制:为服务设置资源限制,避免资源争用
- 卷管理:使用命名卷管理数据,避免数据丢失
- 网络隔离:为不同的服务创建独立的网络,提高安全性
- 监控服务:使用Prometheus和Grafana监控服务状态
- 自动化部署:与CI/CD集成,实现自动化构建、测试和部署
- 安全加固:使用非特权容器,配置适当的capabilities,提高安全性
- 文档化:为Docker Compose配置添加注释,提高可维护性
注意事项#
- 版本兼容性:确保Docker Compose文件版本与Docker Engine版本兼容
- 性能优化:根据硬件环境优化服务的资源配置
- 网络配置:合理配置网络,确保服务间通信安全
- 存储管理:定期清理未使用的卷,释放存储空间
- 安全审计:定期进行安全审计,发现和修复安全问题
- 备份策略:制定数据备份策略,确保数据安全
- 灾难恢复:建立灾难恢复计划,应对突发情况
- 依赖管理:明确服务之间的依赖关系,确保服务按正确顺序启动
通过合理学习和使用Docker Compose,您可以显著提高多容器应用的开发、测试和部署效率。Docker Compose已经成为现代微服务架构的标准工具之一,掌握Docker Compose技术将为您的职业发展带来更多机会。