一、基础回顾(快速过一遍)
| Dockerfile | docker-compose.yml | |
|---|---|---|
| 目标 | 构建一个可移植、可复现的镜像 | 描述并管理多个容器如何一起运行 |
| 产出 | 镜像 image | 容器、网络、卷、配置 |
| 生命周期 | 构建时(Build Time) | 运行时(Runtime),本地开发 + 测试环境首选 |
| 典型命令 | docker build | docker compose up / down / logs |
二、它们在不同场景下的职责完全不同
| 场景 | 必须用 Dockerfile ? | 必须用 Compose ? | 说明 |
|---|---|---|---|
| 本地开发运行单服务 | 是 | 否 | 直接 docker run 就行 |
| 本地开发完整系统 | 是 | 强烈推荐 | 用 Compose 一键启动 MySQL、Redis、Nginx 等 |
| 测试环境(Testing) | 是 | 推荐 | 测试经常用 Compose 快速拉起全套依赖 |
| 生产环境(Production) | 是 | 一般不用 | 生产用 Kubernetes、Docker Swarm、ECS、Nomad、CloudRun 等编排工具 |
三、CI/CD 中它们到底怎么配合?(核心重点)
真实生产级 CI/CD 流程是这样的:
代码提交
↓
GitHub Actions / GitLab CI Jenkins 等
↓
1. 单元测试 + 静态检查
↓
2. 用 Dockerfile 构建镜像 ← 这里用 Dockerfile
↓
3. 把镜像推到镜像仓库(Harbor、ECR、GHCR、Docker Hub)
↓
├─→ 4a. 测试/预发布环境:用 docker-compose.yml 拉起全套服务做集成测试
└─ 4b. 生产环境:Kubernetes 用 Helm Chart 或 K8s Manifest 部署(不使用 Compose)
详细拆解每个阶段:
阶段 1:构建阶段(必须用 Dockerfile)
# GitHub Actions 示例片段
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile # ← 必须有
push: true
tags: mycompany/myapp:${{ github.sha }}, mycompany/myapp:latest
这一步只认 Dockerfile,Compose 完全不参与。
阶段 2:集成测试/预发布环境(强烈推荐用 docker-compose.yml)
- name: Start services with Docker Compose
run: docker compose -f docker-compose.ci.yml up -d
- name: Run integration tests
run: npm run test:integration
- name: Stop services
if: always()
run: docker compose -f docker-compose.ci.yml down -v
常见的 docker-compose.ci.yml 会比本地开发版更严格:
version: '3.9'
services:
app:
image: mycompany/myapp:${{ github.sha }} # 直接用刚刚构建的镜像,不再 build
environment:
- NODE_ENV=test
depends_on:
mysql:
condition: service_healthy
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: testdb
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 5s
retries: 10
redis:
image: redis:7-alpine
阶段 3:生产部署(完全抛弃 docker-compose)
生产环境几乎没人直接用 docker compose up 上生产!常见方案:
- Kubernetes(95% 大厂选择)→ 用 Helm Chart 或 kubectl apply
- Docker Swarm(少量)
- 云厂商托管容器服务:阿里云 ACK、AWS ECS Fargate、腾讯云 TKE、Google Cloud Run 等
生产部署通常会把镜像标签改成固定版本:
# Helm values-prod.yaml 片段
image:
repository: mycompany/myapp
tag: "v1.3.2" # 或 ${{ github.sha }}
四、生产级项目目录结构最佳实践
my-project/
├── Dockerfile # 构建生产镜像(多阶段构建)
├── Dockerfile.dev # 可选:本地开发专用轻量镜像
├── docker-compose.yml # 本地开发用
├── docker-compose.override.yml # 本地覆盖(IDE 自动生成)
├── docker-compose.ci.yml # CI 专用(无卷、更严格)
├── docker-compose.prod.yml # 几乎没人用,生产不用 Compose
├── k8s/ # 或 helm-chart/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── ingress.yaml
└── src/
五、进阶:多阶段构建 + Compose 配合示例
# Dockerfile(生产推荐多阶段)
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY package*.json ./
RUN npm ci --only=production
EXPOSE 3000
CMD ["node", "dist/index.js"]
CI 中可以额外加一个 dev 阶段用于本地:
# docker-compose.yml 本地开发
services:
app:
build:
context: .
target: builder # 只构建到 builder 阶段,热重载快
volumes:
- .:/app
- /app/node_modules
ports:
- "3000:3000"
command: npm run dev
六、总结:一句话记住分工
- Dockerfile 是"造车工厂 → 负责生产"标准零件"(镜像),CI/CD 全程必须用到
- docker-compose.yml 是本地试车场 → 只在开发者本地、测试/CI 环境使用,生产环境基本不用
正确姿势是:
本地开发 → docker-compose.yml + Dockerfile CI/CD 构建 → 只用 Dockerfile 打镜像 集成测试 → 用 docker-compose.yml 拉依赖 生产部署 → 用 Kubernetes/云服务,完全丢掉 Compose
这样才算真正玩明白了 Docker 的精髓!