在Swarm中部署Nacos并配置外部MySQL

在Swarm中部署Nacos并配置外部MySQL

1. 项目结构调整

csharp 复制代码
project/
├── docker-stack.yml          # Swarm主配置文件
├── .env                      # 环境变量文件
├── config/
│   ├── mysql-init/
│   │   ├── init.sql         # MySQL初始化脚本
│   │   └── nacos-schema.sql # Nacos数据库脚本
│   ├── nacos/
│   │   ├── cluster.conf     # Nacos集群配置(可选)
│   │   └── application.properties # Nacos自定义配置
│   └── nginx/
│       └── nginx.conf       # 如果需要nginx代理
├── logs/
│   ├── app/
│   ├── nacos/
│   └── nginx/
└── data/
    ├── mysql/
    ├── redis/
    ├── app-data/
    └── nacos/
        ├── conf/            # Nacos配置文件
        ├── data/            # Nacos数据
        └── logs/            # Nacos日志

2. Nacos数据库初始化脚本

config/mysql-init/nacos-schema.sql

sql 复制代码
-- 创建Nacos数据库
CREATE DATABASE IF NOT EXISTS nacos CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 使用Nacos数据库
USE nacos;

-- 创建Nacos配置表
-- 注意:这里使用Nacos官方提供的SQL脚本,您需要从以下地址下载:
-- https://github.com/alibaba/nacos/blob/master/distribution/conf/mysql-schema.sql
-- 这里是一个简化的示例,实际使用时请使用官方完整脚本

