使用 docker-compose.yml 进行镜像的高效构建与部署
一份实战向的 Compose 指南,涵盖开发/测试/生产的常用写法、性能优化与团队协作套路。
目标:把“命令行上一长串 docker 命令”沉淀为可维护的
docker-compose.yml,一键完成多容器编排、构建、配置与部署。
1. 快速上手
安装 Docker Desktop(Windows/WSL2、macOS)或 Docker Engine(Linux),确保 docker compose version 可用。
项目根目录新建 docker-compose.yml:
version: "3.9"
services:
api:
build:
context: .
dockerfile: Dockerfile
args:
- PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
image: myorg/myapi:latest
env_file: .env
environment:
- UVICORN_WORKERS=2
ports:
- "8080:8080"
volumes:
- ./app:/app:rw
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 10s
timeout: 3s
retries: 5
restart: unless-stopped
db:
image: postgres:16-alpine
environment:
- POSTGRES_DB=app
- POSTGRES_USER=app
- POSTGRES_PASSWORD=secret
volumes:
- dbdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
volumes:
dbdata: {}
启动/停止:
docker compose up -d
docker compose ps
docker compose logs -f api
docker compose down
2. 常用字段与写法速查
build.context与build.dockerfile:指向构建目录与 Dockerfile。build.args:构建时传参,常用于选择镜像源、依赖版本;可配合 BuildKit 缓存(见下)。image:构建产物的名称与标签;建议“私有镜像仓库 + 语义化标签”。env_file/environment:运行时环境变量;敏感信息放.env或 Secrets(生产)。volumes:挂载代码与数据;开发期启用热重载,生产期只挂载持久化数据。ports:端口映射;生产期更建议接入反向代理(Nginx/Traefik)。depends_on+healthcheck:保证依赖服务健康后再启动主服务。restart:no/on-failure/unless-stopped/always。profiles:按场景启用子集服务(开发/测试/工具)。
示例(按场景切换):
services:
worker:
image: myorg/worker:latest
profiles: ["batch"]
docker compose --profile batch up -d worker
3. Dockerfile 与构建优化
多阶段构建(减少镜像体积):
FROM python:3.11-slim AS base
WORKDIR /app
FROM base AS deps
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
FROM base AS runtime
COPY --from=deps /usr/local /usr/local
COPY app ./app
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"]
启用 BuildKit 与缓存:
export DOCKER_BUILDKIT=1
docker compose build
或在 compose 里声明:
services:
api:
build:
context: .
dockerfile: Dockerfile
cache_from:
- type=registry,ref=myorg/myapi:cache
tags:
- myorg/myapi:cache
4. 开发/测试/生产的分层配置
常见做法:基础 docker-compose.yml + 叠加覆盖文件。
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
docker-compose.dev.yml(热重载、更多日志):
services:
api:
environment:
- LOG_LEVEL=debug
volumes:
- ./app:/app:rw
docker-compose.prod.yml(关闭代码挂载、只暴露网关端口):
services:
api:
volumes: []
ports: []
gateway:
image: traefik:v3.0
command:
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
5. 典型多服务项目模板
version: "3.9"
services:
api:
build: { context: ./backend }
environment:
- DATABASE_URL=postgres://app:secret@db:5432/app
depends_on:
db: { condition: service_healthy }
web:
build: { context: ./frontend }
environment:
- VITE_API_BASE=/api
depends_on: [api]
ports:
- "3000:80"
db:
image: postgres:16-alpine
environment:
- POSTGRES_DB=app
- POSTGRES_USER=app
- POSTGRES_PASSWORD=secret
volumes:
- dbdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 10s
retries: 5
volumes:
dbdata: {}
6. 常见问题与排查
- 端口占用:
docker compose ps查看端口,或修改ports; - 权限问题(Linux/WSL2):为数据卷指定 UID/GID,或在 Dockerfile 中创建专有用户运行;
- 跨平台路径:Windows 下路径分隔符与换行符;建议用相对路径与
.env变量; - 服务未就绪:使用
healthcheck+depends_on(带condition)。
7. 与 CI/CD 集成(示例:GitHub Actions)
# .github/workflows/deploy.yml
name: deploy
on: { push: { branches: [ main ] } }
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
push: true
tags: ghcr.io/myorg/myapi:${{ github.sha }}
服务器上拉起:
IMAGE=ghcr.io/myorg/myapi:$(git rev-parse --short HEAD)
docker compose pull && docker compose up -d