Skip to Content
文档服务器Docker Compose

Docker Compose

Docker Compose 是定义和运行多容器应用的工具。通过一个 YAML 文件描述所有服务,一条命令即可启动整个应用栈。

安装 Docker 和 Docker Compose

安装 Docker Engine

# 卸载旧版本 sudo apt remove docker docker-engine docker.io containerd runc 2>/dev/null # 安装依赖 sudo apt update sudo apt install ca-certificates curl gnupg -y # 添加 Docker 官方 GPG 密钥 sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg # 添加仓库 echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # 安装 Docker Engine(含 Compose 插件) sudo apt update sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y # 将当前用户加入 docker 组(免 sudo) sudo usermod -aG docker $USER newgrp docker # 验证安装 docker --version docker compose version

使用国内镜像加速

sudo tee /etc/docker/daemon.json << 'EOF' { "registry-mirrors": [ "https://mirror.ccs.tencentyun.com", "https://docker.mirrors.ustc.edu.cn" ] } EOF sudo systemctl restart docker

docker-compose.yml 基础

文件结构

# docker-compose.yml # 现代 Docker Compose 已不需要 version 字段(已废弃) services: web: image: nginx:latest ports: - "80:80" volumes: - ./html:/usr/share/nginx/html:ro restart: unless-stopped app: build: ./app environment: - DATABASE_URL=postgres://user:pass@db:5432/mydb depends_on: - db db: image: postgres:16 volumes: - db-data:/var/lib/postgresql/data environment: POSTGRES_USER: user POSTGRES_PASSWORD: pass POSTGRES_DB: mydb volumes: db-data: networks: default: driver: bridge

常用配置项

services: myservice: # 镜像 image: ubuntu:26.04 # 或从 Dockerfile 构建 build: context: ./app dockerfile: Dockerfile args: VERSION: "1.0" # 容器名称 container_name: my-app # 端口映射(宿主:容器) ports: - "8080:80" - "127.0.0.1:3000:3000" # 仅本地访问 # 数据卷 volumes: - ./data:/app/data # 绑定挂载 - app-data:/app/storage # 命名卷 - /etc/localtime:/etc/localtime:ro # 同步时区 # 环境变量 environment: - NODE_ENV=production - SECRET_KEY=mysecret # 或从文件加载 env_file: - .env # 重启策略 restart: unless-stopped # always | on-failure | no # 依赖关系 depends_on: db: condition: service_healthy # 健康检查 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:80"] interval: 30s timeout: 10s retries: 3 start_period: 40s # 资源限制 deploy: resources: limits: cpus: '0.50' memory: 512M reservations: cpus: '0.25' memory: 256M # 网络 networks: - frontend - backend # 日志配置 logging: driver: json-file options: max-size: "10m" max-file: "3"

常用命令

# 启动所有服务(后台运行) docker compose up -d # 查看运行状态 docker compose ps # 查看日志 docker compose logs docker compose logs -f web # 实时跟踪指定服务 docker compose logs --tail=100 # 最后 100 行 # 停止所有服务 docker compose down # 停止并删除数据卷 docker compose down -v # 重新构建镜像 docker compose build docker compose up -d --build # 进入容器 docker compose exec web bash # 运行一次性命令 docker compose run --rm app python manage.py migrate # 扩缩容 docker compose up -d --scale web=3 # 查看资源使用 docker compose top docker stats

常用技术栈示例

LEMP 栈(Nginx + PHP + MySQL)

# docker-compose.yml services: nginx: image: nginx:alpine ports: - "80:80" volumes: - ./src:/var/www/html - ./nginx.conf:/etc/nginx/conf.d/default.conf depends_on: - php restart: unless-stopped php: image: php:8.3-fpm volumes: - ./src:/var/www/html restart: unless-stopped mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: rootpass MYSQL_DATABASE: myapp MYSQL_USER: appuser MYSQL_PASSWORD: apppass volumes: - mysql-data:/var/lib/mysql restart: unless-stopped phpmyadmin: image: phpmyadmin:latest ports: - "8080:80" environment: PMA_HOST: mysql depends_on: - mysql restart: unless-stopped volumes: mysql-data:

