别再手动配环境了用Docker Compose一键部署SpringBootVue项目附Nginx配置每次在新服务器部署项目时最头疼的就是重复安装各种依赖环境。Java、Node.js、MySQL、Redis、Nginx...光是版本兼容问题就够折腾半天。更别提不同服务器环境差异导致的在我机器上能跑的经典问题。今天我们就用Docker Compose打造一个真正开箱即用的解决方案只需一个命令就能拉起完整的生产环境。这个方案特别适合需要频繁部署测试环境的开发团队个人开发者管理多个项目需要快速搭建演示环境的场景追求部署一致性的DevOps流程1. 环境准备与项目结构1.1 基础环境检查在开始前确保你的服务器已经安装Docker和Docker Compose。可以通过以下命令验证# 检查Docker版本 docker -v # 检查Docker Compose版本 docker-compose -v如果尚未安装可以参考官方文档快速安装。建议使用较新版本的Docker20.10和Composev2以获得更好的性能和功能支持。1.2 项目目录结构合理的目录结构是高效部署的基础。推荐采用如下组织方式/project-root ├── backend │ ├── Dockerfile │ └── target/server.jar # SpringBoot打包产物 ├── frontend │ └── dist/ # Vue打包后的静态资源 ├── nginx │ ├── nginx.conf │ └── html/ # 前端静态文件实际挂载点 └── docker-compose.yml # 核心编排文件这种结构将前后端分离同时把Nginx配置集中管理非常适合持续集成场景。2. 容器化SpringBoot后端2.1 优化Dockerfile配置传统的Java应用Dockerfile往往简单粗暴我们可以做得更专业# 使用官方精简版JDK镜像 FROM eclipse-temurin:17-jre-jammy # 设置容器内工作目录 WORKDIR /app # 使用分层构建优化镜像大小 COPY target/server.jar /app/server.jar COPY target/lib/* /app/lib/ # 配置JVM参数 ENV JAVA_OPTS-Xms512m -Xmx1024m -XX:UseG1GC # 使用非root用户运行 RUN useradd -m myuser chown -R myuser:myuser /app USER myuser # 健康检查 HEALTHCHECK --interval30s --timeout3s \ CMD curl -f http://localhost:8080/actuator/health || exit 1 EXPOSE 8080 ENTRYPOINT [sh, -c, java ${JAVA_OPTS} -jar server.jar]关键优化点使用更轻量的eclipse-temurin镜像分层构建减少重复构建时的层变更配置合理的JVM参数增加健康检查使用非root用户提升安全性2.2 数据库连接配置在application-prod.properties中使用Docker服务名代替IP地址spring.datasource.urljdbc:mysql://mysql:3306/app_db?useSSLfalse spring.datasource.usernameroot spring.datasource.password${DB_PASSWORD} spring.redis.hostredis spring.redis.port6379这种配置方式使得容器间可以通过服务名直接通信完全解耦IP依赖。3. 编排多服务环境3.1 完整的docker-compose.yml下面是一个功能完备的编排文件示例version: 3.8 services: backend: build: ./backend ports: - 8080:8080 environment: - SPRING_PROFILES_ACTIVEprod - DB_PASSWORDadmin123 depends_on: mysql: condition: service_healthy redis: condition: service_started networks: - app-network frontend: image: nginx:alpine volumes: - ./frontend/dist:/usr/share/nginx/html - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf ports: - 80:80 depends_on: - backend networks: - app-network mysql: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: admin123 MYSQL_DATABASE: app_db volumes: - mysql-data:/var/lib/mysql healthcheck: test: [CMD, mysqladmin, ping, -h, localhost] interval: 5s timeout: 3s retries: 10 networks: - app-network redis: image: redis:alpine command: redis-server --requirepass admin123 volumes: - redis-data:/data networks: - app-network volumes: mysql-data: redis-data: networks: app-network: driver: bridge这个配置实现了自定义桥接网络隔离服务健康检查确保依赖服务就绪数据卷持久化关键数据最小权限原则配置3.2 网络配置技巧默认情况下Compose会为每个项目创建一个独立网络。我们可以利用这个特性实现服务发现容器间直接通过服务名通信端口隔离只有明确暴露的端口才能被外部访问多项目共存不同项目的同名服务不会冲突如果需要跨项目通信可以这样配置networks: shared-network: external: true name: my-shared-network4. 专业级Nginx配置4.1 优化后的nginx.confworker_processes auto; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; # 日志格式 log_format main $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for; access_log /var/log/nginx/access.log main; error_log /var/log/nginx/error.log warn; sendfile on; keepalive_timeout 65; gzip on; gzip_types text/plain text/css application/json application/javascript text/xml; server { listen 80; server_name localhost; # 前端静态资源 location / { root /usr/share/nginx/html; try_files $uri $uri/ /index.html; expires 1y; add_header Cache-Control public; } # API代理 location /api/ { proxy_pass http://backend:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 超时设置 proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; } # 健康检查端点 location /health { access_log off; return 200 OK; } } }这个配置包含了生产环境需要的性能优化gzip、sendfile合理的缓存策略完善的日志记录健壮的超时设置健康检查端点4.2 高级Nginx技巧静态资源版本控制location /static/ { # 开启版本hash支持 rewrite ^/static/(.*)\.[0-9a-f]{8}\.(.*)$ /static/$1.$2 last; expires max; }WebSocket代理location /ws/ { proxy_pass http://backend:8080/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; }限流配置limit_req_zone $binary_remote_addr zoneapi_limit:10m rate10r/s; location /api/ { limit_req zoneapi_limit burst20 nodelay; # 其他代理配置... }5. 部署与运维实践5.1 一键部署命令# 构建并启动所有服务 docker-compose up -d --build # 查看服务状态 docker-compose ps # 查看实时日志 docker-compose logs -f5.2 常用运维操作数据库备份docker exec -it $(docker-compose ps -q mysql) \ mysqldump -u root -padmin123 app_db backup.sql服务更新流程更新前端代码并重新构建更新后端代码并重新打包执行滚动更新# 单独重建前端 docker-compose up -d --build frontend # 单独重建后端 docker-compose up -d --build backend性能监控# 查看容器资源使用情况 docker stats # 查看Java应用内存状态 docker-compose exec backend jstat -gcutil 1 1000 55.3 安全加固建议使用.env文件管理敏感信息# .env文件 DB_PASSWORDcomplex_password_123 REDIS_PASSWORDanother_complex_password然后在docker-compose.yml中引用environment: - DB_PASSWORD${DB_PASSWORD}定期更新基础镜像docker-compose pull限制容器资源deploy: resources: limits: cpus: 1 memory: 1G6. 常见问题排查容器启动顺序问题虽然depends_on可以控制启动顺序但不能保证服务就绪。推荐两种解决方案使用健康检查 depends_on的condition参数如前面示例在应用启动脚本中添加等待逻辑#!/bin/sh # wait-for.sh脚本 until nc -z mysql 3306; do echo Waiting for MySQL... sleep 2 done exec java -jar app.jar时区问题在Dockerfile中设置时区RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime或者在docker-compose.yml中environment: - TZAsia/Shanghai文件权限问题特别是Nginx容器经常遇到权限问题可以在docker-compose.yml中volumes: - ./frontend/dist:/usr/share/nginx/html:ro,z:ro,z表示只读并设置适当的SELinux标签网络连接问题检查容器间通信docker-compose exec backend ping mysql检查端口映射docker-compose port frontend 807. 进阶优化方向7.1 镜像瘦身技巧多阶段构建示例# 构建阶段 FROM maven:3.8.6-eclipse-temurin-17 AS builder WORKDIR /build COPY pom.xml . RUN mvn dependency:go-offline COPY src/ ./src/ RUN mvn package -DskipTests # 运行时阶段 FROM eclipse-temurin:17-jre-jammy COPY --frombuilder /build/target/server.jar /app/server.jar # ...其他配置使用Distroless镜像FROM gcr.io/distroless/java17-debian11 COPY target/server.jar /app/server.jar WORKDIR /app CMD [server.jar]7.2 日志管理方案ELK栈集成services: logstash: image: docker.elastic.co/logstash/logstash:8.5.0 volumes: - ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf ports: - 5000:5000 elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:8.5.0 environment: - discovery.typesingle-node kibana: image: docker.elastic.co/kibana/kibana:8.5.0 ports: - 5601:5601然后在应用配置中输出JSON格式日志通过Logstash收集。7.3 CI/CD集成GitLab CI示例stages: - build - deploy build: stage: build image: docker:20.10 services: - docker:20.10-dind script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - docker-compose -f docker-compose.ci.yml build - docker-compose -f docker-compose.ci.yml push deploy: stage: deploy image: alpine script: - apk add --no-cache openssh-client - ssh $DEPLOY_SERVER cd /opt/app docker-compose pull docker-compose up -d7.4 监控方案Prometheus监控配置services: prometheus: image: prom/prometheus ports: - 9090:9090 volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml grafana: image: grafana/grafana ports: - 3000:3000然后在SpringBoot应用中启用Actuator和Micrometermanagement.endpoints.web.exposure.includehealth,info,prometheus management.metrics.export.prometheus.enabledtrue8. 实际项目经验分享在电商项目中使用这套方案时我们发现几个值得注意的点数据库初始化在mysql服务中添加初始化脚本volumes: - ./init.sql:/docker-entrypoint-initdb.d/init.sql前端环境变量Vue应用需要区分环境变量时可以在Nginx启动前注入FROM nginx:alpine COPY env.sh /docker-entrypoint.d/ RUN chmod x /docker-entrypoint.d/env.sh COPY dist/ /usr/share/nginx/html/env.sh内容#!/bin/sh envsubst /usr/share/nginx/html/assets/env.template.js /usr/share/nginx/html/assets/env.js后端配置热更新使用Spring Cloud Config或直接挂载配置目录volumes: - ./config:/config然后启动命令ENTRYPOINT [java, -jar, /app.jar, --spring.config.location/config/]零停机部署通过traefik或nginx实现蓝绿部署services: backend-v1: # ...配置 labels: - traefik.http.routers.app.rulePathPrefix(/api) - traefik.http.services.app.loadbalancer.server.port8080 backend-v2: # ...新版本配置 deploy: replicas: 0 labels: - traefik.http.routers.app-canary.rulePathPrefix(/api) Headers(X-Canary, true) - traefik.http.services.app-canary.loadbalancer.server.port8080这套方案已经在多个生产环境中稳定运行最大的优势是环境一致性——从开发到生产完全相同的容器环境彻底解决了在我机器上能跑的问题。