Deploy a 3-Node Seata 1.8.0 Cluster with Docker Compose, Nacos & MySQL

This tutorial details deploying a three-node Seata 1.8.0 cluster using Docker Compose, Nacos for service registration and configuration, and MySQL for persistent transaction storage, covering directory layout, node-specific configs, database schema, and verification steps.

Java Captain
Java Captain
Java Captain
Deploy a 3-Node Seata 1.8.0 Cluster with Docker Compose, Nacos & MySQL

Preparation

Seata is an open-source distributed transaction solution from Ant Group and Alibaba, offering four modes: XA (strong consistency, no business intrusion), TCC (eventual consistency, business intrusion), AT (eventual consistency, no intrusion, default), and SAGA (long transactions, business intrusion). This guide focuses on the first three modes and demonstrates a production-style cluster deployment.

Environment

OS: CentOS 7

Host IP: 192.168.136.128

Nacos: already deployed, no authentication

MySQL: already deployed

Docker & Docker Compose installed

Seata version: 1.8.0

Required Downloads

seata-server-1.8.0.zip

– server package for direct Windows startup seata-1.8.0.zip – source package containing configuration files and SQL scripts

From the source package, the following files are needed: server/src/main/resources/application.yml and application.example.yml (server config) script/server/db/mysql.sql (server-side table creation) script/client/at/db/mysql.sql (AT-mode client tables, not used here)

Cluster Setup

1. Directory Structure

Create /app/seata with subdirectories server1, server2, server3. Place a copy of application.yml in each, modifying the port per node.

2. Node Configuration (application.yml)

Example for server1 (port 7091, transaction port 8091):

server:
  port: 7091

spring:
  application:
    name: seata-server

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

console:
  user:
    username: seata
    password: seata

seata:
  config:
    type: nacos
    nacos:
      server-addr: 192.168.136.128:8848
      group: SEATA_GROUP
      data-id: seataServer.properties
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 192.168.136.128:8848
      group: SEATA_GROUP
      cluster: jobs
  security:
    secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
    tokenValidityInMilliseconds: 1800000
    ignore:
      urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login

server2 uses port 7092 (transaction port 8092); server3 uses port 7093 (transaction port 8093).

3. Nacos Configuration (seataServer.properties)

Create a config in Nacos with data-id=seataServer.properties, group=SEATA_GROUP:

store.mode=db
#-----db-----
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://192.168.136.128:3306/seata?useUnicode=true&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false
store.db.user=root
store.db.password=root
store.db.minConn=1
store.db.maxConn=20
store.db.maxWait=5000

store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.lockTable=lock_table
store.db.queryLimit=100

# undo log retention 7 days
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000

# Two-phase retry timeout, -1 = infinite retry
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1

# Retry thread intervals (ms)
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000

4. MySQL Schema Creation

Create database seata and execute the following SQL (from script/server/db/mysql.sql):

-- global_table
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;

-- branch_table
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;

-- lock_table
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;

-- distributed_lock
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 INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0);

5. Docker Compose File

Create /app/seata/docker-compose.yml:

version: "3.2"
services:
  seata1:
    image: seataio/seata-server:1.8.0
    container_name: seata1
    restart: always
    ports:
      - 7091:7091
      - 8091:8091
    environment:
      - SEATA_IP=192.168.136.128
      - SEATA_PORT=8091
      - SERVER_NODE=1
    volumes:
      - /app/seata/server1/application.yml:/seata-server/resources/application.yml
    networks:
      - seata_net

  seata2:
    image: seataio/seata-server:1.8.0
    container_name: seata2
    restart: always
    ports:
      - 7092:7092
      - 8092:8092
    environment:
      - SEATA_IP=192.168.136.128
      - SEATA_PORT=8092
      - SERVER_NODE=2
    volumes:
      - /app/seata/server2/application.yml:/seata-server/resources/application.yml
    networks:
      - seata_net

  seata3:
    image: seataio/seata-server:1.8.0
    container_name: seata3
    restart: always
    ports:
      - 7093:7093
      - 8093:8093
    environment:
      - SEATA_IP=192.168.136.128
      - SEATA_PORT=8093
      - SERVER_NODE=3
    volumes:
      - /app/seata/server3/application.yml:/seata-server/resources/application.yml
    networks:
      - seata_net

networks:
  seata_net:
    driver: bridge
Critical: SEATA_IP and SEATA_PORT must be set to the host VM IP and the transaction port (8091/8092/8093). Without them, Seata registers its container-internal IP in Nacos, making it unreachable from external microservices.

6. Start the Cluster

cd /app/seata
docker-compose up -d

Verification

Container logs – run docker logs -f seata1, seata2, seata3; confirm no errors.

Web console – access each node at:

http://192.168.136.128:7091

http://192.168.136.128:7092

http://192.168.136.128:7093

Credentials: seata / seata.

Nacos service list – open Nacos console, find service seata-server under cluster jobs; three instances should appear.

Single-node deployment: remove two service definitions from docker-compose.yml .
Future posts will use this environment to demonstrate AT, TCC, and XA transaction modes.
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

MicroservicesNacosMySQLDistributed TransactionsCluster DeploymentSeataDocker Compose
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.