CREATE TABLE IF NOT EXISTS `config_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) DEFAULT NULL,
  `content` longtext NOT NULL COMMENT 'content',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
  `app_name` varchar(128) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  `c_desc` varchar(256) DEFAULT NULL,
  `c_use` varchar(64) DEFAULT NULL,
  `effect` varchar(64) DEFAULT NULL,
  `type` varchar(64) DEFAULT NULL,
  `c_schema` text,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';

-- 其他表结构请从官方GitHub获取完整SQL

config/mysql-init/init.sql

sql 复制代码
-- 创建应用数据库
CREATE DATABASE IF NOT EXISTS appdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 创建应用用户
CREATE USER IF NOT EXISTS 'appuser'@'%' IDENTIFIED BY '${MYSQL_PASSWORD}';
GRANT ALL PRIVILEGES ON appdb.* TO 'appuser'@'%';

-- 创建Nacos用户
CREATE USER IF NOT EXISTS 'nacos'@'%' IDENTIFIED BY '${NACOS_DB_PASSWORD}';
GRANT ALL PRIVILEGES ON nacos.* TO 'nacos'@'%';

FLUSH PRIVILEGES;

3. Nacos自定义配置

config/nacos/application.properties

properties 复制代码
# 数据库配置
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://mysql:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user=nacos
db.password=${NACOS_DB_PASSWORD}

# 集群配置(单机模式)
nacos.standalone=true

# 鉴权配置(可选)
nacos.core.auth.enabled=false
nacos.core.auth.server.identity.key=serverIdentity
nacos.core.auth.server.identity.value=security

# 服务发现配置
nacos.naming.empty-service.auto-clean=true
nacos.naming.empty-service.clean.initial-delay-ms=50000
nacos.naming.empty-service.clean.period-time-ms=30000

# 日志配置
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D
logging.file.path=/home/nacos/logs
logging.level.com.alibaba.nacos=info

config/nacos/cluster.conf(集群模式可选)

conf 复制代码
# Nacos集群节点配置
nacos1:8848
nacos2:8848
nacos3:8848

4. docker-stack.yml

yaml 复制代码
version: '3.8'

# 定义网络
networks:
  backend:
    driver: overlay
    attachable: true

# 定义配置
configs:
  # Nacos配置
  nacos-config:
    file: ./config/nacos/application.properties
  # 应用配置(可选)
  app-config:
    file: ./config/application.yml

# 定义卷
volumes:
  mysql-data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: ./data/mysql
  
  redis-data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: ./data/redis
  
  nacos-conf:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: ./data/nacos/conf
  
  nacos-data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: ./data/nacos/data
  
  nacos-logs:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: ./data/nacos/logs
  
  app-logs:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: ./logs/app
  
  app-data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: ./data/app-data

# 定义服务
services:
  # MySQL服务
  mysql:
    image: mysql:8.0
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      TZ: Asia/Shanghai
    volumes:
      - mysql-data:/var/lib/mysql
      - ./config/mysql-init:/docker-entrypoint-initdb.d  # 初始化脚本
    ports:
      - "3306:3306"
    networks:
      - backend
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD"]
      interval: 10s
      timeout: 5s
      retries: 3
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints:
          - node.role == manager

  # Redis服务
  redis:
    image: redis:7-alpine
    container_name: redis
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis-data:/data
    ports:
      - "6379:6379"
    networks:
      - backend
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
      interval: 10s
      timeout: 3s
      retries: 3
    deploy:
      mode: replicated
      replicas: 1

  # Nacos服务
  nacos:
    image: nacos/nacos-server:${NACOS_VERSION:-2.2.0}
    container_name: nacos
    environment:
      MODE: ${NACOS_MODE:-standalone}  # standalone 或 cluster
      SPRING_DATASOURCE_PLATFORM: mysql
      MYSQL_SERVICE_HOST: mysql
      MYSQL_SERVICE_PORT: 3306
      MYSQL_SERVICE_DB_NAME: nacos
      MYSQL_SERVICE_USER: nacos
      MYSQL_SERVICE_PASSWORD: ${NACOS_DB_PASSWORD}
      NACOS_AUTH_ENABLE: ${NACOS_AUTH_ENABLE:-false}
      NACOS_AUTH_TOKEN: ${NACOS_AUTH_TOKEN:-SecretKey012345678901234567890123456789012345678901234567890123456789}
      NACOS_AUTH_IDENTITY_KEY: ${NACOS_AUTH_IDENTITY_KEY:-serverIdentity}
      NACOS_AUTH_IDENTITY_VALUE: ${NACOS_AUTH_IDENTITY_VALUE:-security}
      JVM_XMS: ${NACOS_JVM_XMS:-512m}
      JVM_XMX: ${NACOS_JVM_XMX:-512m}
      JVM_XMN: ${NACOS_JVM_XMN:-256m}
      TZ: Asia/Shanghai
    volumes:
      - nacos-conf:/home/nacos/conf
      - nacos-data:/home/nacos/data
      - nacos-logs:/home/nacos/logs
    ports:
      - "${NACOS_PORT:-8848}:8848"  # 主端口
      - "${NACOS_PORT_GRPC:-9848}:9848"  # gRPC端口,用于服务发现
      - "${NACOS_PORT_GRPC_PLUS:-9849}:9849"  # gRPC端口+1000
    networks:
      - backend
    depends_on:
      mysql:
        condition: service_healthy
    configs:
      - source: nacos-config
        target: /home/nacos/conf/application.properties
    deploy:
      mode: replicated
      replicas: ${NACOS_REPLICAS:-1}
      update_config:
        parallelism: 1
        delay: 10s
        order: start-first
      restart_policy:
        condition: on-failure
        delay: 10s
        max_attempts: 3
      resources:
        limits:
          memory: 1G
        reservations:
          memory: 512M
      placement:
        constraints:
          - node.labels.nacos == true  # 可以给节点打标签
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8848/nacos/v1/ns/operator/metrics"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

  # Spring Boot应用
  app:
    image: ${APP_IMAGE}
    container_name: app
    environment:
      SPRING_PROFILES_ACTIVE: ${SPRING_PROFILE:-prod}
      SPRING_CLOUD_NACOS_DISCOVERY_SERVER-ADDR: nacos:8848
      SPRING_CLOUD_NACOS_CONFIG_SERVER-ADDR: nacos:8848
      SPRING_CLOUD_NACOS_USERNAME: ${NACOS_USERNAME:-nacos}
      SPRING_CLOUD_NACOS_PASSWORD: ${NACOS_PASSWORD:-nacos}
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/${MYSQL_DATABASE}?useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
      SPRING_DATASOURCE_USERNAME: ${MYSQL_USER}
      SPRING_DATASOURCE_PASSWORD: ${MYSQL_PASSWORD}
      SPRING_REDIS_HOST: redis
      SPRING_REDIS_PORT: 6379
      SPRING_REDIS_PASSWORD: ${REDIS_PASSWORD}
      JAVA_OPTS: "-Xmx512m -Xms256m -Duser.timezone=Asia/Shanghai"
      TZ: Asia/Shanghai
    volumes:
      - app-logs:/app/logs
      - app-data:/app/data
    ports:
      - "${APP_PORT:-8080}:8080"
    networks:
      - backend
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
      nacos:
        condition: service_healthy
    deploy:
      mode: replicated
      replicas: ${REPLICAS:-2}
      update_config:
        parallelism: 1
        delay: 10s
        order: start-first
      restart_policy:
        condition: on-failure
        delay: 10s
        max_attempts: 3
      resources:
        limits:
          memory: 1G
        reservations:
          memory: 512M
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

  # Nginx反向代理(可选)
  nginx:
    image: nginx:alpine
    container_name: nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./logs/nginx:/var/log/nginx
      - ./ssl:/etc/nginx/ssl:ro
    networks:
      - backend
    depends_on:
      - app
      - nacos
    deploy:
      mode: replicated
      replicas: 1

5. .env 文件

env 复制代码
# MySQL配置
MYSQL_ROOT_PASSWORD=YourStrongRootPassword
MYSQL_DATABASE=appdb
MYSQL_USER=appuser
MYSQL_PASSWORD=YourStrongAppPassword

# Redis配置
REDIS_PASSWORD=YourStrongRedisPassword

# Nacos配置
NACOS_VERSION=2.2.0
NACOS_MODE=standalone
NACOS_DB_PASSWORD=YourStrongNacosDbPassword
NACOS_AUTH_ENABLE=false
NACOS_AUTH_TOKEN=SecretKey012345678901234567890123456789012345678901234567890123456789
NACOS_USERNAME=nacos
NACOS_PASSWORD=nacos
NACOS_PORT=8848
NACOS_PORT_GRPC=9848
NACOS_REPLICAS=1

# 应用配置
APP_IMAGE=your-registry/springboot-app:1.0.0
APP_PORT=8080
SPRING_PROFILE=prod
REPLICAS=2

# Swarm配置
STACK_NAME=springboot-nacos-stack

6. Nginx配置(代理Nacos和App)

config/nginx/nginx.conf

nginx 复制代码
worker_processes auto;

events {
    worker_connections 1024;
}

http {
    upstream app_servers {
        least_conn;
        server app:8080;
    }

    upstream nacos_servers {
        least_conn;
        server nacos:8848;
    }

    # Nacos服务代理
    server {
        listen 8848;
        server_name nacos.your-domain.com;
        
        location / {
            proxy_pass http://nacos_servers;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_connect_timeout 60s;
            proxy_send_timeout 60s;
            proxy_read_timeout 60s;
            
            # 允许跨域(Nacos控制台需要)
            add_header Access-Control-Allow-Origin *;
            add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
            add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
        }
        
        access_log /var/log/nginx/nacos-access.log;
        error_log /var/log/nginx/nacos-error.log;
    }

    # 应用服务代理
    server {
        listen 80;
        server_name your-domain.com;
        
        location / {
            proxy_pass http://app_servers;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_connect_timeout 60s;
            proxy_send_timeout 60s;
            proxy_read_timeout 60s;
        }
        
        access_log /var/log/nginx/app-access.log;
        error_log /var/log/nginx/app-error.log;
    }
}

7. Spring Boot应用配置示例

bootstrap.yml(应用配置文件)

yaml 复制代码
spring:
  application:
    name: your-app-name
  
  cloud:
    nacos:
      discovery:
        server-addr: ${SPRING_CLOUD_NACOS_DISCOVERY_SERVER_ADDR:nacos:8848}
        namespace: ${NACOS_NAMESPACE:}
        group: ${NACOS_GROUP:DEFAULT_GROUP}
        username: ${SPRING_CLOUD_NACOS_USERNAME:nacos}
        password: ${SPRING_CLOUD_NACOS_PASSWORD:nacos}
      
      config:
        server-addr: ${SPRING_CLOUD_NACOS_CONFIG_SERVER_ADDR:nacos:8848}
        file-extension: yaml
        namespace: ${NACOS_NAMESPACE:}
        group: ${NACOS_GROUP:DEFAULT_GROUP}
        username: ${SPRING_CLOUD_NACOS_USERNAME:nacos}
        password: ${SPRING_CLOUD_NACOS_PASSWORD:nacos}
        refresh-enabled: true

  datasource:
    url: ${SPRING_DATASOURCE_URL}
    username: ${SPRING_DATASOURCE_USERNAME}
    password: ${SPRING_DATASOURCE_PASSWORD}
    driver-class-name: com.mysql.cj.jdbc.Driver
    hikari:
      maximum-pool-size: 10
      minimum-idle: 5

  redis:
    host: ${SPRING_REDIS_HOST}
    port: ${SPRING_REDIS_PORT}
    password: ${SPRING_REDIS_PASSWORD}
    database: 0
    timeout: 5000ms
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0

8. 部署脚本

deploy.sh

bash 复制代码
#!/bin/bash

# 设置颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

echo -e "${GREEN}开始部署Spring Boot + Nacos项目...${NC}"

# 检查Docker Swarm是否已初始化
if ! docker node ls &> /dev/null; then
    echo -e "${YELLOW}Docker Swarm未初始化,正在初始化...${NC}"
    docker swarm init
fi

# 创建必要的目录
echo -e "${GREEN}创建必要的目录...${NC}"
mkdir -p logs/{app,nacos,nginx}
mkdir -p data/{mysql,redis,app-data,nacos/{conf,data,logs}}
mkdir -p config/{mysql-init,nacos,nginx}

# 检查Nacos数据库脚本是否存在
if [ ! -f "config/mysql-init/nacos-schema.sql" ]; then
    echo -e "${YELLOW}下载Nacos数据库脚本...${NC}"
    curl -o config/mysql-init/nacos-schema.sql \
    https://raw.githubusercontent.com/alibaba/nacos/master/distribution/conf/mysql-schema.sql
fi

# 加载环境变量
if [ -f ".env" ]; then
    echo -e "${GREEN}加载环境变量...${NC}"
    export $(cat .env | grep -v '^#' | xargs)
else
    echo -e "${RED}错误: .env文件不存在${NC}"
    exit 1
fi

# 构建应用镜像(如果需要)
if [ "$1" == "build" ]; then
    echo -e "${GREEN}构建应用镜像...${NC}"
    docker build -t ${APP_IMAGE} .
fi

# 部署服务
echo -e "${GREEN}部署服务...${NC}"
docker stack deploy -c docker-stack.yml ${STACK_NAME}

# 等待服务启动
echo -e "${GREEN}等待服务启动...${NC}"
sleep 30

# 检查服务状态
echo -e "${GREEN}检查服务状态...${NC}"
docker stack services ${STACK_NAME}

echo -e "${GREEN}部署完成!${NC}"
echo -e "访问地址:"
echo -e "  Nacos控制台: http://localhost:${NACOS_PORT:-8848}/nacos"
echo -e "  应用服务: http://localhost:${APP_PORT:-8080}"
echo -e "  数据库: localhost:3306"
echo -e "  Redis: localhost:6379"

9. 管理命令

bash 复制代码
# 给节点打标签(用于部署Nacos)
docker node update --label-add nacos=true <node-name>

# 查看Nacos日志
docker service logs ${STACK_NAME}_nacos -f

# 查看所有服务
docker stack ps ${STACK_NAME}

# 扩展Nacos实例(集群模式)
docker service scale ${STACK_NAME}_nacos=3

# 备份Nacos配置
tar -czf nacos-backup-$(date +%Y%m%d).tar.gz data/nacos/conf/

# 访问Nacos控制台
# 用户名: nacos
# 密码: nacos(默认)

10. Nacos集群模式部署(可选)

如果需要部署Nacos集群,需要:

  1. 修改 .env 文件:
env 复制代码
NACOS_MODE=cluster
NACOS_REPLICAS=3
  1. 确保每个节点都有标签:
bash 复制代码
docker node update --label-add nacos=true node1
docker node update --label-add nacos=true node2
docker node update --label-add nacos=true node3
  1. 创建集群配置文件并挂载到每个Nacos实例。

这个配置实现了:

  • Nacos使用外部MySQL存储配置
  • 所有配置文件持久化到本地
  • Spring Boot应用从Nacos获取配置
  • 完整的健康检查和服务依赖
  • 日志和数据持久化

请根据您的实际需求调整配置。

相关推荐
想摆烂的不会研究的研究生9 小时前
每日八股——Redis(1)
数据库·经验分享·redis·后端·缓存
毕设源码-郭学长9 小时前
【开题答辩全过程】以 基于SpringBoot技术的美妆销售系统为例,包含答辩的问题和答案
java·spring boot·后端
追逐时光者10 小时前
精选 10 款 .NET 开源免费、功能强大的 Windows 效率软件
后端·.net
追逐时光者10 小时前
一款开源、免费的 WPF 自定义控件集
后端·.net
S***q37710 小时前
Spring Boot管理用户数据
java·spring boot·后端
毕设源码-郭学长11 小时前
【开题答辩全过程】以 基于SpringBoot框架的民俗文化交流与交易平台的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
l***217811 小时前
SpringBoot Maven快速上手
spring boot·后端·maven
f***147711 小时前
SpringBoot实战:高效实现API限流策略
java·spring boot·后端
计算机毕设VX:Fegn089511 小时前
计算机毕业设计|基于springboot + vue动物园管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计