Docker 部署 Java 服务与 Nginx 反向代理

容器能把应用和运行依赖封装成可重复启动的单元,但不代表部署问题自动消失。配置、数据库数据、网络、日志和升级回滚仍要单独设计。本文整理一个适合学习环境的部署思路,不替代生产环境的安全评审。

1. 镜像、容器和持久化数据

镜像是启动容器所需的只读文件和元数据;容器是镜像运行时的隔离进程。容器删除后,容器可写层中的数据可能随之丢失,因此数据库、上传文件等需要使用卷或外部存储持久化。

应用容器尽量保持无状态:配置通过环境变量或受控配置系统注入,数据保存在数据库、对象存储或卷中。不要把密码直接写进镜像层或提交到公开仓库。

2. 构建 Java 应用

先在本地或 CI 中运行构建,得到可执行 JAR,再用 Dockerfile 将运行时与应用文件打包。多阶段构建可以将构建工具与运行镜像分开,减小最终镜像内容。基础镜像应选择维护中的明确版本,并定期更新和重建,不要长期依赖浮动的 latest 标签。

示意 Dockerfile:

1
2
3
4
5
FROM eclipse-temurin:21-jre
WORKDIR /app
COPY target/app.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/app.jar"]

具体 JRE 版本应与项目编译目标一致,正式环境还要按组织要求选择镜像来源、非 root 用户、证书和安全更新策略。

3. 用 Compose 管理本地服务

开发环境可用 Compose 描述应用、MySQL 和 Redis 的网络关系。服务之间通过 Compose 服务名访问,例如应用连接 mysql,而不是容器 IP。数据库数据目录需要绑定持久卷;密码使用本地未提交的环境文件或 Secret 管理。

启动顺序不等于服务已经可用。应用应对数据库连接失败进行重试或快速失败,并配置健康检查和依赖检查。不要在文章或仓库中放真实账号密码。

4. Nginx 反向代理

Nginx 可接收公网 HTTP 请求,再转发给后端应用。它能统一入口、提供 TLS 终止和转发头,但不会自动解决应用权限和服务可用性。

反向代理要正确传递原始 Host、协议和客户端地址等头部;应用应只信任由受控代理添加的转发头,避免客户端伪造。公网防火墙通常只开放必要端口,数据库和 Redis 不应直接暴露给互联网。

5. 日志、卷和升级

  • 日志输出到标准输出,便于容器平台采集;设置轮转和敏感信息过滤。
  • 对数据库卷定期备份并验证恢复流程,持久化不等于备份。
  • 升级前确认数据库迁移兼容性,并保留回滚方案。
  • 监控容器重启、资源用量、健康检查和应用错误率。

6. 小结

一个可维护的部署至少要把应用、配置、持久化数据、网络入口和运维观测分开考虑。先在本机用容器重现依赖关系,再逐步增加 TLS、备份、最小权限和自动化发布。

参考:Docker 容器基础。