🧘 祺祺·技术笔记

← 返回首页

Docker 容器化部署实践:从开发到生产环境

最近将一个基于 Spring Boot 的后端服务以及配套的 Nginx 前端从裸机部署迁移到了 Docker 容器化方案。整个过程中遇到了不少问题,也积累了一些经验,在此做个记录。

一、为什么选择 Docker

此前服务直接运行在服务器宿主机上,环境和依赖都需要手动维护,每次换机器或者重装系统都要重新配置一遍。Docker 的核心优势在于环境一致性——开发环境、测试环境、生产环境使用同一份镜像,避免了"在我机器上能跑"的尴尬。

另外,对于需要多服务协作的项目(比如后端 + Redis + PostgreSQL),docker-compose 可以一键拉起所有依赖,比手动启动各个进程方便得多。

二、Dockerfile 编写要点

以一个 Java Spring Boot 项目为例,以下是 Dockerfile 的核心内容:

FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY target/app.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

几个需要注意的点:

三、docker-compose 多服务编排

项目依赖 PostgreSQL 和 Redis,使用 docker-compose 统一编排:

version: '3.8'
services:
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: appdb
      POSTGRES_USER: app
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app -d appdb"]
      interval: 10s

  redis:
    image: redis:7-alpine
    volumes:
      - redisdata:/data

  app:
    build: .
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_started
    environment:
      SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/appdb
      SPRING_DATA_REDIS_HOST: redis
    ports:
      - "8080:8080"

volumes:
  pgdata:
  redisdata:

这里的 healthcheck 配置很关键。Spring Boot 应用启动时需要数据库已经就绪,通过 depends_on 的 condition: service_healthy 可以确保数据库完全可用后再启动应用,避免应用启动时报数据库连接失败。

四、镜像仓库与 CI/CD 集成

镜像构建好后需要推送到镜像仓库,我使用的是腾讯云 TCR(容器镜像服务)。配合 GitHub Actions,每次推送代码到主分支后自动构建镜像并推送到仓库,然后 SSH 到服务器拉取最新镜像重启容器。

GitHub Actions 工作流中需要注意缓存依赖层,避免每次构建都重新下载 Maven 依赖:

- name: Cache Maven dependencies
  uses: actions/cache@v3
  with:
    path: ~/.m2
    key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}

五、生产环境注意事项

日志管理

容器默认的日志驱动是 json-file,如果不加限制,长时间运行会占用大量磁盘空间。建议限制日志文件大小和数量:

logging:
  driver: "json-file"
  options:
    max-size: "10m"
    max-file: "3"

健康检查

除了数据库的健康检查,应用本身也应当暴露健康检查接口。Spring Boot Actuator 的 /actuator/health 可以配合 Docker 的 HEALTHCHECK 指令使用。

资源限制

生产环境应当对容器做资源限制,避免某个服务异常占用全部资源:

deploy:
  resources:
    limits:
      memory: 512M
    reservations:
      memory: 256M

六、踩坑记录

七、总结

Docker 容器化带来了环境一致性和部署便利性,但也不是银弹。对于简单的单体应用,容器化的收益可能不明显。但一旦项目涉及多服务协作或有 CI/CD 需求,容器化的优势就会体现出来。后续计划引入 Kubernetes 进行更高级的容器编排,届时再做记录分享。