Docker Compose 部署多个独立 Jar 服务完整实操步骤

Docker Compose 部署多个独立 Jar 服务完整实操步骤

场景说明:一台服务器,同时运行多个 SpringBoot jar(例如:api-gateway.jar、user-service.jar、order-service.jar) 架构: 多个 Java 微服务容器 + Nginx(网关 / 静态前端,可选)+ MySQL + Redis

关键点:

  1. 每个 jar = 独立服务条目
  2. 端口不能冲突,宿主机映射端口区分开
  3. 共用 compose 自动创建的内网网络,容器之间使用服务名互相访问
  4. 每个微服务单独准备 Dockerfile

一、整体目录结构(标准规范)

plaintext

复制代码
deploy/
├── docker-compose.yml
├── .env                     # 统一环境变量:数据库地址、账号密码、配置开关
├── nginx/                   # 可选,前端+反向代理
│   ├── conf.d/
│   └── dist/
├── services/
│   ├── gateway/             # 网关服务1
│   │   ├── Dockerfile
│   │   └── api-gateway.jar
│   ├── user-service/        # 用户服务2
│   │   ├── Dockerfile
│   │   └── user-service.jar
│   └── order-service/       # 订单服务3
│       ├── Dockerfile
│       └── order-service.jar
└── logs/                    # 统一挂载日志目录

二、单个微服务通用 Dockerfile

路径:services/gateway/Dockerfile

所有 jar 服务可以共用一模一样的 Dockerfile,只替换 jar 名称

dockerfile

复制代码
# 使用JDK基础镜像,推荐openjdk17 / 8,和项目编译版本匹配
FROM openjdk:17-jdk-slim

WORKDIR /app

# 拷贝jar包
COPY api-gateway.jar app.jar

# JVM启动参数,生产按需调整
ENTRYPOINT ["java",
"-Xms512m",
"-Xmx1024m",
"-jar",
"app.jar",
"--spring.profiles.active=prod"]

user-service、order-service 目录内 Dockerfile 同理,只修改 COPY 后的 jar 文件名。

三、.env 环境变量文件(推荐)

env

复制代码
# MySQL配置
MYSQL_ROOT_PASSWORD=Root@123456
MYSQL_DATABASE=business_db
MYSQL_USER=appuser
MYSQL_PASSWORD=App@6789

# 各个服务内部端口(容器内端口统一8080,不用改)
# 宿主机对外端口,自行分配,不能重复
GATEWAY_HOST_PORT=8080
USER_HOST_PORT=8081
ORDER_HOST_PORT=8082

四、核心 docker-compose.yml

yaml

复制代码
version: "3.8"

# 全局网络,所有服务自动加入,容器之间通过服务名通信
networks:
  app-net:
    driver: bridge

# 持久化卷
volumes:
  mysql-data:

services:
  # 数据库
  mysql:
    image: mysql:8.0
    restart: always
    networks:
      - app-net
    env_file: .env
    volumes:
      - mysql-data:/var/lib/mysql
      - ./init-sql:/docker-entrypoint-initdb.d  # 数据库初始化脚本
    environment:
      TZ: Asia/Shanghai
    ports:
      - "3306:3306"

  redis:
    image: redis:7-alpine
    restart: always
    networks:
      - app-net
    ports:
      - "6379:6379"
    command: redis-server --requirepass Redis@123

  # 1.网关服务 api-gateway
  gateway:
    build: ./services/gateway
    restart: always
    networks:
      - app-net
    env_file: .env
    ports:
      - "${GATEWAY_HOST_PORT}:8080"
    volumes:
      - ./logs/gateway:/app/logs
    depends_on:
      - mysql
      - redis

  # 2.用户服务 user-service
  user-service:
    build: ./services/user-service
    restart: always
    networks:
      - app-net
    env_file: .env
    ports:
      - "${USER_HOST_PORT}:8080"
    volumes:
      - ./logs/user-service:/app/logs
    depends_on:
      - mysql
      - redis

  # 3.订单服务 order-service
  order-service:
    build: ./services/order-service
    restart: always
    networks:
      - app-net
    env_file: .env
    ports:
      - "${ORDER_HOST_PORT}:8080"
    volumes:
      - ./logs/order-service:/app/logs
    depends_on:
      - mysql
      - redis

  # 可选:Nginx前端反向代理
  nginx:
    image: nginx:alpine
    restart: always
    networks:
      - app-net
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./nginx/dist:/usr/share/nginx/html
      - ./nginx/ssl:/etc/nginx/ssl
    depends_on:
      - gateway

