VortMall Docker 部署指南
本文档详细介绍如何使用 Docker 和 Docker Compose 部署 VortMall 微服务商城系统。
目录
1. 环境准备
1.1 系统要求
| 项目 | 最低要求 | 推荐配置 |
|---|---|---|
| 操作系统 | CentOS 7+ / Ubuntu 20.04+ / Debian 11+ | Ubuntu 22.04 LTS |
| CPU | 4核 | 8核+ |
| 内存 | 16GB | 32GB |
| 磁盘 | 100GB SSD | 200GB SSD |
| Docker | 20.10+ | 24.0+ |
| Docker Compose | 2.0+ | 2.20+ |
1.2 安装 Docker
CentOS / RHEL / Alibaba Cloud Linux
# 卸载旧版本
sudo yum remove docker docker-client docker-client-latest docker-common \
docker-latest docker-latest-logrotate docker-logrotate docker-engine
# 安装依赖
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# 添加 Docker 仓库
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 安装 Docker
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 启动 Docker
sudo systemctl start docker
sudo systemctl enable docker
# 验证安装
docker --version
docker compose version
Ubuntu / Debian
# 卸载旧版本
sudo apt-get remove docker docker-engine docker.io containerd runc
# 安装依赖
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg lsb-release
# 添加 Docker GPG 密钥
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 添加仓库
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装 Docker
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 验证安装
docker --version
docker compose version
1.3 Docker 配置优化
# 创建配置目录
sudo mkdir -p /etc/docker
# 配置 Docker daemon
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://mirror.ccs.tencentyun.com",
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com"
],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
},
"storage-driver": "overlay2",
"live-restore": true,
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Hard": 65536,
"Soft": 65536
}
}
}
EOF
# 重启 Docker
sudo systemctl daemon-reload
sudo systemctl restart docker
# 添加当前用户到 docker 组(免 sudo)
sudo usermod -aG docker $USER
newgrp docker
1.4 系统参数优化
# 优化内核参数
sudo tee -a /etc/sysctl.conf <<-'EOF'
# 网络优化
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_max_tw_buckets = 5000
# 文件句柄
fs.file-max = 2097152
fs.nr_open = 2097152
# 内存优化
vm.swappiness = 10
vm.max_map_count = 262144
EOF
# 应用配置
sudo sysctl -p
# 设置文件句柄限制
sudo tee -a /etc/security/limits.conf <<-'EOF'
* soft nofile 65536
* hard nofile 65536
* soft nproc 65536
* hard nproc 65536
EOF
2. 目录结构规划
2.1 创建部署目录
# 创建主目录
sudo mkdir -p /opt/vortmall
sudo chown -R $USER:$USER /opt/vortmall
cd /opt/vortmall
# 创建子目录
mkdir -p {apps,middleware,data,logs,config,scripts,backup}
# 目录结构
/opt/vortmall/
├── apps/ # 业务服务
│ ├── docker-compose.yml # 业务服务编排
│ ├── .env # 环境变量
│ └── jars/ # JAR 包目录
├── middleware/ # 中间件
│ ├── docker-compose.yml # 中间件编排
│ ├── mysql/ # MySQL 配置
│ ├── redis/ # Redis 配置
│ ├── nacos/ # Nacos 配置
│ ├── rocketmq/ # RocketMQ 配置
│ └── ...
├── data/ # 数据持久化
│ ├── mysql/
│ ├── redis/
│ ├── nacos/
│ ├── minio/
│ └── ...
├── logs/ # 日志目录
│ ├── gateway/
│ ├── auth/
│ ├── biz-user/
│ └── ...
├── config/ # 配置文件
│ └── nacos/ # Nacos 配置导出
├── scripts/ # 运维脚本
│ ├── start.sh
│ ├── stop.sh
│ ├── backup.sh
│ └── health-check.sh
└── backup/ # 备份目录
2.2 复制项目部署文件
# 从项目中复制部署配置
cp -r /path/to/vortmall-api/deployment/DockerCompose/* /opt/vortmall/middleware/
3. 中间件部署
3.1 中间件清单
| 中间件 | 版本 | 端口 | 必需 | 说明 |
|---|---|---|---|---|
| MySQL | 8.4.1 | 3306 | 是 | 数据库 |
| Redis | latest | 6379 | 是 | 缓存 |
| Nacos | 2.5.1 | 8848, 9848 | 是 | 注册/配置中心 |
| RocketMQ | 5.2.0 | 9876, 10911 | 是 | 消息队列 |
| XXL-JOB | 2.4.1 | 8082 | 是 | 任务调度 |
| MinIO | latest | 9000, 9001 | 是 | 文件存储 |
| Seata | 2.0.0 | 7091, 8091 | 否 | 分布式事务 |
| EMQX | 5.8.3 | 1883, 18083 | 否 | MQTT 消息 |
| Elasticsearch | 8.12.0 | 9200 | 否 | 搜索引擎 |
| Kibana | 8.12.0 | 5601 | 否 | ES 可视化 |
| SkyWalking | 10.0.1 | 11800, 12800 | 否 | 链路追踪 |
3.2 中间件 docker-compose.yml
创建 /opt/vortmall/middleware/docker-compose.yml:
version: '3.8'
services:
# ==================== 核心中间件 ====================
mysql:
image: mysql:8.4.1
container_name: vortmall-mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-vortmall666}
MYSQL_CHARACTER_SET_SERVER: utf8mb4
MYSQL_COLLATION_SERVER: utf8mb4_unicode_ci
TZ: Asia/Shanghai
ports:
- "3306:3306"
volumes:
- ${DATA_PATH}/mysql/data:/var/lib/mysql
- ${DATA_PATH}/mysql/conf:/etc/mysql/conf.d
- ${DATA_PATH}/mysql/init:/docker-entrypoint-initdb.d
- /etc/localtime:/etc/localtime:ro
command:
- --default-authentication-plugin=caching_sha2_password
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --max_connections=1000
- --innodb_buffer_pool_size=512M
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD:-vortmall666}"]
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
networks:
- vortmall-network
redis:
image: redis:7-alpine
container_name: vortmall-redis
restart: always
ports:
- "6379:6379"
volumes:
- ${DATA_PATH}/redis/data:/data
- ${DATA_PATH}/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf
command: redis-server /usr/local/etc/redis/redis.conf
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
networks:
- vortmall-network
nacos:
image: nacos/nacos-server:v2.5.1
container_name: vortmall-nacos
restart: always
environment:
MODE: standalone
SPRING_DATASOURCE_PLATFORM: mysql
MYSQL_SERVICE_HOST: mysql
MYSQL_SERVICE_PORT: 3306
MYSQL_SERVICE_USER: root
MYSQL_SERVICE_PASSWORD: ${MYSQL_ROOT_PASSWORD:-vortmall666}
MYSQL_SERVICE_DB_NAME: nacos_config
MYSQL_SERVICE_DB_PARAM: characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
JVM_XMS: 512m
JVM_XMX: 512m
JVM_XMN: 256m
NACOS_AUTH_ENABLE: "true"
NACOS_AUTH_TOKEN: "VG9rZW5TZWNyZXRLZXlGb3JOYWNvc0F1dGhUb2tlbjIwMjQ="
NACOS_AUTH_IDENTITY_KEY: serverIdentity
NACOS_AUTH_IDENTITY_VALUE: vortmall
ports:
- "8848:8848"
- "9848:9848"
- "9849:9849"
volumes:
- ${DATA_PATH}/nacos/logs:/home/nacos/logs
depends_on:
mysql:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8848/nacos/v1/console/health/readiness"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
networks:
- vortmall-network
# ==================== 消息队列 ====================
rocketmq-namesrv:
image: apache/rocketmq:5.2.0
container_name: vortmall-rocketmq-namesrv
restart: always
environment:
JAVA_OPT_EXT: "-Xms512m -Xmx512m -Xmn256m"
ports:
- "9876:9876"
volumes:
- ${DATA_PATH}/rocketmq/namesrv/logs:/home/rocketmq/logs
command: sh mqnamesrv
networks:
- vortmall-network
rocketmq-broker:
image: apache/rocketmq:5.2.0
container_name: vortmall-rocketmq-broker
restart: always
environment:
JAVA_OPT_EXT: "-Xms512m -Xmx1g -Xmn256m"
NAMESRV_ADDR: rocketmq-namesrv:9876
ports:
- "10909:10909"
- "10911:10911"
- "10912:10912"
volumes:
- ${DATA_PATH}/rocketmq/broker/logs:/home/rocketmq/logs
- ${DATA_PATH}/rocketmq/broker/store:/home/rocketmq/store
- ./rocketmq/broker.conf:/home/rocketmq/conf/broker.conf
command: sh mqbroker -c /home/rocketmq/conf/broker.conf
depends_on:
- rocketmq-namesrv
networks:
- vortmall-network
rocketmq-dashboard:
image: apacherocketmq/rocketmq-dashboard:2.0.0
container_name: vortmall-rocketmq-dashboard
restart: always
environment:
JAVA_OPTS: "-Drocketmq.namesrv.addr=rocketmq-namesrv:9876"
ports:
- "8080:8080"
depends_on:
- rocketmq-namesrv
- rocketmq-broker
networks:
- vortmall-network
# ==================== 任务调度 ====================
xxl-job-admin:
image: xuxueli/xxl-job-admin:2.4.1
container_name: vortmall-xxl-job
restart: always
environment:
PARAMS: >-
--spring.datasource.url=jdbc:mysql://mysql:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
--spring.datasource.username=root
--spring.datasource.password=${MYSQL_ROOT_PASSWORD:-vortmall666}
--xxl.job.accessToken=vortmall-xxl-job-token
ports:
- "8082:8080"
volumes:
- ${DATA_PATH}/xxl-job/logs:/data/applogs
depends_on:
mysql:
condition: service_healthy
networks:
- vortmall-network
# ==================== 文件存储 ====================
minio:
image: minio/minio:latest
container_name: vortmall-minio
restart: always
environment:
MINIO_ROOT_USER: ${MINIO_USER:-vortmall}
MINIO_ROOT_PASSWORD: ${MINIO_PASSWORD:-vortmall666}
ports:
- "9000:9000"
- "9001:9001"
volumes:
- ${DATA_PATH}/minio/data:/data
command: server /data --console-address ":9001"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 10s
retries: 3
networks:
- vortmall-network
# ==================== 分布式事务 ====================
seata-server:
image: seataio/seata-server:2.0.0
container_name: vortmall-seata
restart: always
environment:
STORE_MODE: db
SEATA_IP: ${HOST_IP}
SEATA_PORT: 8091
ports:
- "7091:7091"
- "8091:8091"
volumes:
- ./seata/application.yml:/seata-server/resources/application.yml
- ${DATA_PATH}/seata/logs:/seata-server/logs
depends_on:
mysql:
condition: service_healthy
nacos:
condition: service_healthy
networks:
- vortmall-network
# ==================== MQTT 消息服务 ====================
emqx:
image: emqx/emqx:5.8.3
container_name: vortmall-emqx
restart: always
environment:
EMQX_NAME: emqx
EMQX_HOST: ${HOST_IP}
EMQX_DASHBOARD__DEFAULT_USERNAME: admin
EMQX_DASHBOARD__DEFAULT_PASSWORD: ${EMQX_PASSWORD:-vortmall666}
ports:
- "1883:1883"
- "8083:8083"
- "8084:8084"
- "8883:8883"
- "18083:18083"
volumes:
- ${DATA_PATH}/emqx/data:/opt/emqx/data
- ${DATA_PATH}/emqx/log:/opt/emqx/log
healthcheck:
test: ["CMD", "emqx", "ctl", "status"]
interval: 30s
timeout: 10s
retries: 5
networks:
- vortmall-network
# ==================== 搜索引擎 ====================
elasticsearch:
image: elasticsearch:8.12.0
container_name: vortmall-es
restart: always
environment:
- discovery.type=single-node
- ES_JAVA_OPTS=-Xms512m -Xmx1g
- ELASTIC_PASSWORD=${ES_PASSWORD:-vortmall666}
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=false
- TZ=Asia/Shanghai
ports:
- "9200:9200"
- "9300:9300"
volumes:
- ${DATA_PATH}/elasticsearch/data:/usr/share/elasticsearch/data
- ${DATA_PATH}/elasticsearch/plugins:/usr/share/elasticsearch/plugins
- ${DATA_PATH}/elasticsearch/logs:/usr/share/elasticsearch/logs
healthcheck:
test: ["CMD-SHELL", "curl -u elastic:${ES_PASSWORD:-vortmall666} -s http://localhost:9200/_cluster/health | grep -q 'green\\|yellow'"]
interval: 30s
timeout: 10s
retries: 10
start_period: 60s
networks:
- vortmall-network
kibana:
image: kibana:8.12.0
container_name: vortmall-kibana
restart: always
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
- ELASTICSEARCH_USERNAME=kibana_system
- ELASTICSEARCH_PASSWORD=${ES_PASSWORD:-vortmall666}
- I18N_LOCALE=zh-CN
- TZ=Asia/Shanghai
ports:
- "5601:5601"
depends_on:
elasticsearch:
condition: service_healthy
networks:
- vortmall-network
# ==================== 链路追踪 ====================
skywalking-oap:
image: apache/skywalking-oap-server:10.0.1
container_name: vortmall-skywalking-oap
restart: always
environment:
SW_STORAGE: elasticsearch
SW_STORAGE_ES_CLUSTER_NODES: elasticsearch:9200
SW_ES_USER: elastic
SW_ES_PASSWORD: ${ES_PASSWORD:-vortmall666}
TZ: Asia/Shanghai
SW_CORE_RECORD_DATA_TTL: 3
SW_CORE_METRICS_DATA_TTL: 7
ports:
- "11800:11800"
- "12800:12800"
depends_on:
elasticsearch:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:12800/healthcheck || exit 1"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
networks:
- vortmall-network
skywalking-ui:
image: apache/skywalking-ui:10.0.1
container_name: vortmall-skywalking-ui
restart: always
environment:
SW_OAP_ADDRESS: http://skywalking-oap:12800
TZ: Asia/Shanghai
ports:
- "18080:8080"
depends_on:
skywalking-oap:
condition: service_healthy
networks:
- vortmall-network
networks:
vortmall-network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
3.3 环境变量配置
创建 /opt/vortmall/middleware/.env:
# 主机 IP(请修改为实际 IP)
HOST_IP=192.168.1.100
# 数据目录
DATA_PATH=/opt/vortmall/data
# MySQL
MYSQL_ROOT_PASSWORD=vortmall666
# MinIO
MINIO_USER=vortmall
MINIO_PASSWORD=vortmall666
# Elasticsearch
ES_PASSWORD=vortmall666
# EMQX
EMQX_PASSWORD=vortmall666
3.4 配置文件准备
MySQL 配置
创建 /opt/vortmall/data/mysql/conf/my.cnf:
[mysqld]
# 基础配置
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
default-time-zone='+08:00'
# 连接配置
max_connections=1000
max_connect_errors=100
# InnoDB 配置
innodb_buffer_pool_size=512M
innodb_log_file_size=256M
innodb_flush_log_at_trx_commit=2
innodb_lock_wait_timeout=50
# 日志配置
slow_query_log=1
slow_query_log_file=/var/log/mysql/slow.log
long_query_time=2
log_queries_not_using_indexes=1
# Binlog 配置
server-id=1
log-bin=mysql-bin
binlog_format=ROW
expire_logs_days=7
[mysql]
default-character-set=utf8mb4
[client]
default-character-set=utf8mb4
Redis 配置
创建 /opt/vortmall/data/redis/conf/redis.conf:
# 绑定地址
bind 0.0.0.0
# 端口
port 6379
# 密码(生产环境建议设置)
# requirepass vortmall666
# 持久化
appendonly yes
appendfsync everysec
# 内存配置
maxmemory 1gb
maxmemory-policy allkeys-lru
# 日志
loglevel notice
# 连接
tcp-keepalive 300
timeout 0
RocketMQ Broker 配置
创建 /opt/vortmall/middleware/rocketmq/broker.conf:
brokerClusterName=DefaultCluster
brokerName=broker-a
brokerId=0
deleteWhen=04
fileReservedTime=48
brokerRole=ASYNC_MASTER
flushDiskType=ASYNC_FLUSH
# 需要修改为实际 IP
namesrvAddr=rocketmq-namesrv:9876
brokerIP1=192.168.1.100
# 自动创建 Topic
autoCreateTopicEnable=true
autoCreateSubscriptionGroup=true
3.5 初始化数据库脚本
创建 /opt/vortmall/data/mysql/init/01-init-databases.sql:
-- 创建 Nacos 数据库
CREATE DATABASE IF NOT EXISTS `nacos_config` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 创建 XXL-JOB 数据库
CREATE DATABASE IF NOT EXISTS `xxl_job` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 创建 Seata 数据库
CREATE DATABASE IF NOT EXISTS `seata` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 创建业务数据库
CREATE DATABASE IF NOT EXISTS `vortmall-user` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS `vortmall-product` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS `vortmall-order` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS `vortmall-payment` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS `vortmall-system` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS `vortmall-marketing` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS `vortmall-content` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS `vortmall-organize` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS `vortmall-logistics` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS `vortmall-aftersales` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS `vortmall-distribution` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS `vortmall-decoration` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS `vortmall-message` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS `vortmall-file` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS `vortmall-pos` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 创建应用账号
CREATE USER IF NOT EXISTS 'vortmall'@'%' IDENTIFIED BY 'vortmall666';
GRANT ALL PRIVILEGES ON `vortmall-%`.* TO 'vortmall'@'%';
GRANT ALL PRIVILEGES ON `nacos_config`.* TO 'vortmall'@'%';
GRANT ALL PRIVILEGES ON `xxl_job`.* TO 'vortmall'@'%';
GRANT ALL PRIVILEGES ON `seata`.* TO 'vortmall'@'%';
FLUSH PRIVILEGES;
3.6 启动中间件
cd /opt/vortmall/middleware
# 第一步:启动核心中间件
docker compose up -d mysql redis
# 等待 MySQL 完全启动(查看日志)
docker compose logs -f mysql
# 看到 "ready for connections" 后 Ctrl+C 退出
# 第二步:启动 Nacos
docker compose up -d nacos
# 等待 Nacos 启动完成
docker compose logs -f nacos
# 看到 "Nacos started successfully" 后 Ctrl+C 退出
# 第三步:启动消息队列和其他服务
docker compose up -d rocketmq-namesrv rocketmq-broker rocketmq-dashboard
docker compose up -d xxl-job-admin minio
# 第四步(可选):启动扩展服务
docker compose up -d seata-server emqx
docker compose up -d elasticsearch kibana
docker compose up -d skywalking-oap skywalking-ui
# 查看所有容器状态
docker compose ps
4. 镜像构建
4.1 基础 Dockerfile
创建 /opt/vortmall/apps/Dockerfile.base(通用基础镜像):
FROM eclipse-temurin:21-jre-alpine
LABEL maintainer="VortMall Team <admin@vortmall.com>"
# 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 安装常用工具
RUN apk add --no-cache curl tzdata
# 创建应用用户
RUN addgroup -g 1000 vortmall && \
adduser -u 1000 -G vortmall -s /bin/sh -D vortmall
# 创建目录
RUN mkdir -p /app/logs && chown -R vortmall:vortmall /app
# 设置工作目录
WORKDIR /app
# 切换用户
USER vortmall
# 健康检查(子镜像覆盖)
HEALTHCHECK --interval=30s --timeout=10s --retries=3 --start-period=60s \
CMD curl -sf http://localhost:8080/actuator/health || exit 1
4.2 服务 Dockerfile 模板
创建各服务的 Dockerfile,以 Gateway 为例 /opt/vortmall/apps/gateway/Dockerfile:
FROM vortmall/base:latest
LABEL service="vortmall-gateway"
# 设置 JVM 参数
ENV JAVA_OPTS="-Xms512m -Xmx512m -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/app/logs/heapdump.hprof"
# 复制 JAR 包
COPY --chown=vortmall:vortmall vortmall-gateway-*.jar app.jar
# 暴露端口
EXPOSE 8000
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --retries=3 --start-period=60s \
CMD curl -sf http://localhost:8000/actuator/health || exit 1
# 启动命令
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar app.jar"]
4.3 批量构建脚本
创建 /opt/vortmall/scripts/build-images.sh:
#!/bin/bash
set -e
# 配置
REGISTRY="registry.cn-hangzhou.aliyuncs.com/vortmall"
VERSION="${1:-latest}"
PROJECT_PATH="${2:-/path/to/vortmall-api}"
echo "========================================"
echo "VortMall Docker 镜像构建"
echo "版本: $VERSION"
echo "========================================"
# 编译项目
echo ">>> 编译项目..."
cd $PROJECT_PATH
mvn clean package -DskipTests -T 4
# 构建基础镜像
echo ">>> 构建基础镜像..."
docker build -t vortmall/base:latest -f /opt/vortmall/apps/Dockerfile.base .
# 服务列表
declare -A SERVICES=(
["gateway"]="vortmall-gateway/target"
["auth"]="vortmall-auth/target"
["biz-user"]="vortmall-biz/vortmall-biz-user/target"
["biz-product"]="vortmall-biz/vortmall-biz-product/target"
["biz-order"]="vortmall-biz/vortmall-biz-order/target"
["biz-payment"]="vortmall-biz/vortmall-biz-payment/target"
["biz-system"]="vortmall-biz/vortmall-biz-system/target"
["biz-marketing"]="vortmall-biz/vortmall-biz-marketing/target"
["biz-content"]="vortmall-biz/vortmall-biz-content/target"
["biz-organize"]="vortmall-biz/vortmall-biz-organize/target"
["biz-logistics"]="vortmall-biz/vortmall-biz-logistics/target"
["biz-aftersales"]="vortmall-biz/vortmall-biz-aftersales/target"
["biz-distribution"]="vortmall-biz/vortmall-biz-distribution/target"
["biz-decoration"]="vortmall-biz/vortmall-biz-decoration/target"
["biz-message"]="vortmall-biz/vortmall-biz-message/target"
["biz-file"]="vortmall-biz/vortmall-biz-file/target"
["biz-pos"]="vortmall-biz/vortmall-biz-pos/target"
)
# 构建服务镜像
for SERVICE in "${!SERVICES[@]}"; do
JAR_PATH="${SERVICES[$SERVICE]}"
IMAGE_NAME="vortmall/$SERVICE:$VERSION"
echo ">>> 构建镜像: $IMAGE_NAME"
# 创建临时构建目录
BUILD_DIR="/tmp/vortmall-build-$SERVICE"
mkdir -p $BUILD_DIR
# 复制 JAR 和 Dockerfile
cp $PROJECT_PATH/$JAR_PATH/*.jar $BUILD_DIR/
# 生成 Dockerfile
cat > $BUILD_DIR/Dockerfile <<EOF
FROM vortmall/base:latest
LABEL service="vortmall-$SERVICE"
ENV JAVA_OPTS="-Xms256m -Xmx256m -XX:+UseG1GC"
COPY --chown=vortmall:vortmall *.jar app.jar
EXPOSE 8080
ENTRYPOINT ["sh", "-c", "java \$JAVA_OPTS -jar app.jar"]
EOF
# 构建镜像
docker build -t $IMAGE_NAME $BUILD_DIR
# 清理
rm -rf $BUILD_DIR
echo ">>> 完成: $IMAGE_NAME"
done
echo "========================================"
echo "所有镜像构建完成!"
echo "========================================"
# 列出构建的镜像
docker images | grep vortmall
4.4 推送到镜像仓库
# 登录阿里云镜像仓库
docker login --username=your-username registry.cn-hangzhou.aliyuncs.com
# 标记镜像
docker tag vortmall/gateway:latest registry.cn-hangzhou.aliyuncs.com/vortmall/gateway:latest
# 推送镜像
docker push registry.cn-hangzhou.aliyuncs.com/vortmall/gateway:latest
# 批量推送脚本
for image in $(docker images --format "{{.Repository}}:{{.Tag}}" | grep "^vortmall/"); do
remote_image="registry.cn-hangzhou.aliyuncs.com/$image"
docker tag $image $remote_image
docker push $remote_image
done
5. 业务服务部署
5.1 业务服务 docker-compose.yml
创建 /opt/vortmall/apps/docker-compose.yml:
version: '3.8'
services:
# ==================== 核心服务 ====================
gateway:
image: vortmall/gateway:${VERSION:-latest}
container_name: vortmall-gateway
restart: always
environment:
- SPRING_PROFILES_ACTIVE=prod
- VORTMALL_HOST=${MIDDLEWARE_HOST}
- JAVA_OPTS=-Xms512m -Xmx512m
- TZ=Asia/Shanghai
ports:
- "8000:8000"
volumes:
- ${LOG_PATH}/gateway:/app/logs
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:8000/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
networks:
- vortmall-network
depends_on:
- auth
auth:
image: vortmall/auth:${VERSION:-latest}
container_name: vortmall-auth
restart: always
environment:
- SPRING_PROFILES_ACTIVE=prod
- VORTMALL_HOST=${MIDDLEWARE_HOST}
- JAVA_OPTS=-Xms256m -Xmx256m
- TZ=Asia/Shanghai
ports:
- "8001:8001"
volumes:
- ${LOG_PATH}/auth:/app/logs
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:8001/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
networks:
- vortmall-network
# ==================== 业务服务 ====================
biz-user:
image: vortmall/biz-user:${VERSION:-latest}
container_name: vortmall-biz-user
restart: always
environment:
- SPRING_PROFILES_ACTIVE=prod
- VORTMALL_HOST=${MIDDLEWARE_HOST}
- JAVA_OPTS=-Xms512m -Xmx512m
- TZ=Asia/Shanghai
ports:
- "19913:19913"
volumes:
- ${LOG_PATH}/biz-user:/app/logs
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:19913/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
networks:
- vortmall-network
biz-product:
image: vortmall/biz-product:${VERSION:-latest}
container_name: vortmall-biz-product
restart: always
environment:
- SPRING_PROFILES_ACTIVE=prod
- VORTMALL_HOST=${MIDDLEWARE_HOST}
- JAVA_OPTS=-Xms512m -Xmx512m
- TZ=Asia/Shanghai
ports:
- "19901:19901"
volumes:
- ${LOG_PATH}/biz-product:/app/logs
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:19901/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
networks:
- vortmall-network
biz-order:
image: vortmall/biz-order:${VERSION:-latest}
container_name: vortmall-biz-order
restart: always
environment:
- SPRING_PROFILES_ACTIVE=prod
- VORTMALL_HOST=${MIDDLEWARE_HOST}
- JAVA_OPTS=-Xms512m -Xmx512m
- TZ=Asia/Shanghai
ports:
- "19905:19905"
volumes:
- ${LOG_PATH}/biz-order:/app/logs
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:19905/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
networks:
- vortmall-network
biz-payment:
image: vortmall/biz-payment:${VERSION:-latest}
container_name: vortmall-biz-payment
restart: always
environment:
- SPRING_PROFILES_ACTIVE=prod
- VORTMALL_HOST=${MIDDLEWARE_HOST}
- JAVA_OPTS=-Xms256m -Xmx256m
- TZ=Asia/Shanghai
ports:
- "19902:19902"
volumes:
- ${LOG_PATH}/biz-payment:/app/logs
networks:
- vortmall-network
biz-system:
image: vortmall/biz-system:${VERSION:-latest}
container_name: vortmall-biz-system
restart: always
environment:
- SPRING_PROFILES_ACTIVE=prod
- VORTMALL_HOST=${MIDDLEWARE_HOST}
- JAVA_OPTS=-Xms256m -Xmx256m
- TZ=Asia/Shanghai
ports:
- "19903:19903"
volumes:
- ${LOG_PATH}/biz-system:/app/logs
networks:
- vortmall-network
biz-marketing:
image: vortmall/biz-marketing:${VERSION:-latest}
container_name: vortmall-biz-marketing
restart: always
environment:
- SPRING_PROFILES_ACTIVE=prod
- VORTMALL_HOST=${MIDDLEWARE_HOST}
- JAVA_OPTS=-Xms256m -Xmx256m
- TZ=Asia/Shanghai
ports:
- "19904:19904"
volumes:
- ${LOG_PATH}/biz-marketing:/app/logs
networks:
- vortmall-network
biz-content:
image: vortmall/biz-content:${VERSION:-latest}
container_name: vortmall-biz-content
restart: always
environment:
- SPRING_PROFILES_ACTIVE=prod
- VORTMALL_HOST=${MIDDLEWARE_HOST}
- JAVA_OPTS=-Xms256m -Xmx256m
- TZ=Asia/Shanghai
ports:
- "19906:19906"
volumes:
- ${LOG_PATH}/biz-content:/app/logs
networks:
- vortmall-network
biz-organize:
image: vortmall/biz-organize:${VERSION:-latest}
container_name: vortmall-biz-organize
restart: always
environment:
- SPRING_PROFILES_ACTIVE=prod
- VORTMALL_HOST=${MIDDLEWARE_HOST}
- JAVA_OPTS=-Xms256m -Xmx256m
- TZ=Asia/Shanghai
ports:
- "19907:19907"
volumes:
- ${LOG_PATH}/biz-organize:/app/logs
networks:
- vortmall-network
biz-logistics:
image: vortmall/biz-logistics:${VERSION:-latest}
container_name: vortmall-biz-logistics
restart: always
environment:
- SPRING_PROFILES_ACTIVE=prod
- VORTMALL_HOST=${MIDDLEWARE_HOST}
- JAVA_OPTS=-Xms256m -Xmx256m
- TZ=Asia/Shanghai
ports:
- "19908:19908"
volumes:
- ${LOG_PATH}/biz-logistics:/app/logs
networks:
- vortmall-network
biz-aftersales:
image: vortmall/biz-aftersales:${VERSION:-latest}
container_name: vortmall-biz-aftersales
restart: always
environment:
- SPRING_PROFILES_ACTIVE=prod
- VORTMALL_HOST=${MIDDLEWARE_HOST}
- JAVA_OPTS=-Xms256m -Xmx256m
- TZ=Asia/Shanghai
ports:
- "19909:19909"
volumes:
- ${LOG_PATH}/biz-aftersales:/app/logs
networks:
- vortmall-network
biz-distribution:
image: vortmall/biz-distribution:${VERSION:-latest}
container_name: vortmall-biz-distribution
restart: always
environment:
- SPRING_PROFILES_ACTIVE=prod
- VORTMALL_HOST=${MIDDLEWARE_HOST}
- JAVA_OPTS=-Xms256m -Xmx256m
- TZ=Asia/Shanghai
ports:
- "19910:19910"
volumes:
- ${LOG_PATH}/biz-distribution:/app/logs
networks:
- vortmall-network
biz-decoration:
image: vortmall/biz-decoration:${VERSION:-latest}
container_name: vortmall-biz-decoration
restart: always
environment:
- SPRING_PROFILES_ACTIVE=prod
- VORTMALL_HOST=${MIDDLEWARE_HOST}
- JAVA_OPTS=-Xms256m -Xmx256m
- TZ=Asia/Shanghai
ports:
- "19911:19911"
volumes:
- ${LOG_PATH}/biz-decoration:/app/logs
networks:
- vortmall-network
biz-message:
image: vortmall/biz-message:${VERSION:-latest}
container_name: vortmall-biz-message
restart: always
environment:
- SPRING_PROFILES_ACTIVE=prod
- VORTMALL_HOST=${MIDDLEWARE_HOST}
- JAVA_OPTS=-Xms256m -Xmx256m
- TZ=Asia/Shanghai
ports:
- "19912:19912"
volumes:
- ${LOG_PATH}/biz-message:/app/logs
networks:
- vortmall-network
biz-file:
image: vortmall/biz-file:${VERSION:-latest}
container_name: vortmall-biz-file
restart: always
environment:
- SPRING_PROFILES_ACTIVE=prod
- VORTMALL_HOST=${MIDDLEWARE_HOST}
- JAVA_OPTS=-Xms256m -Xmx256m
- TZ=Asia/Shanghai
ports:
- "19914:19914"
volumes:
- ${LOG_PATH}/biz-file:/app/logs
networks:
- vortmall-network
biz-pos:
image: vortmall/biz-pos:${VERSION:-latest}
container_name: vortmall-biz-pos
restart: always
environment:
- SPRING_PROFILES_ACTIVE=prod
- VORTMALL_HOST=${MIDDLEWARE_HOST}
- JAVA_OPTS=-Xms256m -Xmx256m
- TZ=Asia/Shanghai
ports:
- "19915:19915"
volumes:
- ${LOG_PATH}/biz-pos:/app/logs
networks:
- vortmall-network
networks:
vortmall-network:
external: true
name: middleware_vortmall-network
5.2 业务服务环境变量
创建 /opt/vortmall/apps/.env:
# 版本号
VERSION=latest
# 中间件服务器地址
MIDDLEWARE_HOST=192.168.1.100
# 日志目录
LOG_PATH=/opt/vortmall/logs
5.3 启动业务服务
cd /opt/vortmall/apps
# 启动所有服务
docker compose up -d
# 查看服务状态
docker compose ps
# 查看日志
docker compose logs -f gateway
6. 网络配置
6.1 Docker 网络架构
┌─────────────────────────────────────────────────────────────────────────┐
│ Docker Network: vortmall-network │
│ (172.20.0.0/16) │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 中间件服务 │ │
│ │ │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ MySQL │ │ Redis │ │ Nacos │ │RocketMQ │ │ MinIO │ │ │
│ │ │ :3306 │ │ :6379 │ │ :8848 │ │ :9876 │ │ :9000 │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ 内网通信 │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 业务服务 │ │
│ │ │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Gateway │ │ Auth │ │ User │ │ Product │ │ Order │ │ │
│ │ │ :8000 │ │ :8001 │ │ :19913 │ │ :19901 │ │ :19905 │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │
│ │ │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Payment │ │ System │ │Marketing│ │ Content │ │ ... │ │ │
│ │ │ :19902 │ │ :19903 │ │ :19904 │ │ :19906 │ │ │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
└───────────────────────────────────│─────────────────────────────────────┘
│ 端口映射
▼
┌───────────────────────────────┐
│ 宿主机端口 │
│ 8000, 8848, 3306, 6379... │
└───────────────────────────────┘
6.2 创建 Docker 网络
# 创建自定义网络
docker network create --driver bridge --subnet 172.20.0.0/16 vortmall-network
# 查看网络
docker network ls
# 查看网络详情
docker network inspect vortmall-network
6.3 服务间通信
容器间通过服务名称直接访问:
# 应用配置示例
spring:
datasource:
url: jdbc:mysql://vortmall-mysql:3306/vortmall-user
redis:
host: vortmall-redis
cloud:
nacos:
discovery:
server-addr: vortmall-nacos:8848
7. 数据持久化
7.1 数据目录结构
/opt/vortmall/data/
├── mysql/
│ ├── data/ # MySQL 数据文件
│ ├── conf/ # MySQL 配置
│ └── init/ # 初始化脚本
├── redis/
│ ├── data/ # Redis 数据
│ └── conf/ # Redis 配置
├── nacos/
│ └── logs/ # Nacos 日志
├── rocketmq/
│ ├── namesrv/logs/ # NameServer 日志
│ └── broker/
│ ├── logs/ # Broker 日志
│ └── store/ # 消息存储
├── minio/
│ └── data/ # MinIO 数据
├── elasticsearch/
│ ├── data/ # ES 数据
│ ├── plugins/ # ES 插件
│ └── logs/ # ES 日志
├── seata/
│ └── logs/ # Seata 日志
└── emqx/
├── data/ # EMQX 数据
└── log/ # EMQX 日志
7.2 备份策略
创建 /opt/vortmall/scripts/backup.sh:
#!/bin/bash
set -e
# 配置
BACKUP_DIR="/opt/vortmall/backup"
DATE=$(date +%Y%m%d_%H%M%S)
MYSQL_CONTAINER="vortmall-mysql"
MYSQL_PASSWORD="vortmall666"
# 创建备份目录
mkdir -p $BACKUP_DIR/$DATE
echo "=========================================="
echo "VortMall 数据备份 - $DATE"
echo "=========================================="
# 1. 备份 MySQL
echo ">>> 备份 MySQL..."
docker exec $MYSQL_CONTAINER mysqldump -uroot -p$MYSQL_PASSWORD \
--all-databases \
--single-transaction \
--quick \
--lock-tables=false \
> $BACKUP_DIR/$DATE/mysql_all_databases.sql
# 压缩 SQL 文件
gzip $BACKUP_DIR/$DATE/mysql_all_databases.sql
echo "MySQL 备份完成: mysql_all_databases.sql.gz"
# 2. 备份 Redis
echo ">>> 备份 Redis..."
docker exec vortmall-redis redis-cli BGSAVE
sleep 5
docker cp vortmall-redis:/data/dump.rdb $BACKUP_DIR/$DATE/redis_dump.rdb
echo "Redis 备份完成: redis_dump.rdb"
# 3. 备份 Nacos 配置
echo ">>> 备份 Nacos 配置..."
curl -X GET "http://localhost:8848/nacos/v1/cs/configs?dataId=&group=&appName=&config_tags=&pageNo=1&pageSize=100&tenant=&search=blur" \
-u nacos:nacos \
-o $BACKUP_DIR/$DATE/nacos_config.json 2>/dev/null || echo "Nacos 备份需要手动导出"
# 4. 备份 MinIO 数据
echo ">>> 备份 MinIO..."
tar -czf $BACKUP_DIR/$DATE/minio_data.tar.gz -C /opt/vortmall/data minio/
# 5. 计算备份大小
BACKUP_SIZE=$(du -sh $BACKUP_DIR/$DATE | cut -f1)
echo "备份大小: $BACKUP_SIZE"
# 6. 清理旧备份(保留 7 天)
echo ">>> 清理旧备份..."
find $BACKUP_DIR -type d -mtime +7 -exec rm -rf {} + 2>/dev/null || true
echo "=========================================="
echo "备份完成!"
echo "备份目录: $BACKUP_DIR/$DATE"
echo "=========================================="
7.3 定时备份
# 设置执行权限
chmod +x /opt/vortmall/scripts/backup.sh
# 添加定时任务(每天凌晨 3 点)
crontab -e
0 3 * * * /opt/vortmall/scripts/backup.sh >> /opt/vortmall/logs/backup.log 2>&1
8. 日志管理
8.1 日志目录结构
/opt/vortmall/logs/
├── gateway/
│ ├── app.log # 应用日志
│ ├── error.log # 错误日志
│ └── gc.log # GC 日志
├── auth/
├── biz-user/
├── biz-product/
├── biz-order/
└── ...
8.2 日志轮转配置
创建 /etc/logrotate.d/vortmall:
/opt/vortmall/logs/*/*.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 0644 vortmall vortmall
sharedscripts
postrotate
# 如果需要通知应用
endscript
}
8.3 日志查看命令
# 查看容器日志
docker logs -f vortmall-gateway
# 查看最近 100 行
docker logs --tail 100 vortmall-gateway
# 查看指定时间段
docker logs --since="2024-01-01T00:00:00" --until="2024-01-01T01:00:00" vortmall-gateway
# 实时查看多个服务日志
docker compose logs -f gateway auth biz-user
# 查看应用日志文件
tail -f /opt/vortmall/logs/gateway/app.log
# 搜索错误日志
grep -r "ERROR" /opt/vortmall/logs/*/error.log
9. 健康检查与监控
9.1 健康检查脚本
创建 /opt/vortmall/scripts/health-check.sh:
#!/bin/bash
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo "=========================================="
echo "VortMall 健康检查 - $(date '+%Y-%m-%d %H:%M:%S')"
echo "=========================================="
# 中间件检查
echo -e "\n${YELLOW}>>> 中间件状态${NC}"
check_service() {
local name=$1
local url=$2
local response=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 "$url" 2>/dev/null)
if [ "$response" == "200" ] || [ "$response" == "301" ] || [ "$response" == "302" ]; then
echo -e "${GREEN}[OK]${NC} $name"
return 0
else
echo -e "${RED}[FAIL]${NC} $name (HTTP $response)"
return 1
fi
}
check_tcp() {
local name=$1
local host=$2
local port=$3
if nc -z -w 5 $host $port 2>/dev/null; then
echo -e "${GREEN}[OK]${NC} $name ($host:$port)"
return 0
else
echo -e "${RED}[FAIL]${NC} $name ($host:$port)"
return 1
fi
}
# 中间件
check_tcp "MySQL" "localhost" 3306
check_tcp "Redis" "localhost" 6379
check_service "Nacos" "http://localhost:8848/nacos/v1/console/health/readiness"
check_tcp "RocketMQ NameServer" "localhost" 9876
check_service "XXL-JOB" "http://localhost:8082/xxl-job-admin"
check_service "MinIO" "http://localhost:9000/minio/health/live"
# 业务服务检查
echo -e "\n${YELLOW}>>> 业务服务状态${NC}"
declare -A SERVICES=(
["Gateway"]="http://localhost:8000/actuator/health"
["Auth"]="http://localhost:8001/actuator/health"
["User"]="http://localhost:19913/actuator/health"
["Product"]="http://localhost:19901/actuator/health"
["Order"]="http://localhost:19905/actuator/health"
["Payment"]="http://localhost:19902/actuator/health"
["System"]="http://localhost:19903/actuator/health"
["Marketing"]="http://localhost:19904/actuator/health"
)
FAILED=0
for SERVICE in "${!SERVICES[@]}"; do
if ! check_service "$SERVICE" "${SERVICES[$SERVICE]}"; then
FAILED=$((FAILED + 1))
fi
done
# Docker 容器状态
echo -e "\n${YELLOW}>>> Docker 容器状态${NC}"
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep vortmall
# 资源使用情况
echo -e "\n${YELLOW}>>> 资源使用情况${NC}"
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}" | grep vortmall
# 磁盘使用
echo -e "\n${YELLOW}>>> 磁盘使用${NC}"
df -h /opt/vortmall
# 总结
echo -e "\n=========================================="
if [ $FAILED -eq 0 ]; then
echo -e "${GREEN}所有服务正常运行!${NC}"
else
echo -e "${RED}有 $FAILED 个服务异常,请检查!${NC}"
fi
echo "=========================================="
9.2 Prometheus + Grafana 监控(可选)
创建 /opt/vortmall/middleware/monitoring/docker-compose.yml:
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
container_name: vortmall-prometheus
restart: always
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
- '--web.console.templates=/usr/share/prometheus/consoles'
networks:
- vortmall-network
grafana:
image: grafana/grafana:latest
container_name: vortmall-grafana
restart: always
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=vortmall666
volumes:
- grafana_data:/var/lib/grafana
networks:
- vortmall-network
volumes:
prometheus_data:
grafana_data:
networks:
vortmall-network:
external: true
name: middleware_vortmall-network
10. 运维操作
10.1 一键启动脚本
创建 /opt/vortmall/scripts/start.sh:
#!/bin/bash
set -e
echo "=========================================="
echo "VortMall 一键启动"
echo "=========================================="
cd /opt/vortmall
# 启动中间件
echo ">>> 启动中间件..."
cd middleware
docker compose up -d mysql redis
sleep 30
docker compose up -d nacos
sleep 30
docker compose up -d rocketmq-namesrv rocketmq-broker xxl-job-admin minio
sleep 10
# 启动业务服务
echo ">>> 启动业务服务..."
cd ../apps
docker compose up -d
# 等待服务启动
echo ">>> 等待服务启动(60秒)..."
sleep 60
# 健康检查
echo ">>> 执行健康检查..."
/opt/vortmall/scripts/health-check.sh
echo "=========================================="
echo "启动完成!"
echo "=========================================="
10.2 一键停止脚本
创建 /opt/vortmall/scripts/stop.sh:
#!/bin/bash
echo "=========================================="
echo "VortMall 一键停止"
echo "=========================================="
cd /opt/vortmall
# 停止业务服务
echo ">>> 停止业务服务..."
cd apps
docker compose down
# 停止中间件
echo ">>> 停止中间件..."
cd ../middleware
docker compose down
echo "=========================================="
echo "停止完成!"
echo "=========================================="
10.3 服务更新脚本
创建 /opt/vortmall/scripts/update.sh:
#!/bin/bash
SERVICE=$1
VERSION=${2:-latest}
if [ -z "$SERVICE" ]; then
echo "用法: $0 <服务名> [版本号]"
echo "示例: $0 gateway 1.0.1"
exit 1
fi
echo "=========================================="
echo "更新服务: $SERVICE"
echo "版本: $VERSION"
echo "=========================================="
cd /opt/vortmall/apps
# 拉取新镜像
echo ">>> 拉取镜像..."
docker compose pull $SERVICE
# 重启服务
echo ">>> 重启服务..."
docker compose up -d --no-deps $SERVICE
# 等待启动
sleep 30
# 检查状态
echo ">>> 检查状态..."
docker compose ps $SERVICE
echo "=========================================="
echo "更新完成!"
echo "=========================================="
10.4 常用运维命令
# 查看所有容器
docker ps -a | grep vortmall
# 重启单个服务
docker compose -f /opt/vortmall/apps/docker-compose.yml restart gateway
# 查看服务日志
docker logs -f vortmall-gateway --tail 100
# 进入容器
docker exec -it vortmall-gateway sh
# 查看资源使用
docker stats --no-stream | grep vortmall
# 清理无用镜像
docker image prune -a
# 清理无用卷
docker volume prune
# 查看网络
docker network inspect middleware_vortmall-network
11. 常见问题
Q1: 容器启动后立即退出
排查步骤:
# 查看容器日志
docker logs vortmall-gateway
# 查看容器详情
docker inspect vortmall-gateway
# 检查退出代码
docker ps -a | grep vortmall-gateway
常见原因:
- 内存不足:增加 JVM 堆内存或服务器内存
- 配置错误:检查环境变量和配置文件
- 依赖服务未启动:确保 Nacos、MySQL 等已启动
Q2: 服务注册不到 Nacos
排查:
# 检查 Nacos 状态
curl http://localhost:8848/nacos/v1/console/health/readiness
# 检查网络连通性
docker exec vortmall-gateway ping vortmall-nacos
# 检查服务列表
curl "http://localhost:8848/nacos/v1/ns/service/list?pageNo=1&pageSize=10"
Q3: MySQL 连接失败
排查:
# 检查 MySQL 容器
docker logs vortmall-mysql
# 测试连接
docker exec vortmall-mysql mysql -uroot -pvortmall666 -e "show databases;"
# 检查网络
docker exec vortmall-gateway nc -zv vortmall-mysql 3306
Q4: 端口被占用
# 查看端口占用
netstat -tlnp | grep 8000
# 或者
ss -tlnp | grep 8000
# 停止占用进程
kill -9 <PID>
Q5: 磁盘空间不足
# 查看磁盘使用
df -h
# 清理 Docker
docker system prune -a --volumes
# 清理日志
truncate -s 0 /opt/vortmall/logs/*/*.log
Q6: 内存不足
# 查看内存使用
free -h
# 查看容器内存
docker stats --no-stream
# 调整 JVM 参数(在 docker-compose.yml 中)
environment:
- JAVA_OPTS=-Xms256m -Xmx256m
Q7: 时区问题
确保所有容器设置正确时区:
environment:
- TZ=Asia/Shanghai
volumes:
- /etc/localtime:/etc/localtime:ro
附录
A. 端口清单
| 服务 | 端口 | 说明 |
|---|---|---|
| Gateway | 8000 | API 网关 |
| Auth | 8001 | 认证服务 |
| MySQL | 3306 | 数据库 |
| Redis | 6379 | 缓存 |
| Nacos | 8848, 9848 | 注册中心 |
| RocketMQ | 9876, 10911 | 消息队列 |
| XXL-JOB | 8082 | 任务调度 |
| MinIO | 9000, 9001 | 文件存储 |
| Elasticsearch | 9200 | 搜索引擎 |
| Kibana | 5601 | ES 可视化 |
| SkyWalking | 11800, 12800, 18080 | 链路追踪 |
B. 默认账号密码
| 服务 | 账号 | 密码 |
|---|---|---|
| MySQL | root | vortmall666 |
| Nacos | nacos | nacos |
| MinIO | vortmall | vortmall666 |
| XXL-JOB | admin | 123456 |
| Elasticsearch | elastic | vortmall666 |
| Grafana | admin | vortmall666 |








