Docker 一键部署全套基础设施|Redis/RabbitMQ/ES/Kibana/MongoDB/InfluxDB/EMQX/SQLServer2022

一、博客前言

在企业后端、物联网、大数据、中台项目中,经常需要一次性部署全套中间件基础设施。手动逐个搭建、配权限、改配置、建目录、处理容器权限报错,极其繁琐且容易出问题。

本文提供一份生产可用、一键执行、零手动干预、解决所有容器权限坑的完整部署脚本,一次性搭建:

  • Redis 6.2
  • RabbitMQ 3.13
  • Elasticsearch 8.17.2 + Kibana 8.17.2
  • MongoDB 8.0.3
  • InfluxDB 2.7.10
  • EMQX 5.8.8 物联网MQTT网关
  • SQL Server 2022 (彻底解决 /.system 权限拒绝报错)

脚本自动完成:私有仓库配置、目录创建、配置文件生成、精准权限适配、全局网络创建、镜像拉取、服务启动、账号初始化、密码重置、RabbitMQ虚拟主机/用户初始化,部署完成自动销毁脚本,干净整洁。

二、整体架构与目录结构

**1.**部署根目录

统一部署路径:/home/appInfrastructure

**2.**完整目录结构

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| bash appInfrastructure/ ├── redis/ # 缓存服务 ├── rabbitmq/ # 消息队列 ├── es-kibana/ # 日志检索引擎 ├── mongodb/ # NoSQL数据库 ├── influxdb/ # 时序数据库 ├── emqx/ # MQTT物联网网关 ├── sqlserver/ # 关系型数据库 │ ├── data/ # 数据持久化 │ ├── logs/ # 日志目录 │ └── backup/ # 数据库备份目录 └── docker-compose.yml |

三、核心解决的经典坑点(重点)

这是全网很多部署脚本的通病,本文全部修复

1. SQL Server 2022****致命权限问题

错误日志:

|----------------------------------------------------------------------------------------------------------------|
| bash /opt/mssql/bin/sqlservr: Error: The system directory /.system could not be created. Permission denied |

根源 :SQL Server2022 Linux 容器默认非 root 运行,内部用户 mssql UID=10001,绝大多数脚本写错为 1001 或 root 权限,导致启动失败。

本文精准修复

|-------------------------------------------------------------------------------------|
| bash sudo chown -R 10001:10001 ./sqlserver/data ./sqlserver/logs ./sqlserver/backup |

**2.**各中间件专属 UID 权限适配

不同容器内部运行用户UID不同,脚本单独适配:

  • Redis / RabbitMQ / MongoDB:999
  • ES / InfluxDB / EMQX:1000
  • SQL Server:10001 (独家关键修复)

**3.**日志目录单独放开权限

数据目录严格权限、日志目录宽松可读,兼顾安全 + 运维排查

**4.**自动配置私有 Docker HTTP 仓库

自动写入 daemon.json、重启Docker,无需手动改配置。

**5.**全局统一网络 internal-net

所有服务互通,微服务架构标准组网方式。

四、一键部署完整脚本(可直接落地)

新建文件deploy-all.sh,写入以下全部内容:

bash 复制代码
#!/bin/bash
set -e
echo "============================================="
echo "      基础设施一键部署脚本 (专属配置版)      "
echo "============================================="

# 核心配置
BASE_DIR="/home/appInfrastructure"
REGISTRY="10.31.20.13:8081"
IMAGE_PREFIX="${REGISTRY}/public-docker"