⚠️【重点通信规则】容器内部调用地址

容器内部所有服务不要使用 127.0.0.1 或者宿主机 IP 直接使用 compose 的服务名访问:

  • user-service 访问 mysql → mysql:3306
  • gateway 调用 user 服务 → http://user-service:8080
  • user-service 调用 order 服务 → http://order-service:8080

在 application-prod.yml 配置示例:

yaml

复制代码
spring:
  datasource:
    url: jdbc:mysql://mysql:3306/business_db?useUnicode=true&characterEncoding=utf8mb4
  redis:
    host: redis
    port: 6379

五、完整部署操作步骤

1. 服务器前置条件

已经安装 docker + docker-compose-plugin

bash

复制代码
docker -v
docker compose version

2. 上传文件到服务器

在服务器创建目录 /opt/deploy 把本地整理好的目录全部上传:各个 jar、Dockerfile、yml、.env

3. 首次构建并后台启动整套服务

bash

复制代码
cd /opt/deploy
# --build 首次必须加,构建各个jar服务镜像
docker compose up -d --build

4. 常用日常运维命令

bash

复制代码
# 查看所有运行容器
docker compose ps

# 只查看网关实时日志
docker compose logs -f gateway

# 单独重启某一个服务(升级jar常用)
docker compose restart user-service

# 更新jar包后重新构建并重启单个服务
docker compose up -d --build user-service

# 停止全部服务(保留数据卷)
docker compose stop

# 销毁所有容器(数据库卷默认保留)
docker compose down

# 销毁容器+清空数据库数据(慎用!)
docker compose down -v

六、版本升级标准流程(线上规范)

以更新 user-service.jar 为例

  1. 备份旧 jar 包
  2. 上传新 user-service.jar 替换 services/user-service/ 下文件
  3. 执行构建重启:

bash

复制代码
docker compose up -d --build user-service
  1. 查看日志 docker compose logs -f user-service 确认启动成功
  2. 功能验证,异常立刻换回旧 jar 重新构建

七、高频踩坑点

  1. 宿主机端口冲突 每个服务左侧端口 ${xxx_HOST_PORT} 不能重复;容器内部统一 8080 没关系。

  2. 服务之间连接超时 检查连接地址是否写的服务名 ,不要写localhost

  3. depends_on 只是控制启动顺序,不会等待数据库就绪 解决方案:程序内部增加重连机制,或者使用启动脚本等待 mysql 就绪。

  4. 日志容器内看不到,无法持久化 yml 中配置 volumes 挂载日志目录到宿主机。

  5. 密码硬编码 所有敏感配置统一放到 .env,不要写死在 yml 或 jar 配置文件。

扩展方案选择

  • 如果服务数量很多(>5 个微服务):建议拆分多个 compose 项目或者直接转向 K8s
  • 如果不需要外部直接访问后端服务,可以不映射端口,只让 Nginx/Gateway 容器内网调用,更安全。
相关推荐
heimeiyingwang1 小时前
【架构实战】Kubernetes故障排查全景图:从Pod异常到集群雪崩的诊断手册
容器·架构·kubernetes
AAA@峥2 小时前
K8s 资源管控:ResourceQuota 与 LimitRange 机制详解与实战
云原生·容器·kubernetes
daoihfoaf2 小时前
太原助听器品质甄选
容器
云川之下3 小时前
【k8s】Docker inspect 命令
docker·容器·kubernetes
猫吃了源码5 小时前
CentOS7使用Kubeadm安装部署K8s(Kubernetes)最新稳定版本1.26.x
云原生·容器·kubernetes
倔强的石头1065 小时前
飞牛OS部署Mtab:Docker搭建自托管书签导航并实现远程访问
运维·docker·容器
张忠琳5 小时前
【k3s】AutoK3s v0.9.3 —— Part 7 辅助模块超深度逐行分析
云原生·容器·kubernetes·k3s·autok3s
张忠琳15 小时前
【k3s】AutoK3s v0.9.3 Part 1 入口与 CLI 命令模块 — 超深度逐行分析之三
云原生·容器·kubernetes·k3s·autok3s
apgk120 小时前
基于Canal实现mysql数据同步到消息队列(RabbitMQ/Kafka)详细操作教程
docker·kafka·rabbitmq