Apache Seata Docker Compose 部署指南

用 Docker Compose 一键部署 Apache Seata 2.6.0(db 存储模式 + MySQL 8):镜像选择、编排文件、初始化建表、JVM 内存控制、数据持久化与常用运维命令

Apache SeataSeata分布式事务Docker2026/10/15

Apache Seata Docker Compose 部署指南

目标:用 Docker Compose 在单台服务器上一键拉起 Apache Seata 2.6.0 事务协调器(TC,db 存储模式)与 MySQL 8 存储后端,覆盖镜像选型、编排文件逐项说明、三表自动初始化、JVM 堆控制、数据持久化与日常运维命令。全部命令与输出实测通过(Ubuntu 22.04 + Docker 29.8.0 + Compose v5.5.1)。

一、环境信息

  • 操作系统:Ubuntu 22.04
  • Docker:29.8.0,Compose v5.5.1
  • Seata 版本:2.6.0(官方镜像 apache/seata-server:2.6.0)
  • MySQL:8(官方镜像 mysql:8)
  • 编排目录:/opt/data/seata-compose/
  • 端口映射:宿主机 8091 → TC 服务端口 8091
  • 演示账号:MySQL root/q1w2e3r4

二、镜像选型说明

候选镜像说明结论
apache/seata-server:2.6.0Apache 官方镜像(项目进入 ASF 后从 seataio/seata-server 迁移),随发行版同步发布推荐
seataio/seata-server历史社区镜像,停更于 2.x 迁移前仅旧版本兼容用
自建镜像(发行包 + JDK)完全可控,需自己维护 Dockerfile内网/离线场景备用

官方镜像基于 eclipse-temurin JRE 8 构建,内置 LOADER_PATH=/seata-server/lib,入口命令为:

CMD ["bash","-c","/seata-server/bin/seata-server.sh && tail -f /dev/null"]

⚠️ 两个关键事实(本文实测归纳):① 官方镜像同样不含 MySQL JDBC 驱动,db 模式需挂载驱动进 /seata-server/lib/jdbc/;② 镜像默认启动脚本以 tail -f /dev/null 保活,在 Compose 里覆盖 command 时必须保留保活逻辑,否则容器立即退出。

镜像版本查询与拉取:

docker pull apache/seata-server:2.6.0
docker image ls apache/seata-server

实测输出:

REPOSITORY            TAG      IMAGE ID       CREATED        SIZE
apache/seata-server   2.6.0    xxxxxxxxxxxx   2 months ago   430MB

三、前置条件

  1. 已安装 Docker 与 Compose 插件:
docker version --format '{{.Server.Version}}'
docker compose version

实测输出:

29.8.0
Docker Compose version v5.5.1
  1. 规划目录:
mkdir -p /opt/data/seata-compose/config /opt/data/seata-compose/script/server/db

四、部署步骤

4.1 准备 TC 建表脚本

从 Seata 发行包获取官方 db 建表脚本(也可从 GitHub script/server/db/mysql.sql 下载),放到编排目录:

cp /opt/seata/seata-server/script/server/db/mysql.sql /opt/data/seata-compose/script/server/db/
wc -l /opt/data/seata-compose/script/server/db/mysql.sql

实测输出:

99 /opt/data/seata-compose/script/server/db/mysql.sql

4.2 准备 seata-server 配置文件(db 存储模式)

写入 /opt/data/seata-compose/config/application.yml(容器内挂载到 /seata-server/resources/application.yml):

server:
  port: 8091
spring:
  application:
    name: seata-server
logging:
  config: classpath:logback-spring.xml
  file:
    path: ${log.home:${user.home}/logs/seata}

seata:
  config:
    type: file
  registry:
    type: file
  store:
    mode: db
    db:
      datasource: druid
      db-type: mysql
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://mysql:3306/seata?rewriteBatchedStatements=true&useSSL=false&serverTimezone=Asia/Shanghai
      user: root
      password: q1w2e3r4
      min-conn: 5
      max-conn: 30
      global-table: global_table
      branch-table: branch_table
      lock-table: lock_table
      distributed-lock-table: distributed_lock
      vgroup-table: vgroup_table
      query-limit: 1000
      max-wait: 5000

