1. 项目概述
在当今的Web开发领域,前后端分离架构已成为主流选择。这种架构模式将前端展示层与后端业务逻辑彻底解耦,让专业的前端工程师专注于用户界面和交互体验,后端开发者则聚焦于API设计和数据处理。然而,这种架构也带来了部署复杂度的显著提升——需要同时协调前端静态资源服务器、后端应用服务器、数据库服务以及可能的中间件服务。
Docker Compose作为容器编排工具,完美解决了这一痛点。它允许开发者通过一个简单的YAML文件定义多容器应用的拓扑关系,实现一键启动所有关联服务。对于前后端分离项目,这意味着我们可以将Nginx、MySQL、前端静态资源和后端应用打包成标准化的容器镜像,通过一条命令完成整个系统的部署。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与工具选型
2.1 基础环境配置
在开始之前,确保你的开发机或服务器已安装以下组件:
- Docker Engine 20.10.0+
- Docker Compose 2.0.0+
- Git(用于代码版本控制)
对于Linux系统,推荐使用官方脚本安装最新版Docker:
bash复制curl -fsSL https://get.docker.com | sh
sudo systemctl enable --now docker
验证安装是否成功:
bash复制docker --version
docker compose version
2.2 项目结构设计
典型的前后端分离项目在Docker环境下的目录结构应如下:
code复制project-root/
├── frontend/ # 前端项目目录
│ ├── Dockerfile # 前端镜像构建文件
│ ├── dist/ # 构建后的静态资源
│ └── ... # 前端源码
├── backend/ # 后端项目目录
│ ├── Dockerfile # 后端镜像构建文件
│ ├── target/ # Java项目构建输出
│ └── ... # 后端源码
├── nginx/ # Nginx配置目录
│ ├── nginx.conf # 主配置文件
│ └── conf.d/ # 站点配置
├── mysql/ # 数据库相关
│ ├── init.sql # 初始化脚本
│ └── data/ # 数据卷挂载点
└── docker-compose.yml # 编排主文件
3. 核心组件配置详解
3.1 前端容器化配置
以Vue.js项目为例,前端Dockerfile通常采用多阶段构建:
dockerfile复制# 构建阶段
FROM node:16 as builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# 生产阶段
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
关键点说明:
- 使用alpine基础镜像可大幅减小镜像体积(约5MB vs 常规镜像100MB+)
- 静态资源应通过Nginx提供,而非Node.js开发服务器
- 生产环境务必配置正确的缓存策略(如hash文件名+长期缓存)
3.2 后端服务配置
Spring Boot项目的典型Dockerfile:
dockerfile复制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
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]
优化建议:
- 使用JRE基础镜像而非JDK(减少约200MB空间)
- 构建参数中添加--no-daemon可避免Gradle守护进程问题
- 考虑添加JVM内存参数(如-Xmx512m)
3.3 Nginx反向代理配置
nginx/conf.d/app.conf示例:
nginx复制upstream backend {
server backend:8080;
}
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://backend/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
关键配置说明:
- 前端路由需要配置try_files回退到index.html(支持Vue Router的history模式)
- API请求需要添加proxy_set_header保证后端能获取真实客户端IP
- 建议配置gzip压缩(可减少传输体积60%+)
3.4 MySQL服务配置
docker-compose.yml中的MySQL服务定义:
yaml复制services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: appdb
MYSQL_USER: appuser
MYSQL_PASSWORD: userpass
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 10s
retries: 5
数据库优化建议:
- 生产环境应使用自定义配置文件调整缓存大小等参数
- 重要数据卷建议使用命名卷而非主机目录
- 初始化脚本中应包含索引创建和基础数据插入
4. Docker Compose编排实战
4.1 完整编排文件示例
docker-compose.yml核心内容:
yaml复制version: '3.8'
services:
frontend:
build: ./frontend
ports:
- "80:80"
depends_on:
- backend
networks:
- app-network
backend:
build: ./backend
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/appdb
SPRING_DATASOURCE_USERNAME: appuser
SPRING_DATASOURCE_PASSWORD: userpass
depends_on:
mysql:
condition: service_healthy
networks:
- app-network
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: appdb
MYSQL_USER: appuser
MYSQL_PASSWORD: userpass
volumes:
- mysql-data:/var/lib/mysql
networks:
- app-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 10s
retries: 5
networks:
app-network:
driver: bridge
volumes:
mysql-data:
4.2 关键配置解析
-
网络配置:
- 自定义bridge网络实现服务间隔离通信
- 容器间使用服务名直接访问(如backend访问mysql:3306)
-
依赖控制:
- depends_on仅控制启动顺序,不保证服务可用性
- 通过healthcheck实现真正的依赖就绪检测
-
资源管理:
- 可添加deploy.resources限制CPU/内存使用
- 生产环境建议配置restart_policy
4.3 部署与运维命令
启动完整服务栈:
bash复制docker compose up -d --build
查看服务日志:
bash复制docker compose logs -f backend
执行数据库备份:
bash复制docker compose exec mysql sh -c 'exec mysqldump -uappuser -p"$MYSQL_PASSWORD" appdb' > backup.sql
更新前端服务:
bash复制docker compose build frontend
docker compose up -d --no-deps frontend
5. 高级优化技巧
5.1 镜像构建优化
- 利用构建缓存:
dockerfile复制# 优先拷贝依赖声明文件
COPY package.json yarn.lock ./
RUN npm install
# 再拷贝其余源码
COPY . .
- 多阶段构建的进阶用法:
dockerfile复制# 使用专门的目标镜像作为构建器
FROM node:16 as builder
...
# 使用scratch空镜像作为最终基础
FROM scratch
COPY --from=builder /app/dist /
5.2 部署策略优化
蓝绿部署实现方案:
yaml复制services:
frontend-blue:
build: ./frontend
networks:
- app-network
labels:
- "traefik.http.routers.frontend-blue.rule=Host(`example.com`) && Headers(`X-Deployment`, `blue`)"
frontend-green:
build: ./frontend
networks:
- app-network
labels:
- "traefik.http.routers.frontend-green.rule=Host(`example.com`) && Headers(`X-Deployment`, `green`)"
5.3 监控与日志
集成Prometheus监控:
yaml复制services:
backend:
...
environment:
- SPRING_ACTUATOR_METRICS_EXPORT_PROMETHEUS_ENABLED=true
ports:
- "8081:8081" # Actuator端口
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
6. 常见问题排查
6.1 容器启动顺序问题
典型症状:后端服务启动时连接MySQL失败
解决方案:
- 增加健康检查机制
- 后端应用实现连接重试逻辑
- 使用wait-for-it.sh脚本控制启动顺序
6.2 前端路由404问题
解决方案:
nginx复制location / {
try_files $uri $uri/ /index.html;
}
6.3 跨域配置问题
正确做法:
- 开发环境:配置后端CORS
- 生产环境:通过Nginx反向代理统一域名
6.4 数据库持久化问题
验证步骤:
bash复制docker compose down
docker compose up -d
# 检查数据是否保留
7. 生产环境注意事项
-
安全加固:
- 禁止使用latest标签
- 最小化容器权限(--read-only)
- 定期更新基础镜像
-
性能调优:
- Nginx worker_processes设置为CPU核心数
- MySQL配置innodb_buffer_pool_size
- JVM内存参数调优
-
备份策略:
- 数据库定期dump备份
- 重要数据卷使用云存储备份
- 镜像推送到私有仓库
-
监控告警:
- 容器资源使用监控
- 应用健康检查端点
- 日志集中收集分析
