
1. 为什么需要Docker Compose部署前后端分离项目前后端分离架构已经成为现代Web开发的标准模式但随之而来的部署复杂度却让很多开发者头疼。想象一下这样的场景你需要部署一个VueSpringBoot的电商系统前端需要Node.js环境打包后端需要Java环境运行数据库还要单独配置。传统部署方式就像同时玩三个抛接球稍有不慎就会全盘崩溃。我去年帮朋友部署一个ReactDjango项目时整整花了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.232.2 容器化方案选型为什么选择Docker Compose而不是Kubernetes对于中小型项目学习曲线平缓YAML配置比K8s的manifest简单10倍开发环境友好单机即可运行完整服务拓扑资源消耗低不需要维护控制平面组件经验之谈只有当服务实例超过10个或需要自动扩缩容时才考虑上K8s3. 核心配置文件详解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_HOSTmysql depends_on: - mysql - redis mysql: image: mysql:8.0 volumes: - mysql_data:/var/lib/mysql environment: - MYSQL_ROOT_PASSWORDyourpassword 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_PASSWORDsecure_password_1234. 各服务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 --frombuilder /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 --frombuilder /app/build/libs/*.jar app.jar ENTRYPOINT [java, -jar, app.jar]性能技巧区分JDK和JRE镜像运行时不需要编译工具使用.dockerignore排除*.iml等开发文件JVM参数建议配置-XX:MaxRAMPercentage75.0 -XX:UseContainerSupport5. 网络与通信配置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_URLhttp://backend:80806. 生产环境增强配置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.scrapetrue - prometheus.port8080 - prometheus.path/actuator/prometheus7. 完整部署流程演示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 frontend8. 常见问题排错指南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_healthy8.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_SECRETmysecret volumes: - ./backend:/app9.3 安全加固措施非root用户运行RUN adduser -D myuser USER myuser镜像签名验证docker trust inspect --pretty registry.example.com/myapp网络隔离mysql: networks: - internal_network10. 实际项目案例分享最近用这套方案部署了一个在线教育平台前端Nuxt 3 TailwindCSS后端NestJS Prisma数据库PostgreSQL MongoDB消息队列RabbitMQ关键优点将Monorepo结构拆分为独立服务使用docker-compose.override.yml管理开发配置为每个服务配置资源限制集成Sentry错误监控部署效果开发环境启动时间从45分钟降至3分钟生产环境部署耗时稳定在8分钟左右各服务资源占用下降30%