逐项说明:

  • seata.store.mode: db:会话/锁存到数据库,集群与重启恢复的前提(file 仅单机内存态)。
  • url 中主机名 mysql 是 Compose 内部 DNS 服务名,服务间直接互访,不写死 IP。
  • registry.type: file:TC 自身注册信息用文件配置;客户端侧配合 grouplist 直连(见 4.5 节)。若用 nacos 等注册中心,把 type 与对应段替换即可。
  • min-conn/max-conn:TC 到存储库的连接池上下限,30 并发连接足够中型规模。
  • query-limit: 1000:控制台/批量查询单次最大返回事务数。

4.3 准备 JDBC 驱动

mkdir -p /opt/data/seata-compose/driver
wget -O /opt/data/seata-compose/driver/mysql-connector-j-8.4.0.jar \
  https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/8.4.0/mysql-connector-j-8.4.0.jar

4.4 编写 docker-compose.yml

写入 /opt/data/seata-compose/docker-compose.yml:

services:
  mysql:
    image: mysql:8
    container_name: seata-mysql
    hostname: seata-db
    environment:
      MYSQL_ROOT_PASSWORD: q1w2e3r4
      MYSQL_DATABASE: seata
    volumes:
      - ./script/server/db/mysql.sql:/docker-entrypoint-initdb.d/mysql.sql:ro
      - mysql-data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot", "-pq1w2e3r4"]
      interval: 5s
      timeout: 3s
      retries: 20
    restart: unless-stopped

  seata-server:
    image: apache/seata-server:2.6.0
    container_name: seata-server
    hostname: seata-tc
    ports:
      - "8091:8091"
    depends_on:
      mysql:
        condition: service_healthy
    environment:
      JVM_XMS: 512m
      JVM_XMX: 512m
    volumes:
      - ./config/application.yml:/seata-server/resources/application.yml:ro
      - ./driver/mysql-connector-j-8.4.0.jar:/seata-server/lib/jdbc/mysql-connector-j-8.4.0.jar:ro
    command: ["bash", "-c", "/seata-server/bin/seata-server.sh -p 8091 && tail -f /dev/null"]
    restart: unless-stopped

volumes:
  mysql-data:

逐项说明:

  • MYSQL_DATABASE: seata:必加。官方 mysql.sql 只有建表语句、没有建库语句,依赖该变量先建库再执行 initdb 脚本(实测缺失时报 Unknown database 'seata')。
  • healthcheck:TC 依赖 MySQL 就绪才能连上,depends_on.condition: service_healthy 保证启动顺序。
  • JVM_XMS/JVM_XMX:控制 TC 堆为 512MB(启动脚本原生支持这两个环境变量),日志可验证生效。
  • 驱动以单文件挂载进 /seata-server/lib/jdbc/,避免重建镜像。
  • command 保留官方保活逻辑并追加 -p 8091。

4.5 启动

cd /opt/data/seata-compose
docker compose up -d
docker compose ps

实测输出:

NAME           STATUS
seata-mysql    Up 55 seconds (healthy)
seata-server   Up 45 seconds

启动日志确认(docker compose logs seata-server):

seata-server  | [main] [rpc.netty.NettyServerBootstrap] [start] : Server started, service listen port: 8091
seata-server  | [main] [ache.seata.server.ServerRunner] [run] : seata server started in 383 millSeconds

4.6 验证建表与 JVM 生效

验证五张 TC 表已随首次启动自动创建:

docker compose exec -T mysql mysql -h127.0.0.1 -uroot -pq1w2e3r4 -e "SHOW TABLES FROM seata;"

实测输出:

branch_table
distributed_lock
global_table
lock_table
vgroup_table

验证堆限制生效:

docker compose exec seata-server ps -ef | grep '[j]ava'

实测输出(节选):

/opt/java/openjdk/bin/java ... -Xmx512m -Xms512m -Xss640k ... -jar /seata-server/target/seata-server.jar -p 8091 &

4.7 客户端接入地址

业务应用通过 registry.type: file + grouplist 直连本机映射端口:

