Seata 1.8.0 Docker 部署方案(MySQL 存储 + Nacos 鉴权)
0. 版本与组件说明
- 服务端镜像:
seataio/seata-server:1.8.0(Seata 1.x 末版官方镜像,基于 openjdk8) - 端口:
8091(TC 通信,Netty)、7091(管控台 HTTP,1.5+ 引入) - 存储:MySQL(
store.mode=db) - 注册中心:Nacos(type=nacos)
- 配置中心:Nacos(type=nacos,data-id 推荐
seata.properties) - 安全:1.8.0 控制台默认账号
seata/seata,本方案在application.yml中覆盖为自定义账号
部署架构
flowchart LRClient[业务微服务<br/>seata-client]subgraph Host[Linux 宿主机 SERVER_IP]Docker[seataio/seata-server:1.8.0<br/>8091 TC / 7091 Console]endNacos[(Nacos<br/>注册 + 配置中心)]MySQL[(MySQL<br/>seata_server)]Docker -->|注册| NacosDocker -->|读取配置| NacosDocker -->|持久化全局/分支/锁| MySQLClient -->|获取地址| NacosClient -->|TC RPC 8091| Docker
1. 环境准备
mkdir -p /data/seata/{conf,logs}
cd /data/seatadocker --versionss -lnt | egrep '8091|7091' || echo "8091/7091 currently free"
如启用了 firewalld(云服务器还要同时在腾讯云控制台安全组放行):
firewall-cmd --permanent --add-port=8091/tcp
firewall-cmd --permanent --add-port=7091/tcp
firewall-cmd --reload
2. 初始化 MySQL(服务端存储)
在已有 MySQL 中创建数据库与 4 张服务端表(来自 Seata 官方 script/server/db/mysql.sql):
CREATE DATABASE IF NOT EXISTS seata_serverDEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;USE seata_server;-- 全局事务表
CREATE TABLE IF NOT EXISTS `global_table` (`xid` VARCHAR(128) NOT NULL,`transaction_id` BIGINT,`status` TINYINT NOT NULL,`application_id` VARCHAR(32),`transaction_service_group` VARCHAR(32),`transaction_name` VARCHAR(128),`timeout` INT,`begin_time` BIGINT,`application_data` VARCHAR(2000),`gmt_create` DATETIME,`gmt_modified` DATETIME,PRIMARY KEY (`xid`),KEY `idx_status_gmt_modified` (`status`, `gmt_modified`),KEY `idx_transaction_id` (`transaction_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- 分支事务表
CREATE TABLE IF NOT EXISTS `branch_table` (`branch_id` BIGINT NOT NULL,`xid` VARCHAR(128) NOT NULL,`transaction_id` BIGINT,`resource_group_id` VARCHAR(32),`resource_id` VARCHAR(256),`branch_type` VARCHAR(8),`status` TINYINT,`client_id` VARCHAR(64),`application_data` VARCHAR(2000),`gmt_create` DATETIME(6),`gmt_modified` DATETIME(6),PRIMARY KEY (`branch_id`),KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- 全局锁表
CREATE TABLE IF NOT EXISTS `lock_table` (`row_key` VARCHAR(128) NOT NULL,`xid` VARCHAR(128),`transaction_id` BIGINT,`branch_id` BIGINT NOT NULL,`resource_id` VARCHAR(256),`table_name` VARCHAR(32),`pk` VARCHAR(36),`status` TINYINT NOT NULL DEFAULT 0 COMMENT '0:locked,1:rollbacking',`gmt_create` DATETIME,`gmt_modified` DATETIME,PRIMARY KEY (`row_key`),KEY `idx_status` (`status`),KEY `idx_branch_id` (`branch_id`),KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- HA 分布式锁
CREATE TABLE IF NOT EXISTS `distributed_lock` (`lock_key` CHAR(20) NOT NULL,`lock_value` VARCHAR(20) NOT NULL,`expire` BIGINT,PRIMARY KEY (`lock_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT IGNORE INTO `distributed_lock` (lock_key, lock_value, expire) VALUES('AsyncCommitting','',0),('RetryCommitting','',0),('RetryRollbacking','',0),('TxTimeoutCheck','',0);
业务侧(每个被 AT 模式管理的业务库)还需要
undo_log表 —— 等接入客户端时再加,本次不在部署范围。
3. 准备 application.yml(注册中心 + 安全 + 指向配置中心)
文件路径:/data/seata/conf/application.yml
server:port: 7091spring:application:name: seata-serverlogging:config: classpath:logback-spring.xmlfile:path: ${user.home}/logs/seataextend:logstash-appender:destination: 127.0.0.1:4560kafka-appender:bootstrap-servers: 127.0.0.1:9092topic: logback_to_logstashconsole:user:username: <SEATA_CONSOLE_USER>password: <SEATA_CONSOLE_PWD>seata:config:type: nacosnacos:server-addr: <NACOS_IP>:8848namespace: <NACOS_NAMESPACE_ID>group: <NACOS_GROUP>username: <NACOS_USER>password: <NACOS_PWD>data-id: seataServer.propertiesregistry:type: nacosnacos:application: seata-serverserver-addr: <NACOS_IP>:8848group: <NACOS_GROUP>namespace: <NACOS_NAMESPACE_ID>cluster: defaultusername: <NACOS_USER>password: <NACOS_PWD>security:secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017tokenValidityInMilliseconds: 1800000ignore:urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/**/*.woff,/**/*.woff2,/api/v1/auth/login
要点:
seata.config.type=nacos+data-id=seataServer.properties,所有存储/事务组等业务配置都从 Nacos 拉取- 控制台账号通过
console.user.username/password覆盖默认seata/seata(建议改成自定义强密码) secretKey仅作为本地控制台 JWT 签名,请在生产环境改成随机长串**ignore.urls末尾必须是/api/v1/auth/login(Seata 1.8.0 控制台登录接口的真实路径)。
4. 推送 Seata 业务配置到 Nacos
在 Nacos 控制台(命名空间 <NACOS_NAMESPACE_ID>、分组 <NACOS_GROUP>)新建配置:
- Data ID:
seata.properties - 格式:
Properties - 内容:
# ---- 存储模式 ----
store.mode=db
store.lock.mode=db
store.session.mode=db# ---- 公共连接池 ----
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://<MYSQL_HOST>:3306/seata_server?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
store.db.user=<MYSQL_USER>
store.db.password=<MYSQL_PWD>
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.distributedLockTable=distributed_lock
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000# ---- 服务端事务 ----
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
server.distributedLockExpireTime=10000
server.xaerNotaRetryTimeout=60000
server.session.branchAsyncQueueSize=5000
server.session.enableBranchAsyncRemove=false# ---- 事务分组映射(业务侧使用) ----
# 业务方 spring.cloud.alibaba.seata.tx-service-group=mall_tx_group
# 这里需要把组名映射到上面 registry 注册的 cluster(默认 default)
service.vgroupMapping.fsymall_tx_group=default
service.default.grouplist=<SERVER_IP>:8091
service.enableDegrade=false
service.disableGlobalTransaction=false# ---- 客户端默认参数 ----
client.rm.asyncCommitBufferLimit=10000
client.rm.lock.retryInterval=10
client.rm.lock.retryTimes=30
client.rm.lock.retryPolicyBranchRollbackOnConflict=true
client.rm.reportRetryCount=5
client.rm.tableMetaCheckEnable=true
client.rm.sqlParserType=druid
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.onlyCareUpdateColumns=true
client.undo.logTable=undo_log
log.exceptionRate=100
业务侧的事务组名
mall_tx_group之后接入时用,本次仅占位。
5. 启动 Seata Docker 容器
docker pull seataio/seata-server:1.8.0docker run -d --name seata \--restart=always \-p 8091:8091 \-p 7091:7091 \-e SEATA_IP=42.194.214.28 \-e SEATA_PORT=8091 \-v /data/seata/conf/application.yml:/seata-server/resources/application.yml \-v /data/seata/logs:/root/logs/seata \seataio/seata-server:1.8.0
要点(这一步坑较多,请仔细看):
SEATA_IP必须填能被业务微服务访问到的地址(同 VPC 内填内网 IP,跨 VPC 填公网/NAT 后地址)。否则注册到 Nacos 的是容器内 IP(如172.x.x.x),客户端连不通。- 不要使用
-e SEATA_CONFIG_NAME=...。该环境变量是 1.x 早期为registry.conf(HOCON 格式)设计的,内部会拼.conf后缀加载,对 1.5+ 的application.yml不生效,会静默回退到镜像内置默认配置。社区已知问题:apache/incubator-seata#7053。 - 覆盖
application.yml的正确方式是 单文件挂载覆盖镜像内默认文件:-v /data/seata/conf/application.yml:/seata-server/resources/application.yml。 - 不要用
-v /data/seata/conf:/seata-server/resources(目录对目录覆盖),因为镜像内/seata-server/resources/下还有logback-spring.xml、META-INF/services/等文件,目录挂载会把它们一起遮蔽掉,导致日志或 SPI 失效。 - 不要把
STORE_MODE=db用环境变量传 —— 我们走 Nacos 配置中心,统一在seata.properties中控制。
启动后立即验证生效的配置:
docker exec seata cat /seata-server/resources/application.yml | head -40
应当能看到你写的 console.user.username/password 和 seata.config/registry 的 Nacos 配置,而不是镜像默认值。
6. 验证
docker logs -f --tail 200 seata
预期日志关键字:
Server started, service listen port: 8091register TC success或RegistryService is selected: NacosRegistryServiceImpl- 无 MySQL 连接异常、无 Nacos 401/403
其他验证:
- 浏览器访问
http://<SERVER_IP>:7091,使用<SEATA_CONSOLE_USER>/<SEATA_CONSOLE_PWD>登录 - Nacos 控制台 → 服务管理 → 服务列表(对应命名空间和分组)能看到
seata-server - MySQL
seata_server库表保持空状态即正常(有事务时才写入)
7. 常见问题排查清单
- 客户端报
no available service 'default' found, please make sure registry config correct:检查service.vgroupMapping.xxx与客户端tx-service-group是否一致,以及 Nacos 命名空间/分组是否一致。 - 容器启动后立刻退出:多半是
application.yml解析失败或 Nacos 鉴权失败,看docker logs。 - Nacos 列表里 IP 是
172.x容器内网 IP:忘记设置SEATA_IP。 - MySQL 报
Public Key Retrieval is not allowed:连接串加allowPublicKeyRetrieval=true(方案中已带)。 - 控制台 7091 打不开 / 401:1.8.0 默认账号是
seata/seata,本方案在application.yml中已覆盖,请使用<SEATA_CONSOLE_USER>/<SEATA_CONSOLE_PWD>登录。 - 控制台仍然用默认
seata/seata能登录、自己设的密码无效:典型表现是改了application.yml但未生效。原因是SEATA_CONFIG_NAME对application.yml不生效(见第 5 步要点)。修复:去掉SEATA_CONFIG_NAME,改用-v /data/seata/conf/application.yml:/seata-server/resources/application.yml单文件挂载,重建容器。 - 控制台输入正确账号密码点登录后返回 401:浏览器
POST /api/v1/auth/login直接 401,服务端日志JwtAuthenticationEntryPoint: Full authentication is required to access this resource。原因是seata.security.ignore.urls末尾写成了/login,而 Seata 1.8.0 登录接口实际是/api/v1/auth/login,登录请求自己被 JWT 过滤器拦了。修复:把application.yml里ignore.urls末尾改为/api/v1/auth/login,然后docker restart seata。 - 客户端启动报
can not get cluster name in registry config 'service.vgroupMapping.xxx':在 Nacos 的seataServer.properties中没找到该事务组映射,注意客户端读取的 group 也得和服务端一致。 - 浏览器换密码后还能用旧密码登录:浏览器仍持有旧 JWT,无痕窗口或清缓存再试。
8. 卸载/重置(如需)
docker rm -f seata
# 重建表
mysql -h <MYSQL_HOST> -u <MYSQL_USER> -p -e "DROP DATABASE seata_server;"