# ===================== 自动配置Docker信任HTTP仓库 =====================
echo "0. 自动配置Docker信任HTTP仓库..."
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json > /dev/null <<EOF
{
  "insecure-registries": ["10.31.20.13:8081"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
echo "✅ Docker HTTP仓库配置完成,等待服务重启..."
sleep 5
# ==========================================================================

# 1. 初始化工作目录
echo "1. 初始化工作目录..."
sudo mkdir -p ${BASE_DIR}
cd ${BASE_DIR}

# ===================== 第一步:创建所有服务目录(先建目录,防止报错)=====================
echo "2. 创建服务目录结构..."
# Redis
sudo mkdir -p ./redis/data ./redis/logs
# RabbitMQ
sudo mkdir -p ./rabbitmq/data ./rabbitmq/logs
# MongoDB
sudo mkdir -p ./mongodb/data ./mongodb/logs
# ES & Kibana
sudo mkdir -p ./es-kibana/es/master/{conf,data,logs,plugins}
sudo mkdir -p ./es-kibana/kibana
# InfluxDB
sudo mkdir -p ./influxdb/data ./influxdb/config ./influxdb/logs
# EMQX
sudo mkdir -p ./emqx/data ./emqx/log
# SQL Server 目录(新增backup备份目录)
sudo mkdir -p ./sqlserver/data ./sqlserver/logs ./sqlserver/backup
# ====================================================================================

# 2. 写入配置文件(目录已创建,无报错)
echo "3. 写入服务配置文件..."

# Redis配置
cat > ./redis/redis.conf <<'EOF'
bind 0.0.0.0
protected-mode no
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile ""
databases 48
always-show-logo no
set-proc-title yes
proc-title-template "{title} {listen-addr} {server-mode}"
save 3600 1
save 300 100
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
rdb-del-sync-files no
dir ./
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-diskless-load disabled
repl-disable-tcp-nodelay no
replica-priority 100
acllog-max-len 128
requirepass shhy123#
maxclients 10000
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
lazyfree-lazy-user-del no
lazyfree-lazy-user-flush no
oom-score-adj no
oom-score-adj-values 0 200 800
disable-thp yes
appendonly yes
appendfilename "append.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
jemalloc-bg-thread yes
EOF

# Elasticsearch配置
cat > ./es-kibana/es/master/conf/elasticsearch.yml <<'EOF'
cluster.name: "elasticsearch"
cluster.max_shards_per_node: 12000
network.host: 0.0.0.0
xpack.security.enabled: true
http.cors.enabled: true
http.cors.allow-origin: "*" 
http.cors.allow-headers: "Authorization, Content-Type, X-Requested-With"
EOF

# Kibana配置
cat > ./es-kibana/kibana/kibana.yml <<'EOF'
server.port: 5601
server.host: "0.0.0.0"
elasticsearch.hosts: ["http://es:9200"]
i18n.locale: "zh-CN"
elasticsearch.username: kibana_system
elasticsearch.password: shhy123#
EOF

# 3. 生成docker-compose.yml
echo "4. 生成Docker编排文件..."
cat > docker-compose.yml <<EOF
networks:
  internal-net:
    external: true

services:
  redis:
    image: ${IMAGE_PREFIX}/redis:6.2.0
    container_name: redis6
    restart: always
    ports:
      - "6379:6379"
    volumes:
      - ./redis/redis.conf:/usr/local/etc/redis/redis.conf:ro
      - ./redis/data:/data:rw
      - ./redis/logs:/var/log/redis:rw
    environment:
      - TZ=Asia/Shanghai
    command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 3
    networks:
      - internal-net

  rabbitmq:
    image: ${IMAGE_PREFIX}/rabbitmq:3.13-management
    container_name: rabbitmq
    restart: always
    hostname: rabbitmq
    environment:
      - RABBITMQ_DEFAULT_VHOST=my_vhost
      - RABBITMQ_DEFAULT_USER=admin
      - RABBITMQ_DEFAULT_PASS=shhy123#
    volumes:
      - ./rabbitmq/data:/var/lib/rabbitmq:rw
      - ./rabbitmq/logs:/var/log/rabbitmq:rw
    ports:
      - "4369:4369"
      - "5672:5672"
      - "15672:15672"
      - "25672:25672"
    cap_add:
      - CAP_SYS_NICE
    networks:
      - internal-net
    healthcheck:
      test: ["CMD", "rabbitmq-diagnostics", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3

  es:
    image: ${IMAGE_PREFIX}/elasticsearch:8.17.2
    container_name: es
    restart: always
    hostname: es
    environment:
      - "ES_JAVA_OPTS=-Xms2048m -Xmx2048m"
      - "discovery.type=single-node"
      - "cluster.name=elasticsearch-spc"
      - "ELASTIC_PASSWORD=shhy123#"
      - "TAKE_FILE_OWNERSHIP=true"
      - TZ=Asia/Shanghai
    volumes:
      - ./es-kibana/es/master/conf/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro
      - ./es-kibana/es/master/data:/usr/share/elasticsearch/data:rw
      - ./es-kibana/es/master/logs:/usr/share/elasticsearch/logs:rw
      - ./es-kibana/es/master/plugins:/usr/share/elasticsearch/plugins:rw
    ports:
      - "9200:9200"
      - "9300:9300"
    networks:
      - internal-net
    healthcheck:
      test: ["CMD", "curl", "-s", "-u", "elastic:\$\$ELASTIC_PASSWORD", "http://localhost:9200/_cluster/health"]
      interval: 15s
      timeout: 10s
      retries: 3

  kibana:
    image: ${IMAGE_PREFIX}/kibana:8.17.2
    container_name: kibana
    restart: always
    hostname: kibana
    environment:
      - TZ=Asia/Shanghai
      - "elasticsearch.hosts=http://es:9200"
      - "elasticsearch.username=kibana_system"
      - "elasticsearch.password=shhy123#"
      - "NODE_OPTIONS=--openssl-legacy-provider=false"
    volumes:
      - ./es-kibana/kibana/kibana.yml:/usr/share/kibana/config/kibana.yml:ro
    ports:
      - "5601:5601"
    networks:
      - internal-net
    depends_on:
      - es
    healthcheck:
      test: ["CMD", "curl", "-s", "http://localhost:5601/api/status"]
      interval: 15s
      timeout: 10s
      retries: 3

  mongodb:
    image: ${IMAGE_PREFIX}/mongo:8.0.3
    container_name: mongodb
    restart: always
    hostname: mongodb
    environment:
      - TZ=Asia/Shanghai
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=shhy123#
    volumes:
      - ./mongodb/data:/data/db:rw
      - ./mongodb/logs:/var/log/mongodb:rw
    ports:
      - "27017:27017"
    networks:
      - internal-net
    healthcheck:
      test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')", "-u", "admin", "-p", "shhy123#", "--authenticationDatabase", "admin"]
      interval: 10s
      timeout: 5s
      retries: 3

  influxdb:
    image: ${IMAGE_PREFIX}/influxdb:2.7.10
    container_name: influxdb
    restart: always
    hostname: influxdb
    environment:
      - TZ=Asia/Shanghai
      - DOCKER_INFLUXDB_INIT_MODE=setup
      - DOCKER_INFLUXDB_INIT_USERNAME=admin
      - DOCKER_INFLUXDB_INIT_PASSWORD=shhy123#
      - DOCKER_INFLUXDB_INIT_ORG=my_org
      - DOCKER_INFLUXDB_INIT_BUCKET=default_bucket
      - DOCKER_INFLUXDB_INIT_RETENTION=30d
      - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=my_secret_token_123
    volumes:
      - ./influxdb/data:/var/lib/influxdb2:rw
      - ./influxdb/config:/etc/influxdb2:rw
      - ./influxdb/logs:/var/log/influxdb2:rw
    ports:
      - "8086:8086"
    networks:
      - internal-net
    healthcheck:
      test: ["CMD", "curl", "-s", "-o", "/dev/null", "http://localhost:8086/health"]
      interval: 10s
      timeout: 5s
      retries: 3

  emqx:
    image: ${IMAGE_PREFIX}/emqx/emqx:5.8.8
    container_name: emqx
    restart: always
    hostname: emqx
    environment:
      - TZ=Asia/Shanghai
      - EMQX_NODE_NAME=emqx@127.0.0.1
      - EMQX_CLUSTER__DISCOVERY_STRATEGY=static
      - EMQX_LISTENER_TCP_DEFAULT_BIND=0.0.0.0:1883
      - EMQX_LISTENER_WS_DEFAULT_BIND=0.0.0.0:8083
      - EMQX_LOG_LEVEL=info
      - EMQX_LOG_CONSOLE_ENABLE=true
      - EMQX_NODE_PROCESS_LIMIT=2097152
      - EMQX_NODE_MAX_PORTS=1048576
      - EMQX_NODE_COOKIE=emqx_secret_cookie_123
    volumes:
      - ./emqx/data:/opt/emqx/data:rw
      - ./emqx/log:/opt/emqx/log:rw
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "1883:1883"
      - "8083:8083"
      - "8084:8084"
      - "8883:8883"
      - "18083:18083"
    networks:
      - internal-net
    healthcheck:
      test: ["CMD", "/opt/emqx/bin/emqx", "ctl", "status"]
      interval: 20s
      timeout: 25s
      retries: 10
      start_period: 60s
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 1G
        reservations:
          cpus: '0.5'
          memory: 512M

  sqlserver:
    image: ${IMAGE_PREFIX}/mssql/server:2022-latest
    container_name: sqlserver2022
    restart: always
    hostname: sqlserver
    environment:
      - TZ=Asia/Shanghai
      - ACCEPT_EULA=Y
      - SA_PASSWORD=shhy123#
      - MSSQL_PID=Express
    volumes:
      - ./sqlserver/data:/var/opt/mssql:rw
      - ./sqlserver/logs:/var/log/mssql:rw
      - ./sqlserver/backup:/var/opt/mssql/backup:rw
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "1433:1433"
    networks:
      - internal-net
    healthcheck:
      test: ["CMD-SHELL", "pidof sqlservr"]
      interval: 15s
      timeout: 10s
      retries: 5
      start_period: 40s
EOF

# ===================== 【核心】权限配置 =====================
echo "5. 配置服务权限..."
sudo chown -R 999:999 ./redis/data ./redis/logs
sudo chmod -R 755 ./redis
sudo chmod -R 777 ./redis/logs

sudo chown -R 999:999 ./rabbitmq/data ./rabbitmq/logs
sudo chmod -R 755 ./rabbitmq
sudo chmod -R 700 ./rabbitmq/data
sudo chmod -R 777 ./rabbitmq/logs

sudo chown -R 999:999 ./mongodb/data ./mongodb/logs
sudo chmod -R 755 ./mongodb
sudo chmod -R 777 ./mongodb/logs

sudo chown -R 1000:1000 ./es-kibana/es/master/data ./es-kibana/es/master/logs ./es-kibana/es/master/plugins
sudo chmod -R 755 ./es-kibana
sudo chmod -R 777 ./es-kibana/es/master/logs

sudo chown -R 1000:1000 ./influxdb/data ./influxdb/config ./influxdb/logs
sudo chmod -R 755 ./influxdb
sudo chmod -R 777 ./influxdb/logs

sudo chown -R 1000:1000 ./emqx/data ./emqx/log
sudo chmod -R 755 ./emqx
sudo chmod -R 700 ./emqx/data
sudo chmod -R 777 ./emqx/log

# SQL Server 目录权限(新增backup备份目录)
sudo chown -R 10001:10001 ./sqlserver/data ./sqlserver/logs ./sqlserver/backup
sudo chmod -R 770 ./sqlserver
sudo chmod -R 777 ./sqlserver/logs ./sqlserver/backup
# ====================================================================================

# 登录私有仓库
echo "6. 登录私有镜像仓库..."
sudo docker login ${REGISTRY}

# ========== 前置:先手动创建全局共享网络 internal-net ==========
echo "7. 检查并创建全局共享网络 internal-net"
if ! docker network inspect internal-net >/dev/null 2>&1; then
    docker network create internal-net
    echo "✅ 全局网络 internal-net 创建完成"
else
    echo "✅ 全局网络 internal-net 已存在,跳过创建"
fi
# ==============================================================

# 拉取镜像
echo "8. 拉取服务镜像..."
sudo docker compose pull

# 启动服务
echo "9. 启动所有服务..."
sudo docker compose up -d

# 设置Kibana密码
echo "10. 等待ES启动完成(100秒)..."
sleep 100
echo "11. 设置Kibana密码..."
echo "y" | docker exec -i es /usr/share/elasticsearch/bin/elasticsearch-reset-password -u kibana_system -i -b << EOF
shhy123#
shhy123#
EOF
echo "✅ Kibana密码已成功设置为: shhy123#"

# 强制创建 / 虚拟主机
echo "12. 等待rabbitmq启动完成(100秒)..."
sleep 100
echo "创建虚拟主机 / ..."
docker exec rabbitmq rabbitmqctl add_vhost / 2>/dev/null || true

echo "13. 开始创建RabbitMQ用户 spcmq 密码 123456,并赋予 management 权限..."
docker exec rabbitmq rabbitmqctl add_user spcmq 123456 2>/dev/null || true
docker exec rabbitmq rabbitmqctl set_user_tags spcmq management
docker exec rabbitmq rabbitmqctl set_permissions -p / spcmq ".*" ".*" ".*"
echo "✅ RabbitMQ 虚拟主机 / + 用户 spcmq 配置完成"

# 等待SQL Server就绪提示
echo "14. 等待SQL Server启动完成(60秒)..."
sleep 60
echo "✅ SQL Server 2022 部署完成,账号:sa / 密码:shhy123#"
echo "✅ 备份文件存放路径:宿主机 ./sqlserver/backup  容器内 /var/opt/mssql/backup"

echo "============================================="
echo "              部署完成!🎉                   "
echo " 所有服务权限已按规范配置完成"
echo " RabbitMQ 新增用户:spcmq / 123456 (management)"
echo " RabbitMQ 虚拟主机:/"
echo " SQL Server 账号:sa / 密码:shhy123# 端口:1433"
echo " SQL Server 备份目录:./sqlserver/backup"
echo " 查看状态:docker compose ps"
echo "============================================="

# 自动删除脚本自身
rm -f -- "$0"

五、部署执行步骤

**1.**赋予执行权限

|-----------------------------|
| bash chmod +x deploy-all.sh |

**2.**一键执行部署

|----------------------|
| bash ./deploy-all.sh |

六、所有服务账号密码清单(统一整理)

Redis

密码:shhy123#

RabbitMQ

默认管理员:admin / shhy123#

业务用户:spcmq / 123456

虚拟主机:/、my_vhost

Elasticsearch

超级管理员:elastic / shhy123#

Kibana系统用户:kibana_system / shhy123#

MongoDB

账号:admin / shhy123#

InfluxDB

账号:admin / shhy123#

SQL Server 2022

账号:sa / shhy123#

备份目录:宿主机 /home/appInfrastructure/sqlserver/backup

七、常用运维命令

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| bash # 查看所有服务状态 docker compose ps # 重启全部服务 docker compose restart # 停止所有服务(保留数据) docker compose down # 彻底销毁重建(数据保留) docker compose down && docker compose up -d # 查看某服务日志 docker logs -f sqlserver2022 |

八、总结

本脚本是生产级的全套中间件部署方案:

  • 全自动无人值守部署
  • 精准适配各容器UID权限,彻底杜绝权限报错
  • 自动初始化账号、虚拟主机、密码、配置
  • 部署完成自销毁,服务器环境干净

可直接用于:项目初始化、测试环境、预生产环境、物联网平台、数据中台、微服务基础设施搭建。