1. 为什么需要Docker Compose部署前后端分离项目
前后端分离架构已经成为现代Web开发的标准模式,但随之而来的部署复杂度却让很多开发者头疼。想象一下这样的场景:你需要部署一个Vue+SpringBoot的电商系统,前端需要Node.js环境打包,后端需要Java环境运行,数据库还要单独配置。传统部署方式就像同时玩三个抛接球,稍有不慎就会全盘崩溃。
我去年帮朋友部署一个React+Django项目时,整整花了2天时间处理环境冲突问题。nginx配置出错导致前端路由失效,Python依赖版本不兼容引发500错误,PostgreSQL连接超时...各种问题接踵而至。直到改用Docker Compose后,部署时间缩短到15分钟,且在任何机器上都能稳定运行。
2. 项目整体架构设计
2.1 典型分离式架构组成
以一个主流技术栈为例:
- 前端:Vue 3 + Vite
- 后端:Spring Boot 2.7 + MyBatis Plus
- 数据库:MySQL 8.0
- 缓存:Redis 6.2
- 代理:Nginx 1.23
2.2 容器化方案选型
为什么选择Docker Compose而不是Kubernetes?对于中小型项目:
- 学习曲线平缓:YAML配置比K8s的manifest简单10倍
- 开发环境友好:单机即可运行完整服务拓扑
- 资源消耗低:不需要维护控制平面组件
经验之谈:只有当服务实例超过10个或需要自动扩缩容时,才考虑上K8s
3. 核心配置文件详解
3.1 docker-compose.yml 骨架
version: '3.8' services: frontend: build: ./frontend ports: - "5173:5173" depends_on: - backend backend: build: ./backend ports: - "8080:8080" environment: - DB_HOST=mysql depends_on: - mysql - redis mysql: image: mysql:8.0 volumes: - mysql_data:/var/lib/mysql environment: - MYSQL_ROOT_PASSWORD=yourpassword redis: image: redis:6.2-alpine volumes: mysql_data:3.2 关键参数解析
depends_on控制启动顺序但不等同于健康检查。实际项目中建议:
healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"] interval: 30s timeout: 10s retries: 3volumes持久化数据特别重要。我曾因忘记配置volume导致测试数据全丢:
volumes: - ./backend/logs:/app/logs - ./mysql/conf:/etc/mysql/conf.denvironment敏感信息应该用env_file:
# .env DB_PASSWORD=secure_password_123
4. 各服务Dockerfile优化技巧
4.1 前端构建最佳实践
# 阶段1:构建 FROM node:16 as builder WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build # 阶段2:运行 FROM nginx:alpine COPY --from=builder /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf避坑指南:
- 使用多阶段构建减小镜像体积(从1.2GB降到23MB)
- 永远不要用
npm install -g,会导致依赖混乱 - 生产环境记得配置nginx缓存策略
4.2 后端Java镜像调优
FROM eclipse-temurin:17-jdk-jammy as builder WORKDIR /app COPY . . RUN ./gradlew bootJar FROM eclipse-temurin:17-jre-jammy WORKDIR /app COPY --from=builder /app/build/libs/*.jar app.jar ENTRYPOINT ["java", "-jar", "app.jar"]性能技巧:
- 区分JDK和JRE镜像,运行时不需要编译工具
- 使用
.dockerignore排除*.iml等开发文件 - JVM参数建议配置:
-XX:MaxRAMPercentage=75.0 -XX:+UseContainerSupport
5. 网络与通信配置
5.1 自定义网络拓扑
默认的bridge网络存在DNS解析问题,建议:
networks: app_network: driver: bridge services: frontend: networks: - app_network backend: networks: - app_network5.2 跨服务通信方案
前端访问后端的三种方式:
- 通过服务名直接访问(推荐)
axios.get('http://backend:8080/api/products') - 使用Nginx反向代理
location /api { proxy_pass http://backend:8080; } - 环境变量注入(适合动态配置)
ENV API_BASE_URL=http://backend:8080
6. 生产环境增强配置
6.1 日志收集方案
backend: logging: driver: "json-file" options: max-size: "10m" max-file: "3"配合ELK栈:
docker run --name filebeat -d \ --volume="/var/lib/docker/containers:/var/lib/docker/containers:ro" \ docker.elastic.co/beats/filebeat:8.3.36.2 监控与告警
Prometheus配置示例:
backend: labels: - "prometheus.scrape=true" - "prometheus.port=8080" - "prometheus.path=/actuator/prometheus"7. 完整部署流程演示
7.1 开发环境启动
# 带日志输出 docker-compose up --build # 后台运行 docker-compose up -d # 查看特定服务日志 docker-compose logs -f backend7.2 生产环境部署
构建镜像并推送到仓库:
docker-compose build docker tag myapp_frontend registry.example.com/myapp:v1 docker push registry.example.com/myapp:v1使用生产配置启动:
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d零停机更新:
docker-compose pull frontend docker-compose up -d --no-deps frontend
8. 常见问题排错指南
8.1 端口冲突解决
错误现象:
Bind for 0.0.0.0:8080 failed: port is already allocated解决方案:
# 查找占用进程 sudo lsof -i :8080 # 或者直接强制重建 docker-compose down && docker-compose up -d8.2 容器启动顺序问题
症状:后端启动时MySQL还未准备好
解决方案:
使用wait-for-it.sh脚本:
COPY wait-for-it.sh /wait-for-it.sh ENTRYPOINT ["/wait-for-it.sh", "mysql:3306", "--", "java", "-jar", "app.jar"]或者用Docker健康检查+depends_on条件:
depends_on: mysql: condition: service_healthy
8.3 磁盘空间不足
定期清理无用资源:
# 删除停止的容器 docker container prune # 删除无用镜像 docker image prune -a # 删除构建缓存 docker builder prune9. 进阶技巧与优化
9.1 多环境配置管理
使用extends语法:
# docker-compose.common.yml services: backend: image: backend env_file: .env # docker-compose.prod.yml services: backend: extends: file: docker-compose.common.yml service: backend deploy: resources: limits: cpus: '2' memory: 1G9.2 本地开发热重载配置
前端开发时挂载源码:
frontend: volumes: - ./frontend/src:/app/src command: npm run devSpring Boot DevTools支持:
backend: environment: - SPRING_DEVTOOLS_REMOTE_SECRET=mysecret volumes: - ./backend:/app9.3 安全加固措施
非root用户运行:
RUN adduser -D myuser USER myuser镜像签名验证:
docker trust inspect --pretty registry.example.com/myapp网络隔离:
mysql: networks: - internal_network
10. 实际项目案例分享
最近用这套方案部署了一个在线教育平台:
- 前端:Nuxt 3 + TailwindCSS
- 后端:NestJS + Prisma
- 数据库:PostgreSQL + MongoDB
- 消息队列:RabbitMQ
关键优���点:
- 将Monorepo结构拆分为独立服务
- 使用docker-compose.override.yml管理开发配置
- 为每个服务配置资源限制
- 集成Sentry错误监控
部署效果:
- 开发环境启动时间从45分钟降至3分钟
- 生产环境部署耗时稳定在8分钟左右
- 各服务资源占用下降30%