听书神器
78.72M · 2026-02-13
接上篇文章:Linux Docker Compose 部署.NET+Vue+MySQL+Redis+Nginx 完整记录(亲测无坑)
写在前面:在实际开发和测试中,经常会遇到需要在同一台服务器部署多个后端API(如主服务+附属服务、测试服务+生产服务)和多个前端Web(如管理端+用户端、PC端+移动端适配版)的场景。单纯靠docker run命令逐个启动容器,会面临端口冲突、配置混乱、维护困难等问题。
本文基于Docker Compose,实现「2个及以上.NET8后端API + 2个及以上Vue前端Web」的容器化部署,核心解决端口隔离、配置统一、Nginx分流等问题;同时扩展PostgreSQL、SQL Server两种数据库的替换方案,补充多个实用部署场景(如子域名访问、HTTPS、日志集中),全程亲测可复现,用于后期查阅,也希望能帮到有同样需求的同行。
适用场景:个人测试、小型项目多服务部署、企业内部多环境(测试+开发)部署,可灵活扩展服务数量,无需重新搭建整体环境。
所有文件统一放在本地易找到的目录(如桌面),后续用Xftp/WinSCP上传到服务器,避免混乱,文件清单如下:
后端文件:backend1-publish、backend2-publish(2个后端的.NET8发布文件,可新增backend3-publish等,命名区分)
前端文件:frontend1-dist、frontend2-dist(2个前端的Vue打包文件,可新增,命名区分)
镜像tar包(离线备用):multi-service-images.tar(含所有所需镜像:后端运行时、前端代理、3种数据库、Redis,解决网络拉取超时)
配置文件:
无论后续用哪种数据库、部署多少服务,这部分工作都是基础,一次性做好,避免后续重复操作。
最小化安装的CentOS7缺少很多基础工具,先安装必要依赖,确保Docker、命令执行正常:
# 更新系统软件包(可选,建议执行,避免依赖版本过低)
yum update -y
# 安装基础工具(wget、vim、net-tools等,后续编辑配置、查看端口常用)
yum install -y wget vim net-tools epel-release
# 安装Docker依赖所需的额外工具(避免后续安装Docker失败)
yum install -y curl policycoreutils-python-utils
# 1. 卸载旧版本Docker(如果之前装过,避免冲突,没装过可跳过)
yum remove -y docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
# 2. 配置Docker官方源(CentOS7专属)
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 3. 安装Docker CE 24.0.7(指定版本,避免自动更新到不稳定版本)
yum install -y docker-ce-24.0.7 docker-ce-cli-24.0.7 containerd.io
# 4. 启动Docker服务,并设置开机自启(关键,多服务需随Docker自动启动)
systemctl start docker
systemctl enable docker
# 5. 验证Docker安装成功(输出版本号即成功)
docker --version
成功标识:Docker version 24.0.7, build afdd53b
Docker默认拉取国外镜像源,国内访问极慢,甚至超时,配置阿里云专属加速(比公共源更稳定)。登录阿里云官网(www.aliyun.com/),搜索 “容器镜像服务”,进入 “镜像加速I器”,复制自己的专属加速地址(示例:xxxxxx.mirror.aliyuncs.com,替换成自己的);
# 1. 创建Docker配置目录(如果不存在)
mkdir -p /etc/docker
# 2. 写入加速配置(替换成自己的阿里云专属加速地址,获取方式:阿里云→容器镜像服务→镜像加速I器)
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://xxxxxx.mirror.aliyuncs.com", "https://mirror.ccs.tencentyun.com"]
}
EOF
# 3. 重新加载配置,重启Docker,让加速生效
systemctl daemon-reload
systemctl restart docker
# 4. 验证加速配置是否生效(输出配置的加速地址即成功)
docker info | grep -A 2 "Registry Mirrors"
成功标识:输出中包含自己配置的阿里云加速地址,无报错。
CentOS7默认安装的Docker Compose是1.x版本,不支持多服务的健康检查、依赖条件等配置,升级到V2版本:
# 1. 删除旧版docker-compose(如果之前装过)
rm -f /usr/local/bin/docker-compose
# 2. 安装Docker Compose V2(插件形式,稳定,和Docker联动更好)
yum install -y docker-compose-plugin
# 3. 建立软链接,保持docker-compose命令可用(和旧版用法一致,无需改命令)
ln -s /usr/libexec/docker/cli-plugins/docker-compose /usr/local/bin/docker-compose
# 4. 验证升级成功(输出V2版本号即成功)
docker-compose --version
成功标识:Docker Compose version v2.27.1(版本号可略有差异,只要是V2即可)
测试环境:直接关闭防火墙,避免端口被拦截,简化配置;生产环境:仅开放所需端口,提升安全性。
# 测试环境:关闭防火墙并禁止开机自启
systemctl stop firewalld
systemctl disable firewalld
systemctl status firewalld # 验证,输出inactive即成功
# 生产环境:开放所需端口(示例,根据自己的端口修改)
# 后端端口:58588、58589;前端端口:6866、6867;数据库端口:3306(MySQL)、5432(PostgreSQL)、1433(SQL Server);Redis端口:6379
firewall-cmd --add-port=58588/tcp --permanent
firewall-cmd --add-port=58589/tcp --permanent
firewall-cmd --add-port=6866/tcp --permanent
firewall-cmd --add-port=6867/tcp --permanent
firewall-cmd --add-port=3306/tcp --permanent
firewall-cmd --add-port=5432/tcp --permanent
firewall-cmd --add-port=1433/tcp --permanent
firewall-cmd --add-port=6379/tcp --permanent
firewall-cmd --reload # 生效配置
firewall-cmd --list-ports # 验证,查看开放的端口清单
将本地准备的所有文件,上传到服务器的/root/multi-service-docker目录(自定义目录,方便记忆),最终目录结构如下(支持多后端、多前端、多数据库):
multi-service-docker/ # 项目根目录(所有文件都放在这里)
├── docker-compose.yml # 核心编排文件(管理所有服务,含多数据库配置)
# 后端目录(2个,可扩展更多)
├── backend1/ # 第一个后端API服务
│ └── publish/ # 后端1的.NET8发布文件(含核心DLL、appsettings.json)
├── backend2/ # 第二个后端API服务
│ └── publish/ # 后端2的.NET8发布文件
# 前端目录(2个,可扩展更多)
├── frontend1/ # 第一个前端Web(如管理端)
│ └── dist/ # 前端1的Vue打包文件(index.html、css、js)
├── frontend2/ # 第二个前端Web(如用户端)
│ └── dist/ # 前端2的Vue打包文件
# Nginx配置目录
├── nginx/
│ └── nginx.conf # Nginx核心配置(多前端/多后端分流)
# 数据库配置目录(3种数据库,按需使用)
├── mysql/
│ ├── my.cnf # MySQL配置文件
│ └── init-mysql.sql # MySQL初始化SQL
├── postgresql/
│ ├── postgresql.conf # PostgreSQL配置文件
│ └── init-postgresql.sql # PostgreSQL初始化SQL
├── sqlserver/
│ ├── sqlserver.conf # SQL Server配置文件(可选)
│ └── init-sqlserver.sql # SQL Server初始化SQL
# 离线镜像包(备用)
└── multi-service-images.tar # 所有所需镜像的离线包
上传方法:用 MobaXterm/Xftp/WinSCP连接服务器(IP:服务器真实IP,账号:root,密码:自己的服务器密码),将本地准备的文件,按上述目录结构,拖到对应文件夹中即可。
先实现最基础的多服务部署(2后端+2前端+MySQL+Redis+Nginx),掌握核心逻辑后,再扩展其他数据库和场景,新手建议先按此方案部署成功,再进行扩展。
该文件是多服务部署的核心,管理所有容器的启动、依赖、端口、挂载等配置,注释详细,可直接复制使用,关键配置已标注:
version: '3.8'
# 所有服务的集合(多后端、多前端、数据库、Redis、Nginx)
services:
# === 公共依赖服务:MySQL(基础版,后续可替换为PostgreSQL/SQL Server) ===
mysql:
image: mysql:8.0 # 使用MySQL 8.0镜像
container_name: multi-mysql # 自定义容器名,唯一,方便管理
restart: always # 容器异常退出/服务器重启后,自动重启
environment:
MYSQL_ROOT_PASSWORD: Root@123456 # MySQL root密码(自定义,建议复杂密码)
MYSQL_USER: appuser # 项目访问MySQL的用户名(自定义)
MYSQL_PASSWORD: App@123456 # 项目访问MySQL的密码(自定义)
MYSQL_DATABASE: app_db1 # 后端1所用数据库名
MYSQL_DATABASE2: app_db2 # 后端2所用数据库名(分库部署,可选)
TZ: Asia/Shanghai # 强制容器时区为东八区(解决时差问题)
ports:
- "3306:3306" # 端口映射:宿主机3306 → 容器内3306(本地工具可连接)
volumes:
- ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf # 挂载MySQL配置文件
- ./mysql/init-mysql.sql:/docker-entrypoint-initdb.d/init-mysql.sql # 挂载初始化SQL
- mysql-data:/var/lib/mysql # 数据卷:持久化MySQL数据(容器删除不丢失)
- /etc/localtime:/etc/localtime:ro # 挂载宿主机时区文件,双重保障时差
command: --lower_case_table_names=1 # MySQL不区分大小写(避免表名大小写问题)
networks:
- multi-service-network # 加入自定义网络,实现所有容器互通
# 健康检查:检测MySQL是否真正就绪,避免后端启动早于MySQL,导致连接失败
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uappuser", "-pApp@123456"]
interval: 5s # 每5秒检测一次
timeout: 30s # 超时时间30秒
retries: 10 # 重试10次,失败则认为容器未就绪
start_period: 20s # 容器启动后,延迟20秒开始检测
# === 公共依赖服务:Redis(缓存,多后端可共享/隔离) ===
redis:
image: redis:7-alpine # 轻量版Redis,占用资源少
container_name: multi-redis # 唯一容器名
restart: always # 自动重启
ports:
- "6379:6379" # 端口映射:宿主机6379 → 容器内6379
volumes:
- redis-data:/data # 数据卷:持久化Redis数据
command: redis-server --requirepass "Redis@123456" # Redis密码(自定义)
networks:
- multi-service-network # 加入自定义网络
environment:
TZ: Asia/Shanghai # 同步东八区时区
# Redis健康检查(可选,优化多后端依赖)
healthcheck:
test: ["CMD", "redis-cli", "ping", "-a", "Redis@123456"]
interval: 3s
timeout: 10s
retries: 5
# === 后端API 1(第一个服务,如管理端后端) ===
backend1:
image: mcr.microsoft.com/dotnet/aspnet:8.0 # .NET8运行时镜像(无需构建,直接运行发布文件)
container_name: multi-backend1 # 唯一容器名,区分其他后端
restart: always # 自动重启
ports:
- "58588:58588" # 唯一端口,避免和其他后端冲突
depends_on:
mysql:
condition: service_healthy # 仅在MySQL健康检查通过(真正就绪)后,才启动后端1
redis:
condition: service_healthy # Redis就绪后,启动后端1
volumes:
- ./backend1/publish:/app # 挂载后端1的发布目录(核心,容器直接运行发布文件)
- /wwwroot/Resources1:/wwwroot/Resources # 挂载后端1的文件目录(如用户头像,按需挂载)
environment:
TZ: Asia/Shanghai # 同步时区
ASPNETCORE_URLS: "http://*:58588" # 强制后端158588端口(解决端口不通问题)
ASPNETCORE_ENVIRONMENT: Production # .NET环境(生产环境)
# 后端1的MySQL连接字符串(连接MySQL的app_db1库,server用容器名mysql)
ConnectionStrings__MySQL: "server=mysql;port=3306;database=app_db1;user=appuser;password=App@123456;charset=utf8mb4;AllowPublicKeyRetrieval=True;SslMode=None"
# 后端1的Redis连接字符串(server用容器名redis,密码对应上面的Redis密码)
ConnectionStrings__Redis: "redis:6379,password=Redis@123456,defaultDatabase=0,ssl=false,abortConnect=false"
working_dir: /app # 容器工作目录,指向挂载的发布目录
entrypoint: ["dotnet", "Backend1.WebHost.dll"] # 启动后端1的核心DLL(替换为自己的DLL名)
networks:
- multi-service-network # 加入自定义网络,可访问MySQL/Redis/其他后端
# === 后端API 2(第二个服务,如用户端后端) ===
backend2:
image: mcr.microsoft.com/dotnet/aspnet:8.0 # 和后端1共用.NET8运行时镜像
container_name: multi-backend2 # 唯一容器名,区分后端1
restart: always # 自动重启
ports:
- "58589:58589" # 唯一端口,避免和后端1冲突(不可重复)
depends_on:
mysql:
condition: service_healthy # 依赖MySQL就绪
redis:
condition: service_healthy # 依赖Redis就绪
volumes:
- ./backend2/publish:/app # 挂载后端2的发布目录(独立目录,避免代码覆盖)
- /wwwroot/Resources2:/wwwroot/Resources # 后端2的文件目录(独立挂载,避免文件混乱)
environment:
TZ: Asia/Shanghai
ASPNETCORE_URLS: "http://*:58589" # 强制后端258589端口
ASPNETCORE_ENVIRONMENT: Production
# 后端2的MySQL连接字符串(可连接不同库app_db2,实现分库部署)
ConnectionStrings__MySQL: "server=mysql;port=3306;database=app_db2;user=appuser;password=App@123456;charset=utf8mb4;AllowPublicKeyRetrieval=True;SslMode=None"
# 后端2的Redis连接字符串(可指定不同数据库defaultDatabase=1,实现缓存隔离)
ConnectionStrings__Redis: "redis:6379,password=Redis@123456,defaultDatabase=1,ssl=false,abortConnect=false"
working_dir: /app
entrypoint: ["dotnet", "Backend2.WebHost.dll"] # 后端2的核心DLL(替换为自己的)
networks:
- multi-service-network
# === Nginx服务(核心:多前端代理+多后端分流) ===
nginx:
image: nginx:alpine # 轻量版Nginx
container_name: multi-nginx # 唯一容器名
restart: always # 自动重启
ports:
- "6866:6866" # 前端1访问端口(唯一)
- "6867:6867" # 前端2访问端口(唯一,避免冲突)
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf # 挂载Nginx分流配置
- ./frontend1/dist:/usr/share/nginx/html/web1 # 挂载前端1的静态文件
- ./frontend2/dist:/usr/share/nginx/html/web2 # 挂载前端2的静态文件
depends_on:
- backend1 # 后端1启动后,再启动Nginx(避免前端访问后端失败)
- backend2 # 后端2启动后,再启动Nginx
networks:
- multi-service-network
environment:
TZ: Asia/Shanghai
# 数据卷:持久化MySQL、Redis数据(容器删除、docker-compose down不会删除数据)
volumes:
mysql-data:
redis-data:
# 自定义网络:所有服务加入同一网络,容器间可通过「容器名」直接通信,无需配置IP
networks:
multi-service-network:
driver: bridge
Nginx的核心作用是:代理多个前端静态文件,将前端的API请求,按路径前缀分流到对应后端,避免端口混乱,配置如下(注释详细):
worker_processes 1; # 按服务器CPU核心数调整,1核用1,2核用2
events {
worker_connections 1024; # 最大连接数,足够多服务使用
}
http {
include /etc/nginx/mime.types; # 引入MIME类型(支持前端静态文件)
default_type application/octet-stream;
sendfile on; # 开启高效文件传输
keepalive_timeout 65; # 连接超时时间
# === 前端1配置(访问端口:6866,对应管理端) ===
server {
listen 6866; # 前端1的访问端口(和docker-compose.yml中Nginx的端口映射一致)
server_name localhost; # 测试环境用localhost,生产环境可改为域名
# 前端1的静态文件代理(加载Vue打包后的index.html、css、js)
location / {
root /usr/share/nginx/html/web1; # 对应前端1的dist目录(docker-compose.yml中挂载的路径)
index index.html index.htm;
try_files $uri $uri/ /index.html; # 解决Vue路由刷新404问题(关键)
}
# 前端1调用的后端1API(路径前缀:/api1/,分流到backend1)
location /api1/ {
proxy_pass ; # 转发到后端1容器(容器名+端口)
# 转发请求头,确保后端能获取客户端真实IP、请求地址等信息
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;
}
# 前端1如需调用后端2API(可选,按需配置)
location /api2/ {
proxy_pass ;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
# === 前端2配置(访问端口:6867,对应用户端) ===
server {
listen 6867; # 前端2的访问端口(唯一,不重复)
server_name localhost;
# 前端2的静态文件代理
location / {
root /usr/share/nginx/html/web2; # 对应前端2的dist目录
index index.html index.htm;
try_files $uri $uri/ /index.html; # Vue路由兼容
}
# 前端2调用的后端2API(路径前缀:/api2/,分流到backend2)
location /api2/ {
proxy_pass ; # 转发到后端2容器
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;
}
# 前端2如需调用后端1API(可选,按需配置)
location /api1/ {
proxy_pass ;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
所有配置完成后,一键启动所有服务,然后逐个验证,确保所有服务正常运行。
# 1. 进入项目根目录(必须在docker-compose.yml所在目录执行命令)
cd /root/multi-service-docker
# 2. 后台启动所有服务(-d:后台运行,无需手动值守)
docker-compose up -d
# 3. 查看所有服务运行状态(关键,确认所有服务都启动成功)
docker-compose ps
成功标识:docker-compose ps输出中,multi-mysql、multi-redis、multi-backend1、multi-backend2、multi-nginx 5个服务的State列,均为Up (healthy)或Up,无Exited状态。
http://服务器IP:58588/swagger(如:)成功标识:浏览器能正常打开Swagger页面,无报错,能看到后端1的所有接口。
http://服务器IP:58589/swagger 成功标识:正常打开Swagger页面,接口能正常显示。http://服务器IP:6866 成功标识:能正常打开Vue页面,样式、图片正常,调用/api1/xxx接口能返回正常数据。http://服务器IP:6867 成功标识:能正常打开Vue页面,调用/api2/xxx接口能返回正常数据。 失败排查:若某个服务启动失败或访问不通,执行docker-compose logs -f 服务名(如docker-compose logs -f multi-backend1),查看实时日志,根据日志提示排查问题(如端口冲突、连接串错误、目录挂载失败)。
实际项目中,可能会用到PostgreSQL(开源、适合复杂查询)或SQL Server(微软生态、适合.NET项目),以下是完整的替换方案,只需修改docker-compose.yml和后端连接串,无需修改前端和Nginx配置。
PostgreSQL是开源的高性能数据库,兼容性强,适合大多数.NET项目,替换步骤如下:
删除原有的mysql服务,新增postgresql服务,其他服务(后端1/2、前端1/2、Redis、Nginx)无需修改,仅修改后端的连接串:
version: '3.8'
services:
# === 替换为PostgreSQL服务(替换原有的MySQL) ===
postgresql:
image: postgres:15 # PostgreSQL 15镜像(稳定版,适配.NET8)
container_name: multi-postgresql # 唯一容器名
restart: always
environment:
POSTGRES_USER: appuser # 项目访问PostgreSQL的用户名
POSTGRES_PASSWORD: App@123456 # 密码(和之前MySQL一致,方便记忆)
POSTGRES_DB: app_db1 # 后端1所用数据库
POSTGRES_DB2: app_db2 # 后端2所用数据库(分库部署)
TZ: Asia/Shanghai # 同步东八区时区
ports:
- "5432:5432" # PostgreSQL默认端口5432
volumes:
- ./postgresql/postgresql.conf:/var/lib/postgresql/data/postgresql.conf # 挂载配置文件
- ./postgresql/init-postgresql.sql:/docker-entrypoint-initdb.d/init-postgresql.sql # 挂载初始化SQL
- postgresql-data:/var/lib/postgresql/data # 数据卷:持久化数据
- /etc/localtime:/etc/localtime:ro
networks:
- multi-service-network
# 健康检查:检测PostgreSQL是否就绪
healthcheck:
test: ["CMD-SHELL", "pg_isready -U appuser -d app_db1"]
interval: 5s
timeout: 30s
retries: 10
start_period: 20s
# === Redis服务(不变) ===
redis:
image: redis:7-alpine
container_name: multi-redis
restart: always
ports:
- "6379:6379"
volumes:
- redis-data:/data
command: redis-server --requirepass "Redis@123456"
networks:
- multi-service-network
environment:
TZ: Asia/Shanghai
healthcheck:
test: ["CMD", "redis-cli", "ping", "-a", "Redis@123456"]
interval: 3s
timeout: 10s
retries: 5
# === 后端1服务(仅修改MySQL连接串为PostgreSQL连接串) ===
backend1:
image: mcr.microsoft.com/dotnet/aspnet:8.0
container_name: multi-backend1
restart: always
ports:
- "58588:58588"
depends_on:
postgresql: # 依赖改为postgresql,而非mysql
condition: service_healthy
redis:
condition: service_healthy
volumes:
- ./backend1/publish:/app
- /wwwroot/Resources1:/wwwroot/Resources
environment:
TZ: Asia/Shanghai
ASPNETCORE_URLS: "http://*:58588"
ASPNETCORE_ENVIRONMENT: Production
# 后端1的PostgreSQL连接串(替换原有的MySQL连接串)
ConnectionStrings__PostgreSQL: "Host=postgresql;Port=5432;Database=app_db1;Username=appuser;Password=App@123456;Pooling=true;Timeout=30;"
# Redis连接串(不变)
ConnectionStrings__Redis: "redis:6379,password=Redis@123456,defaultDatabase=0,ssl=false,abortConnect=false"
working_dir: /app
entrypoint: ["dotnet", "Backend1.WebHost.dll"]
networks:
- multi-service-network
# === 后端2服务(仅修改连接串) ===
backend2:
image: mcr.microsoft.com/dotnet/aspnet:8.0
container_name: multi-backend2
restart: always
ports:
- "58589:58589"
depends_on:
postgresql:
condition: service_healthy
redis:
condition: service_healthy
volumes:
- ./backend2/publish:/app
- /wwwroot/Resources2:/wwwroot/Resources
environment:
TZ: Asia/Shanghai
ASPNETCORE_URLS: "http://*:58589"
ASPNETCORE_ENVIRONMENT: Production
# 后端2的PostgreSQL连接串
ConnectionStrings__PostgreSQL: "Host=postgresql;Port=5432;Database=app_db2;Username=appuser;Password=App@123456;Pooling=true;Timeout=30;"
# Redis连接串(不变)
ConnectionStrings__Redis: "redis:6379,password=Redis@123456,defaultDatabase=1,ssl=false,abortConnect=false"
working_dir: /app
entrypoint: ["dotnet", "Backend2.WebHost.dll"]
networks:
- multi-service-network
# === Nginx服务(不变) ===
nginx:
image: nginx:alpine
container_name: multi-nginx
restart: always
ports:
- "6866:6866"
- "6867:6867"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./frontend1/dist:/usr/share/nginx/html/web1
- ./frontend2/dist:/usr/share/nginx/html/web2
depends_on:
- backend1
- backend2
networks:
- multi-service-network
environment:
TZ: Asia/Shanghai
# 数据卷:替换为postgresql-data,删除mysql-data
volumes:
postgresql-data:
redis-data:
# 自定义网络(不变)
networks:
multi-service-network:
driver: bridge
Npgsql.EntityFrameworkCore.PostgreSQL(适配.NET8的版本);ConnectionStrings:MySQL,改为ConnectionStrings:PostgreSQL,对应docker-compose.yml中的连接串;修改Program.cs:如使用EF Core的数据库提供器,从MySQL改为PostgreSQL,示例:
cd /root/multi-service-docker
# 停止并删除原有容器(避免冲突)
docker-compose down
# 启动新服务
docker-compose up -d
# 查看状态
docker-compose ps
验证:和基础方案一致,访问前端、后端、PostgreSQL(用Navicat连接服务器IP:5432),确认所有服务正常。
SQL Server是微软推出的关系型数据库,和.NET生态兼容性极佳,适合企业级.NET项目,替换步骤如下(类似PostgreSQL):
version: '3.8'
services:
# === 替换为SQL Server服务 ===
sqlserver:
image: mcr.microsoft.com/mssql/server:2022-latest # SQL Server 2022镜像
container_name: multi-sqlserver # 唯一容器名
restart: always
environment:
ACCEPT_EULA: "Y" # 必须设置为Y,接受SQL Server许可协议
SA_PASSWORD: "App@12345678" # SA密码(复杂度要求:至少8位,含字母+数字+特殊符号)
MSSQL_PID: "Express" # 版本:Express(免费版,适合测试/小型项目)
TZ: Asia/Shanghai # 同步时区
ports:
- "1433:1433" # SQL Server默认端口1433
volumes:
- ./sqlserver/sqlserver.conf:/var/opt/mssql/mssql.conf # 挂载配置文件
- ./sqlserver/init-sqlserver.sql:/docker-entrypoint-initdb.d/init-sqlserver.sql # 初始化SQL
- sqlserver-data:/var/opt/mssql # 数据卷:持久化数据
- /etc/localtime:/etc/localtime:ro
networks:
- multi-service-network
# 健康检查:检测SQL Server是否就绪
healthcheck:
test: ["CMD-SHELL", "/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P App@12345678 -Q 'SELECT 1'"]
interval: 10s
timeout: 30s
retries: 10
start_period: 30s # SQL Server启动较慢,延迟30秒开始检测
# === Redis服务(不变) ===
redis:
image: redis:7-alpine
container_name: multi-redis
restart: always
ports:
- "6379:6379"
volumes:
- redis-data:/data
command: redis-server --requirepass "Redis@123456"
networks:
- multi-service-network
environment:
TZ: Asia/Shanghai
healthcheck:
test: ["CMD", "redis-cli", "ping", "-a", "Redis@123456"]
interval: 3s
timeout: 10s
retries: 5
# === 后端1服务(仅修改连接串) ===
backend1:
image: mcr.microsoft.com/dotnet/aspnet:8.0
container_name: multi-backend1
restart: always
ports:
- "58588:58588"
depends_on:
sqlserver: # 依赖改为sqlserver
condition: service_healthy
redis:
condition: service_healthy
volumes:
- ./backend1/publish:/app
- /wwwroot/Resources1:/wwwroot/Resources
environment:
TZ: Asia/Shanghai
ASPNETCORE_URLS: "http://*:58588"
ASPNETCORE_ENVIRONMENT: Production
# 后端1的SQL Server连接串
ConnectionStrings__SQLServer: "Server=sqlserver,1433;Database=app_db1;User ID=sa;Password=App@12345678;TrustServerCertificate=True;"
# Redis连接串(不变)
ConnectionStrings__Redis: "redis:6379,password=Redis@123456,defaultDatabase=0,ssl=false,abortConnect=false"
working_dir: /app
entrypoint: ["dotnet", "Backend1.WebHost.dll"]
networks:
- multi-service-network
# === 后端2服务(仅修改连接串) ===
backend2:
image: mcr.microsoft.com/dotnet/aspnet:8.0
container_name: multi-backend2
restart: always
ports:
- "58589:58589"
depends_on:
sqlserver:
condition: service_healthy
redis:
condition: service_healthy
volumes:
- ./backend2/publish:/app
- /wwwroot/Resources2:/wwwroot/Resources
environment:
TZ: Asia/Shanghai
ASPNETCORE_URLS: "http://*:58589"
ASPNETCORE_ENVIRONMENT: Production
# 后端2的SQL Server连接串
ConnectionStrings__SQLServer: "Server=sqlserver,1433;Database=app_db2;User ID=sa;Password=App@12345678;TrustServerCertificate=True;"
# Redis连接串(不变)
ConnectionStrings__Redis: "redis:6379,password=Redis@123456,defaultDatabase=1,ssl=false,abortConnect=false"
working_dir: /app
entrypoint: ["dotnet", "Backend2.WebHost.dll"]
networks:
- multi-service-network
# === Nginx服务(不变) ===
nginx:
image: nginx:alpine
container_name: multi-nginx
restart: always
ports:
- "6866:6866"
- "6867:6867"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./frontend1/dist:/usr/share/nginx/html/web1
- ./frontend2/dist:/usr/share/nginx/html/web2
depends_on:
- backend1
- backend2
networks:
- multi-service-network
environment:
TZ: Asia/Shanghai
# 数据卷:替换为sqlserver-data
volumes:
sqlserver-data:
redis-data:
# 自定义网络(不变)
networks:
multi-service-network:
driver: bridge
Microsoft.EntityFrameworkCore.SqlServer(适配.NET8的版本);ConnectionStrings:MySQL改为ConnectionStrings:SQLServer,对应docker-compose.yml中的连接串;如果本文对你有一点点帮助,点个赞支持一下吧,你的每一个【赞】都是我创作的最大动力 _
更多技术文章请往:
www.guosisoft.com/article
www.rdiframework.net/article
大家一起共同交流和进步呀!!