WordPress

services: wordpress: image: wordpress:latest ports: - "80:80" environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress_pass WORDPRESS_DB_NAME: wordpress volumes: - wp-content:/var/www/html depends_on: db: condition: service_healthy restart: unless-stopped db: image: mariadb:11 environment: MARIADB_ROOT_PASSWORD: root_pass MARIADB_DATABASE: wordpress MARIADB_USER: wordpress MARIADB_PASSWORD: wordpress_pass volumes: - db-data:/var/lib/mysql healthcheck: test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped volumes: wp-content: db-data:

Gitea + PostgreSQL

services: gitea: image: gitea/gitea:latest ports: - "3000:3000" - "2222:22" environment: - GITEA__database__DB_TYPE=postgres - GITEA__database__HOST=db:5432 - GITEA__database__NAME=gitea - GITEA__database__USER=gitea - GITEA__database__PASSWD=gitea_pass volumes: - gitea-data:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro depends_on: - db restart: unless-stopped db: image: postgres:16-alpine environment: POSTGRES_USER: gitea POSTGRES_PASSWORD: gitea_pass POSTGRES_DB: gitea volumes: - postgres-data:/var/lib/postgresql/data restart: unless-stopped volumes: gitea-data: postgres-data:

监控栈(Prometheus + Grafana)

services: prometheus: image: prom/prometheus:latest ports: - "9090:9090" volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus-data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.retention.time=30d' restart: unless-stopped grafana: image: grafana/grafana:latest ports: - "3000:3000" environment: - GF_SECURITY_ADMIN_USER=admin - GF_SECURITY_ADMIN_PASSWORD=admin_pass volumes: - grafana-data:/var/lib/grafana depends_on: - prometheus restart: unless-stopped node-exporter: image: prom/node-exporter:latest ports: - "9100:9100" volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro - /:/rootfs:ro command: - '--path.procfs=/host/proc' - '--path.sysfs=/host/sys' - '--path.rootfs=/rootfs' restart: unless-stopped volumes: prometheus-data: grafana-data:

使用 .env 文件

# .env 文件(与 docker-compose.yml 同目录) MYSQL_ROOT_PASSWORD=secretpass MYSQL_DATABASE=myapp APP_PORT=8080
# docker-compose.yml 中引用 services: db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: ${MYSQL_DATABASE} app: ports: - "${APP_PORT}:80"

网络配置

services: frontend: networks: - front-tier backend: networks: - front-tier - back-tier db: networks: - back-tier networks: front-tier: driver: bridge back-tier: driver: bridge internal: true # 隔离网络,不可访问外网

数据备份与恢复

# 备份数据卷 docker run --rm -v myproject_db-data:/data -v $(pwd):/backup ubuntu \ tar czf /backup/db-backup-$(date +%Y%m%d).tar.gz -C /data . # 恢复数据卷 docker run --rm -v myproject_db-data:/data -v $(pwd):/backup ubuntu \ bash -c "cd /data && tar xzf /backup/db-backup-20260324.tar.gz" # 数据库导出(以 MySQL 为例) docker compose exec db mysqldump -u root -p myapp > backup.sql # 数据库导入 docker compose exec -T db mysql -u root -p myapp < backup.sql

最佳实践

  1. 版本固定:生产环境中使用固定版本标签(如 nginx:1.27),避免 latest
  2. 环境变量分离:敏感信息放在 .env 文件中,并加入 .gitignore
  3. 健康检查:为关键服务配置 healthcheck,确保依赖服务就绪
  4. 日志限制:配置日志轮转,防止磁盘空间耗尽
  5. 资源限制:使用 deploy.resources 限制 CPU 和内存
  6. 只读挂载:配置文件使用 :ro 只读挂载
  7. 命名卷:使用命名卷而非绑定挂载存储持久数据
  8. 网络隔离:数据库等服务使用 internal 网络,不暴露端口
Last updated on