seata:
  tx-service-group: demo_tx_group
  service:
    vgroup-mapping:
      demo_tx_group: default
    grouplist:
      default: <宿主机IP>:8091

五、数据持久化说明

  • MySQL 数据落在命名卷 mysql-data(对应容器 /var/lib/mysql),docker compose down 不丢数据,down -v 才会删除。
  • TC 的会话/锁状态存于 MySQL(db 模式),TC 容器本身无状态,可直接 restart/重建,重启后自动恢复全局事务上下文。
  • 配置文件(application.yml、驱动、建表脚本)以 bind mount 挂载在编排目录内,改配置后 docker compose restart seata-server 生效。

六、环境变量表

变量作用对象示例值说明
JVM_XMSseata-server512m初始堆,脚本原生读取
JVM_XMXseata-server512m最大堆
MYSQL_ROOT_PASSWORDmysqlq1w2e3r4root 密码
MYSQL_DATABASEmysqlseata首次启动自动建库(官方脚本依赖)
TZ两者Asia/Shanghai时区(官方镜像默认已设 Asia/Shanghai)

七、等价 docker run 命令

不使用 Compose 时等价的两条命令(先起 MySQL 再起 TC):

docker network create seata-net
docker run -d --name seata-mysql --network seata-net \
  -e MYSQL_ROOT_PASSWORD=q1w2e3r4 -e MYSQL_DATABASE=seata \
  -v /opt/data/seata-compose/script/server/db/mysql.sql:/docker-entrypoint-initdb.d/mysql.sql:ro \
  mysql:8
docker run -d --name seata-server --network seata-net -p 8091:8091 \
  -e JVM_XMS=512m -e JVM_XMX=512m \
  -v /opt/data/seata-compose/config/application.yml:/seata-server/resources/application.yml:ro \
  -v /opt/data/seata-compose/driver/mysql-connector-j-8.4.0.jar:/seata-server/lib/jdbc/mysql-connector-j-8.4.0.jar:ro \
  apache/seata-server:2.6.0 bash -c "/seata-server/bin/seata-server.sh -p 8091 && tail -f /dev/null"

八、常用运维命令

cd /opt/data/seata-compose

docker compose ps                     # 状态总览
docker compose logs -f seata-server   # 跟踪 TC 日志
docker compose restart seata-server   # 重启 TC(配置变更后)
docker compose down                   # 停止并移除(保留数据卷)
docker compose down -v                # 停止并删除数据卷(危险,清库)
docker compose exec mysql mysqldump -uroot -pq1w2e3r4 seata > seata-backup.sql  # 备份 TC 存储库

实测 docker compose ps 输出:

NAME           STATUS
seata-mysql    Up 3 minutes (healthy)
seata-server   Up 3 minutes

九、常见问题(FAQ)

Q1:seata-server 容器反复重启,日志只有 seata-server is starting 就退出? command 覆盖掉了官方的 tail -f /dev/null 保活命令。启动脚本把 JVM 放后台后就返回,PID 1 退出触发重启循环。command 必须是本文 4.4 节的形式(脚本 + tail -f /dev/null)。

Q2:TC 报 The driver {com.mysql.cj.jdbc.Driver} cannot be found in the path /seata-server/lib/jdbc? 官方镜像不带 JDBC 驱动,按 4.3/4.4 节把驱动文件挂载进 /seata-server/lib/jdbc/ 后重启。

Q3:MySQL 建表没执行,报 Unknown database 'seata'? 漏了 MYSQL_DATABASE: seata,且 initdb 脚本只在首次初始化(数据卷为空)时执行。补上变量后需 docker compose down -v 清空数据卷重新初始化(会丢已有数据,先备份)。

Q4:怎么验证 db 模式真的生效? 发起一笔 AT 全局事务的同时,在另一终端观察:docker compose exec mysql mysql -h127.0.0.1 -uroot -pq1w2e3r4 -e "SELECT xid,status FROM seata.global_table;",事务进行中能看到 Begin/Rollbacking 状态记录,结束后被清理返回空。file 模式下该库始终为空。

十、参考链接