Toggle navigation
首页
产品中心
全新RDIF.vNext低代码框架
镇店
.NET C/S开发框架
.NET Web敏捷开发框架
.NET 快速开发框架(全新EasyUI版本)
.NET 代码生成器
.NET WebAPI服务端开发框架
客户案例
付款方式
技术文章
文档中心
下载
关于
首页
技术文章
RDIF.NET
正文
原创
2026-02-10
浏览 (
5046
)
Linux Docker Compose 部署.NET+Vue+MySQL+Redis+Nginx 完整记录(亲测无坑)
 ## 写在前面:为什么用 Docker Compose?比单容器部署好在哪? 做容器化部署时,单靠`docker run`命令逐个启动 MySQL、Redis、后端、Nginx 容器会非常繁琐 —— 不仅要记大量命令参数,还得手动控制容器启动顺序、配置网络联动,一旦服务器重启,所有容器要重新逐个启动,维护成本极高。 **Docker Compose**是 Docker 官方的多容器编排工具,核心是通过一个`docker-compose.yml`配置文件,集中管理所有容器的**镜像、端口、挂载、环境变量、网络、依赖关系**等所有配置,能完美解决单容器部署的痛点。 ### Docker Compose 核心优点(也是本次部署选择它的原因) 1. **一键启停**:一条`docker-compose up -d`启动所有服务,`docker-compose down`停止并清理,无需逐个执行`docker run`/`docker stop`; 2. **配置统一**:所有容器配置集中在一个 yaml 文件,易编辑、易备份,后续修改只需改配置文件,无需记复杂命令; 3. **容器自动联动**:自动创建专属网络,容器间通过**服务名**即可通信,无需手动配置网络;可通过`depends_on`控制启动顺序,解决服务依赖问题; 4. **环境一致性**:配置文件可跨环境复用,本地测试、服务器部署用同一套配置,避免 “本地能跑,服务器不行”; 5. **易维护易迁移**:项目目录 + 配置文件 + 离线镜像包,可直接迁移到其他服务器,解压后一键启动,无需重新配置; 6. **数据卷 / 网络自动管理**:自动创建数据卷、自定义网络,无需手动执行`docker volume create`/`docker network create`。 相比单容器部署,Docker Compose 让多服务容器化部署的效率提升数倍,尤其适合**后端 + 前端 + 数据库 + 缓存 + 代理**这类多组件的项目部署,也是目前中小型项目容器化的主流方案。 ## 一、部署环境准备(提前确认,避免后续兼容问题) ### 1. 虚拟机环境(个人测试用,非生产) - 系统:CentOS 7.9(最小化安装,已配置静态 IP:192.168.1.100,虚拟 IP,替换真实 IP) - 内存:4G(建议不低于 2G,否则 Docker 容器启动可能卡顿) - 硬盘:50G(足够存放镜像、项目文件和数据库数据) - 网络:能访问外网(前期拉取镜像 / 安装依赖用,后期可断网运行) ### 2. 软件版本(全程统一版本,避免兼容问题) - Docker:Docker CE 24.0.7(CentOS7 稳定版) - Docker Compose:V2.27.1(解决旧版配置兼容问题) - 后端:.NET 8(本地 VS2022 发布到 publish 文件夹) - 前端:Vue3(本地 yarn 打包到 dist 文件夹) - MySQL:8.0(Docker 镜像,数据持久化) - Redis:7-alpine(轻量版,适合容器部署) - Nginx:alpine(轻量版,代理前端静态文件 + 后端接口) ### 3. 本地准备文件(提前打包好,上传到虚拟机) - 后端:publish 文件夹(VS2022 发布后的.NET8 项目文件,含核心 dll、配置文件) - 前端:dist 文件夹(Vue3 打包后的静态文件,含 index.html、css、js) - 镜像 tar 包:rdif-all-images.tar(离线镜像包,含 MySQL、Redis、Nginx 等 6 个所需镜像,解决网络拉取超时) - 配置文件:my.cnf(MySQL 配置)、nginx.conf(Nginx 配置)、init.sql(MySQL 初始化 SQL)、docker-compose.yml(核心编排文件) ## 二、前期准备工作(必做,奠定部署基础) ### 1. CentOS7 系统基础配置(最小化安装补充依赖) 最小化安装的 CentOS7 缺少很多基础工具,先安装必要依赖,避免后续 Docker 安装、命令执行失败: ```bash # 更新系统软件包(可选,建议执行,避免依赖版本过低) yum update -y # 安装基础工具(wget、vim、net-tools等,后续常用) yum install -y wget vim net-tools epel-release ``` ### 2. 安装 Docker CE(CentOS7 稳定版,步骤固定) CentOS7 默认源没有 Docker,需要配置 Docker 官方源,同时解决依赖缺失问题(重点解决 container-selinux 依赖): ```bash # 1. 卸载旧版本Docker(如果之前装过,避免冲突,没装过可跳过) yum remove -y docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine # 2. 安装Docker依赖(必做,否则安装失败) yum install -y yum-utils device-mapper-persistent-data lvm2 container-selinux # 3. 配置Docker官方源 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 4. 安装Docker CE(稳定版) yum install -y docker-ce docker-ce-cli containerd.io # 5. 启动Docker服务,并设置开机自启(提前配置,后续不用再改) systemctl start docker systemctl enable docker # 6. 验证Docker安装成功(输出版本号即成功) docker --version ``` ✅ 成功标识:`Docker version 24.0.7, build afdd53b` ### 3. 配置 Docker 镜像加速(国内必做,否则镜像拉取超时) Docker 默认拉取官方镜像(国外源),国内访问极慢,甚至超时。这里用阿里云个人专属镜像加速(比公共源更稳定),步骤如下: 1. 登录阿里云官网(https://www.aliyun.com/),搜索 “容器镜像服务”,进入 “镜像加速器”,复制自己的专属加速地址(示例:https://xxxxxx.mirror.aliyuncs.com,替换成自己的);  2. 配置镜像加速,修改 Docker 守护进程配置文件: ```bash # 创建Docker配置目录(如果不存在) mkdir -p /etc/docker # 写入加速配置(替换成自己的阿里云专属加速地址) tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://xxxxxx.mirror.aliyuncs.com", "https://mirror.ccs.tencentyun.com"] } EOF # 重新加载配置,重启Docker,让加速生效 systemctl daemon-reload systemctl restart docker # 验证加速配置是否生效(输出配置的加速地址即成功) docker info | grep -A 2 "Registry Mirrors" ``` ✅ 成功标识:输出中包含自己配置的阿里云加速地址。 ### 4. 升级 Docker Compose(解决旧版配置兼容问题) CentOS7 默认安装的 Docker Compose 是 1.x 版本,不支持新版 docker-compose.yml 中的配置(如 condition、start_period),升级到 V2 版本(官方推荐): ```bash # 1. 删除旧版docker-compose(如果之前装过) rm -f /usr/local/bin/docker-compose # 2. 安装Docker Compose V2(插件形式,稳定) 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`(版本号可不同) ### 5. 关闭防火墙(测试环境,避免端口访问失败) 个人测试用,直接关闭 CentOS7 的 FirewallD 防火墙,避免前端、后端、数据库端口被拦截,生产环境可按需开放端口: ```bash # 1. 立即停止防火墙服务 systemctl stop firewalld # 2. 禁止防火墙开机自启(避免虚拟机重启后防火墙又开启) systemctl disable firewalld # 3. 验证防火墙状态(输出inactive即成功关闭) systemctl status firewalld ``` ## 三、项目目录结构整理(规范目录,避免后续混乱) 将本地准备好的所有文件,上传到 CentOS7 虚拟机的`/root/rdif-docker`目录(自定义目录,方便记忆),最终目录结构如下(重点:前后端仅保留打包 / 发布文件,无源码、无多余文件):  ```plaintext rdif-docker/ # 项目根目录(所有文件都放在这里) ├── docker-compose.yml # 核心编排文件,管理所有容器 ├── backend/ # 后端目录(仅保留VS发布的publish) │ └── publish/ # .NET8发布文件(含RDIF.WebHost.dll、appsettings.json) ├── frontend/ # 前端目录(仅保留Vue3打包的dist) │ └── dist/ # Vue3静态文件(index.html、css、js、assets) ├── nginx/ # Nginx配置目录 │ └── nginx.conf # Nginx配置文件(代理前端+后端接口) ├── mysql/ # MySQL配置目录 │ ├── my.cnf # MySQL配置(不区分大小写、字符集等) │ └── init.sql # MySQL初始化SQL(创建库、表、初始化数据) └── rdif-all-images.tar # 离线镜像包(含所有所需镜像,避免拉取超时) ``` ### 上传文件方法(新手推荐,可视化操作) 用 MobaXterm或Xftp 或 WinSCP 工具,连接虚拟机(IP:192.168.1.100,账号:root,密码:Root@123456,虚拟密码),将本地的 publish、dist、配置文件、镜像 tar 包,拖到对应目录下即可。 ## 四、编写 docker-compose.yml(核心配置,重中之重) 这是整个部署的核心,所有容器(MySQL、Redis、后端、Nginx)的联动、端口映射、目录挂载,都在这里配置。结合本次需求(前后端已打包 / 发布,无需编译构建),编写如下配置(注释详细,可直接复制修改,替换自己的对应信息,**Redis 密码已替换为通用虚拟密码**): ```yaml version: '3.8' # 所有服务的集合 services: # 1. MySQL8 服务(数据库,数据持久化) mysql: image: mysql:8.0 # 使用的镜像(本地已导入,无需拉取) container_name: rdif-mysql # 自定义容器名,方便管理 restart: always # 容器异常退出/ Docker启动时,自动重启 environment: MYSQL_ROOT_PASSWORD: Root@123456 # MySQL root密码(虚拟,替换成自己的) MYSQL_USER: guosisoft # 项目访问MySQL的用户名(自定义) MYSQL_PASSWORD: Mysql@123456 # 项目访问MySQL的密码(虚拟) MYSQL_DATABASE: rdif_vue3 # 项目所用数据库名(自定义) MYSQL_TZINFO_TO_SYS_TABLES: 1 # 初始化MySQL时区表,解决时差问题 TZ: Asia/Shanghai # 强制容器时区为东八区(核心,解决时差) ports: - "3306:3306" # 端口映射:宿主机3306 → 容器内3306(本地工具可连接) volumes: # 挂载MySQL配置文件,实现自定义配置 - ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf # 挂载初始化SQL,容器启动时自动执行,创建库表 - ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql # 挂载数据卷,持久化MySQL数据(docker-compose down不会删除数据) - mysql-data:/var/lib/mysql # 挂载宿主机时区文件,双重保障时区同步(只读,避免容器修改) - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro command: --lower_case_table_names=1 # MySQL不区分大小写(避免项目表名大小写问题) networks: - rdif-network # 加入自定义网络,实现容器间通信 # 健康检查:检测MySQL是否真正就绪,避免后端启动早于MySQL healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uguosisoft", "-pMysql@123456"] interval: 5s # 每5秒检测一次 timeout: 30s # 超时时间30秒 retries: 10 # 重试10次,失败则认为容器未就绪 start_period: 20s # 容器启动后,延迟20秒开始检测 # 2. Redis 服务(缓存,轻量版,密码已替换为虚拟通用密码) redis: image: redis:7-alpine # 轻量版Redis,占用资源少 container_name: rdif-redis # 自定义容器名 restart: always # 自动重启 ports: - "6379:6379" # 端口映射:宿主机6379 → 容器内6379 volumes: - redis-data:/data # 数据卷持久化Redis数据 command: redis-server --requirepass "Redis@123456" # Redis虚拟密码,替换成自己的复杂密码 networks: - rdif-network # 加入自定义网络 environment: TZ: Asia/Shanghai # 同步东八区时区 # 3. .NET8 后端服务(已发布,直接挂载运行,Redis连接密码同步替换) backend: image: mcr.microsoft.com/dotnet/aspnet:8.0 # .NET8运行时镜像(无需构建) container_name: rdif-backend # 自定义容器名 restart: always # 自动重启 ports: - "58588:58588" # 端口映射:宿主机58588 → 容器内58588(后端接口端口) depends_on: mysql: condition: service_healthy # 仅在MySQL健康检查通过(就绪)后,才启动后端 redis: condition: service_started # Redis启动后,即可启动后端 volumes: # 核心:挂载本地publish到容器的/app目录 - ./backend/publish:/app # 宿主机:/wwwroot/Resources → 容器内:/wwwroot/Resources - /wwwroot/Resources:/wwwroot/Resources environment: TZ: Asia/Shanghai # 同步东八区时区 ASPNETCORE_URLS: "http://*:58588" # 强制.NET8容器内监听58588端口(解决端口不通) ASPNETCORE_ENVIRONMENT: Production # .NET环境(生产环境) # MySQL连接字符串(替换成自己的用户名、密码、数据库名,server用容器名mysql) ConnectionStrings__MySQL: "server=mysql;port=3306;database=rdif_vue3;user=guosisoft;password=Mysql@123456;charset=utf8mb4;AllowPublicKeyRetrieval=True;SslMode=None" # Redis连接字符串(server用容器名redis,密码同步替换为虚拟密码) ConnectionStrings__Redis: "redis:6379,password=Redis@123456,defaultDatabase=0,ssl=false,abortConnect=false" working_dir: /app # 容器工作目录,指向挂载的publish目录 entrypoint: ["dotnet", "RDIF.WebHost.dll"] # 启动后端核心dll(替换成自己的dll名) networks: - rdif-network # 加入自定义网络 # 4. Nginx 服务(代理前端静态文件+后端接口) nginx: image: nginx:alpine # 轻量版Nginx container_name: rdif-nginx # 自定义容器名 restart: always # 自动重启 ports: - "6866:6866" # 端口映射:宿主机6866 → 容器内6866(前端访问端口) volumes: # 挂载Nginx配置文件,实现前端代理和接口转发 - ./nginx/nginx.conf:/etc/nginx/nginx.conf # 挂载前端dist目录,Nginx直接代理静态文件(核心) - ./frontend/dist:/usr/share/nginx/html depends_on: - backend # 后端启动后,再启动Nginx networks: - rdif-network # 加入自定义网络 environment: TZ: Asia/Shanghai # 同步东八区时区 # 数据卷:持久化MySQL和Redis数据(docker-compose down不会删除) volumes: mysql-data: redis-data: # 自定义网络:所有容器加入同一网络,实现容器间通信(用容器名即可访问) networks: rdif-network: driver: bridge ``` ### 关键配置说明(必看,避免踩坑) 1. 所有容器都配置了`restart: always`,配合 Docker 开机自启,实现虚拟机重启后所有服务自动启动; 2. 后端配置`ASPNETCORE_URLS: "http://*:58588"`,强制监听 58588 端口,和端口映射一致,解决.NET8 默认监听 8080 导致的端口不通; 3. MySQL 连接字符串中,`server=mysql`(用容器名),而非虚拟机 IP,容器间通信必须这样配置;补充`AllowPublicKeyRetrieval=True;SslMode=None`,解决容器内连接 MySQL 失败; 4. 所有容器都配置`TZ: Asia/Shanghai`,同步东八区时区,解决 MySQL 时差 8 小时问题; 5. 后端`depends_on`配置了`condition: service_healthy`,确保 MySQL 完全就绪后再启动后端,避免后端启动时 MySQL 未初始化完成导致的连接失败; 6. 所有敏感密码(MySQL/Redis)均为虚拟示例,实际部署请替换为**字母 + 数字 + 特殊符号**的复杂密码,提升安全性。 ## 五、本地拉取镜像并打包为 tar(离线方案前置步骤,关键!) 本次部署采用**离线镜像导入**方案(解决服务器网络拉取超时问题),需在**本地能正常联网的电脑**上提前拉取所有所需镜像,再打包为 tar 文件,最后上传到 CentOS 服务器。 ### 5.1 本地拉取镜像的前提条件 本地电脑(Windows/macOS)需安装**Docker Desktop**(Docker 桌面版),内置 Docker 引擎和镜像管理功能,是本地操作 Docker 的必备工具: - 下载地址:https://www.docker.com/products/docker-desktop/ - 安装后验证:打开 Docker Desktop,启动后在本地终端(CMD/PowerShell/ 终端)执行`docker --version`,输出版本号即安装成功; - 关键设置:Docker Desktop 中配置**镜像加速**(和服务器端一致,阿里云 / 网易云均可),避免本地拉取镜像超时。 ### 5.2 本地终端拉取本次部署所有所需镜像 打开本地终端(Windows 用 PowerShell/CMD,macOS/Linux 用终端),执行以下`docker pull`命令,逐个拉取镜像(按本次部署的版本号拉取,确保版本一致): ```bash # 1. 拉取MySQL8.0镜像 docker pull mysql:8.0 # 2. 拉取Redis7轻量版镜像 docker pull redis:7-alpine # 3. 拉取.NET8运行时镜像(后端运行依赖) docker pull mcr.microsoft.com/dotnet/aspnet:8.0 # 4. 拉取Nginx轻量版镜像 docker pull nginx:alpine ``` ✅ 拉取成功验证:本地终端执行`docker images`,能看到以上 4 个镜像,无报错即拉取完成。   ### 5.3 本地将镜像打包为 tar 文件(单镜像 / 批量镜像两种方式) 打包镜像有**单镜像打包**和**批量镜像打包**两种方式,推荐**批量打包为一个 tar 文件**(方便上传和服务器导入),以下两种方式均提供代码示例。 #### 方式 1:批量打包所有镜像为一个 tar 文件(推荐,一次导入所有) 将所有拉取的镜像打包为一个统一的 tar 文件(示例:rdif-all-images.tar),放在本地**易找到的目录**(如桌面),执行命令前先切换到目标目录(如 Windows 桌面目录): ```bash # Windows PowerShell切换到桌面目录(示例,可替换为自己的目录) cd C:\Users\你的用户名\Desktop # 批量打包镜像为rdif-all-images.tar(核心命令,包含所有所需镜像) docker save -o rdif-all-images.tar mysql:8.0 redis:7-alpine mcr.microsoft.com/dotnet/aspnet:8.0 nginx:alpine ``` - 关键参数:`-o` 指定输出的 tar 文件名和路径;后面跟**所有需要打包的镜像名:版本**,用空格分隔。 #### 方式 2:单个镜像单独打包(按需使用,适合单独更新镜像) 如果后续只需更新某个镜像(如仅更新 MySQL),可单独打包该镜像,命令如下: ```bash # 打包MySQL8.0为单独的tar文件 docker save -o mysql_8.0.tar mysql:8.0 # 打包Redis7-alpine为单独的tar文件 docker save -o redis_7_alpine.tar redis:7-alpine # 打包.NET8运行时为单独的tar文件 docker save -o dotnet_aspnet_8.0.tar mcr.microsoft.com/dotnet/aspnet:8.0 # 打包Nginx-alpine为单独的tar文件 docker save -o nginx_alpine.tar nginx:alpine ``` ### 5.4 验证本地打包成功 打包完成后,在本地目标目录(如桌面)能看到生成的 tar 文件(如 rdif-all-images.tar),文件大小约 2-3G(正常大小),即打包成功;后续用 MobaXterm/Xftp/WinSCP 将该 tar 文件上传到 CentOS 服务器的`/root/rdif-docker`目录即可。  ## 六、服务器端核心部署步骤(离线导入镜像 + 启动服务) ### 6.1 离线导入镜像(解决网络拉取超时,核心步骤) 将本地打包好的镜像 tar 文件上传到服务器后,执行以下命令离线导入,无需再联网拉取: ```bash # 1. 进入项目根目录(确保镜像tar包在该目录下) cd /root/rdif-docker # 2. 查看镜像tar包是否存在(能看到rdif-all-images.tar即正常) ls -l # 3. 离线导入所有镜像(耐心等待,约1-2分钟,镜像包约2-3G) docker load -i rdif-all-images.tar # 4. 验证镜像导入成功(能看到4个所需镜像即正常) docker images ``` ✅ 成功标识:`docker images`输出中包含`mysql:8.0`、`redis:7-alpine`、`nginx:alpine`、`mcr.microsoft.com/dotnet/aspnet:8.0`等镜像。  ### 6.2 启动所有服务(核心命令,一键启动) 所有配置和准备工作完成后,执行以下命令,一键启动所有容器,无需手动逐个启动: ```bash # 进入项目根目录(必须在docker-compose.yml所在目录执行) cd /root/rdif-docker # 后台启动所有服务(-d:后台运行,无需构建,因为前后端已打包) docker-compose up -d # 查看所有服务运行状态(所有服务State列显示Up即正常) docker-compose ps ``` ✅ 成功标识:`docker-compose ps`输出中,mysql、redis、backend、nginx 四个服务的 State 列均为`Up (healthy)`或`Up`。  ### 6.3 验证服务启动成功(逐个验证,确保无问题) 启动后,逐个验证前端、后端、数据库、Redis 是否正常,避免后续使用时出现问题: #### (1)验证后端服务(Swagger 访问,核心) .NET8 后端默认集成 Swagger,访问地址:`http://192.168.1.100:58588/swagger/index.html`(替换成自己的虚拟机 IP 和后端端口) - ✅ 成功标识:浏览器能正常打开 Swagger 页面,无报错,能看到所有接口; - ❌ 失败排查:如果打不开,执行`docker-compose logs -f backend`,查看后端实时日志,排查问题(如端口监听错误、MySQL 连接失败)。  #### (2)验证前端服务(静态页面访问) 前端由 Nginx 代理,访问地址:`http://192.168.1.100:6866`(替换成自己的虚拟机 IP 和前端端口) - ✅ 成功标识:浏览器能正常打开 Vue3 前端页面,样式、图片正常显示; - ❌ 失败排查:打不开则查看 Nginx 日志,命令:`docker-compose logs -f nginx`,检查 Nginx 配置是否正确、dist 目录是否挂载成功。  #### (3)验证 MySQL 服务(本地工具连接) 用 Navicat 或 DBeaver 等本地数据库工具,连接虚拟机上的 MySQL: - 主机:192.168.1.100(虚拟机 IP) - 端口:3306 - 用户名:guosisoft(自定义的 MySQL 用户名) - 密码:Mysql@123456(自定义的密码) - 数据库:rdif_vue3(自定义的数据库名) - ✅ 成功标识:能正常连接,能看到 init.sql 初始化的库、表和数据。 #### (4)验证 Redis 服务(可选,按需验证) 用 Redis 客户端工具(如 Another Redis Desktop Manager),连接虚拟机上的 Redis: - 主机:192.168.1.100(虚拟机 IP) - 端口:6379 - 密码:Redis@123456(自定义的 Redis 密码) - ✅ 成功标识:能正常连接,能执行 set、get 等命令。 ## 七、部署过程中遇到的坑及解决方案(重点,避坑指南) 这部分是核心,记录了我部署过程中遇到的所有问题,每个问题都有详细的排查过程和解决方案,亲测有效,帮你少走弯路。 ### 坑 1:Docker 镜像拉取超时,提示 “dial tcp ... i/o timeout” - 现象:执行`docker pull mysql:8.0`或`docker-compose up -d`时,拉取镜像超时,提示访问`registry-1.docker.io`失败; - 排查:虚拟机能 ping 通百度(外网正常),镜像加速配置也生效,但仍拉取超时,推测是虚拟机网络有隐性限制(如内网拦截); - 解决方案:采用**离线导入镜像方案**(前文 5、6 小节已详细说明),在本地能联网的电脑上拉取镜像、打包成 tar 包,上传到服务器后用`docker load -i`导入,彻底跳过网络拉取。 ### 坑 2:后端服务启动成功,但访问`http://192.168.1.100:58588`打不开 Swagger - 现象:`docker-compose ps`显示 backend 服务是 Up 状态,但浏览器访问后端地址打不开,查看后端日志,显示`Now listening on: http://[::]:8080`; - 排查:后端容器默认监听 8080 端口,但 docker-compose.yml 中映射的是 58588:58588,端口不匹配,导致访问不通; - 解决方案:在 backend 服务的 environment 中,添加`ASPNETCORE_URLS: "http://*:58588"`,强制.NET8 容器内监听 58588 端口,和端口映射一致,重启后端容器即可。  ### 坑 3:后端日志提示 “Unable to connect to any of the specified MySQL hosts” - 现象:后端启动后,日志持续报错,无法连接 MySQL,但本地 Navicat 能正常连接虚拟机上的 MySQL; - 排查:本地能连接,说明 MySQL 端口映射正常;后端容器和 MySQL 容器在同一 Docker 网络,应该用容器名(mysql)访问,而非虚拟机 IP,排查后发现连接字符串正确,但后端启动早于 MySQL 初始化完成; - 解决方案: 1. 给 MySQL 服务添加健康检查(前文 docker-compose.yml 中的 healthcheck 配置),检测 MySQL 是否真正就绪; 2. 后端服务的 depends_on 中,添加`condition: service_healthy`,确保 MySQL 健康检查通过后,再启动后端; 3. 给 MySQL 连接字符串补充`AllowPublicKeyRetrieval=True;SslMode=None`,解决容器内连接 MySQL 的公钥检索和 SSL 限制。 ### 坑 4:执行`docker-compose down`提示配置无效,“Unsupported config option for services.backend: 'condition'” - 现象:执行 docker-compose 命令时,提示配置无效,不支持`condition`和`start_period`; - 排查:查看 docker-compose 版本,发现是 1.x 版本,不支持新版配置项; - 解决方案:升级 Docker Compose 到 V2 版本(前文二、4 小节已详细说明),升级后即可支持所有配置。 ### 坑 5:MySQL 容器时间比北京时间慢 8 小时 - 现象:MySQL 中查询当前时间(`select now();`),比北京时间慢 8 小时,影响项目时间相关功能; - 排查:Docker 容器默认使用 UTC 世界标准时间,国内使用东八区(CST),两者相差 8 小时; - 解决方案: 1. 给 MySQL 服务添加环境变量`TZ: Asia/Shanghai`,强制容器时区为东八区(核心); 2. 挂载宿主机的时区文件(`/etc/localtime:/etc/localtime:ro`),双重保障时区同步; 3. 给后端、Nginx、Redis 容器也添加相同的`TZ`环境变量,实现全服务时间统一; 4. 重建 MySQL 容器(环境变量修改后,单纯 restart 不生效,需`docker-compose stop mysql && docker-compose rm -f mysql && docker-compose up -d mysql`)。  ### 坑 6:虚拟机重启后,所有 Docker 服务都需要手动启动 - 现象:虚拟机重启后,Docker 服务和所有容器都停止了,需要手动执行`systemctl start docker`和`docker-compose up -d`; - 排查:Docker 服务未设置开机自启,容器的`restart: always`配置,需要 Docker 服务启动后才会生效; - 解决方案:设置 Docker 服务开机自启,命令:`systemctl enable docker`,后续虚拟机重启后,Docker 会自动启动,所有容器也会自动后台启动。 ### 坑 7:本地打包镜像后,服务器导入提示 “no such image” - 现象:执行`docker load -i rdif-all-images.tar`时,提示镜像不存在; - 排查:本地拉取的镜像版本和服务器 docker-compose.yml 中配置的版本不一致,或打包时镜像名拼写错误; - 解决方案:本地执行`docker images`确认镜像名和版本,确保和 docker-compose.yml 中完全一致,重新打包并上传。 ### 坑 8:虚拟机重启后IP变更问题 首先查看本地网络配置,如下参考:  虚拟机网络适配器设置为桥接模式。  在linux中执行命令: ```bash vim /etc/sysconfig/network-scripts/ifcfg-ens33 ```  保存后重启网络服务 ```bash systemctl restart network ``` ## 八、常用 Docker/Compose 管理命令(日常运维必备) 部署完成后,日常维护、排错,都会用到以下命令,整理好放在这里,方便后续使用(所有命令均亲测可用)。 ### (一)Docker 基础命令(全局通用) ```bash # 1. Docker服务管理(核心,开机自启/启停) systemctl start docker # 启动Docker服务 systemctl stop docker # 停止Docker服务 systemctl restart docker # 重启Docker服务 systemctl enable docker # Docker开机自启(永久生效) systemctl disable docker # 关闭Docker开机自启 systemctl status docker # 查看Docker服务状态 systemctl is-enabled docker # 检查Docker是否开机自启(输出enabled则是) # 2. 容器管理(日常排错、启停常用) docker ps # 查看**运行中**的容器 docker ps -a # 查看**所有**容器(运行+停止) docker start <容器名/ID> # 启动指定容器(用容器名,更方便) docker stop <容器名/ID> # 停止指定容器 docker restart <容器名/ID> # 重启指定容器(如后端容器:docker restart rdif-backend) docker rm <容器名/ID> # 删除指定停止的容器 docker rm -f <容器名/ID> # 强制删除**运行中**的容器(谨慎使用) docker exec -it <容器名/ID> /bin/bash # 进入容器交互终端(Alpine镜像用sh替代/bin/bash) docker logs <容器名/ID> # 查看容器日志(最新) docker logs -f <容器名/ID> # 实时查看容器日志(排错核心,重点) docker logs --tail 100 <容器名/ID> # 查看容器最后100行日志 # 3. 镜像管理(离线导入/打包常用) docker images # 查看本地所有镜像 docker rmi <镜像名/ID> # 删除指定镜像(无容器依赖时) docker rmi -f <镜像名/ID> # 强制删除镜像(忽略容器依赖,谨慎,如:docker rmi -f mysql:8.0) docker load -i <镜像tar包> # 离线导入镜像(如:docker load -i rdif-all-images.tar) docker save -o <输出tar包> <镜像名> # 打包本地镜像为tar包(如:docker save -o mysql8.tar mysql:8.0) docker pull <镜像名:版本> # 拉取远程镜像 docker system prune -f # 清理无用容器/镜像/缓存(无风险,推荐定期执行) # 4. 数据卷/网络管理(本次自动创建,按需查看) docker volume ls # 查看所有Docker数据卷(保存MySQL/Redis数据) docker network ls # 查看所有Docker网络(本次为rdif-network) ``` ### (二)Docker Compose 命令(项目管理核心,需在项目根目录执行) ```bash # 1. 核心启停命令(最常用) docker-compose up -d # 后台启动所有服务(无构建,本次核心用) docker-compose up -d --build # 后台启动+构建镜像(有Dockerfile时用) docker-compose down # 停止并删除所有容器(保留数据卷/镜像,安全) docker-compose stop # 仅停止所有容器(不删除,容器仍存在) docker-compose start # 启动已停止的所有容器 docker-compose restart # 重启所有服务(配置未改时用) docker-compose restart backend # 重启指定服务(如后端,无需重启所有服务) # 2. 状态/日志查看(排错常用) docker-compose ps # 查看所有服务运行状态(看是否Up) docker-compose logs -f # 实时查看所有服务日志 docker-compose logs -f <服务名> # 实时查看指定服务日志(如docker-compose logs -f backend,实时查看后端日志(排错重点) # 3. 其他常用 docker-compose config # 验证docker-compose.yml配置语法是否正确(避免配置错误) docker-compose rm <服务名> # 删除指定停止的服务容器 ``` ## 九、开机自启配置(无需手动干预,虚拟机重启自动恢复) 前面已经提到,这里再单独整理一遍,确保虚拟机重启后,所有服务自动启动,无需手动操作: ```bash # 1. 确保Docker服务开机自启(已配置,再次验证) systemctl enable docker systemctl is-enabled docker # 输出enabled即成功 # 2. 验证容器自动重启策略(docker-compose.yml已配置restart: always) docker-compose config | grep -i restart # 输出4个restart: always即正常 # 3. 测试验证(可选,手动重启虚拟机) reboot # 重启虚拟机,重新连接后,直接访问服务,确认能正常打开 ``` ✅ 成功标识:虚拟机重启后,无需执行任何命令,`docker-compose ps`显示所有服务都是 Up 状态,前端、后端、Swagger 都能正常访问。 ## 十、前后端更新方法(日常维护,简单高效) 后续需要更新前端或后端代码时,无需重新部署整个环境,直接替换打包 / 发布文件,重启对应服务即可,步骤如下: ### 1. 后端更新(VS2022+ 重新发布后) 1. 本地 VS2022+ 重新发布.NET8 项目,生成新的 publish 文件夹; 2. 用 Xftp 工具,将新的 publish 文件夹,覆盖服务器`/root/rdif-docker/backend/`下的旧 publish 文件夹; 3. 重启后端容器,更新生效: ```bash cd /root/rdif-docker docker-compose restart backend ``` ### 2. 前端更新(Vue3 重新打包后) 1. 本地 Vue3 项目重新打包(yarn build/npm run build),生成新的 dist 文件夹; 2. 用 Xftp 工具,将新的 dist 文件夹,覆盖服务器`/root/rdif-docker/frontend/`下的旧 dist 文件夹; 3. 重启 Nginx 容器,更新生效: ```bash cd /root/rdif-docker docker-compose restart nginx ``` ## 十一、总结与注意事项(最后提醒,避坑收尾) ### 总结 本次部署基于**Docker Compose**实现了.NET8 后端(已发布)+Vue 前端(已打包)+MySQL8+Redis+Nginx 的整套多服务容器化部署,全程亲测可复现,核心亮点: 1. 采用**离线镜像导入**方案,解决服务器网络拉取镜像超时问题,附本地拉取 + 打包完整步骤,新手也能上手; 2. 前后端无需容器内编译构建,直接挂载本地打包 / 发布文件,启动更快、更新更方便,适合已完成本地开发的项目; 3. 解决了**端口不通、MySQL 连接失败、时区时差、容器启动顺序、配置兼容、开机自启**等 6 大核心问题,附详细避坑方案; 4. 所有配置集中在`docker-compose.yml`,一键启停、易维护、易迁移,虚拟机重启后服务自动恢复,无需手动干预; 5. 全程采用轻量版镜像(alpine),降低服务器资源占用,适合个人测试 / 小型项目部署。 ### 注意事项(重点避坑,生产环境必看) 1. **版本强一致**:本地拉取的镜像版本、docker-compose.yml 中的镜像版本、后端 / 前端的运行依赖版本,必须完全一致,避免兼容问题; 2. **容器间通信规则**:同一 Docker 自定义网络内,服务间访问**必须用容器名 / 服务名**(如后端连 MySQL 用`server=mysql`),而非服务器 IP;本地工具(Navicat/Redis 客户端)连接才用服务器 IP; 3. **环境变量修改规则**:修改容器的环境变量(如 TZ、ASPNETCORE_URLS、密码)后,**必须重建容器**(`stop+rm+up -d`),单纯`restart`不会加载新配置; 4. **数据持久化**:MySQL/Redis 数据通过 Docker**数据卷**持久化,`docker-compose down`不会删除数据卷,但手动执行`docker volume rm`会丢失数据,谨慎操作; 5. **敏感信息保护**:本文中的 IP、密码、镜像加速地址均为虚拟示例,实际部署请**替换为自己的真实信息**,并设置复杂密码(字母 + 数字 + 特殊符号); 6. 生产环境优化 :本文为个人测试环境 配置,生产环境需做以下优化: - 开启防火墙,仅开放项目所需端口(6866/58588/3306),执行`firewall-cmd --add-port=端口/tcp --permanent && firewall-cmd --reload`; - 禁用 root 账号直接登录,创建普通用户并赋予 Docker 操作权限; - 配置 SSL 证书,实现 HTTPS 访问; - 对 MySQL/Redis 做主从复制 / 集群,提升可用性; 7. **排错核心思路**:任何服务启动失败、访问不通,**优先查看容器日志**(`docker-compose logs -f 服务名`),日志是定位问题的最直接依据;  8. **镜像备份**:服务器端的离线镜像 tar 包建议保留,后续服务器重装可直接导入,无需重新本地打包。 整个部署过程虽然踩了不少坑,但核心问题都是忽略了**容器化的细节**(如端口匹配、时区配置、容器通信规则、启动顺序),只要按步骤做好配置、逐一验证,就能顺利完成部署。Docker Compose 的编排能力让多服务部署变得简单,也是后端开发必备的技能之一。 希望这篇详细的部署记录,能帮到有同样需求的朋友,少走弯路,高效完成.NET8+Vue 项目的 Docker 容器化部署。如果大家在部署过程中遇到其他问题,欢迎在评论区留言,一起交流解决~ ## 十二、结语 如果本文对你有一点点帮助,点个赞支持一下吧,你的每一个【赞】都是我创作的最大动力 _ 更多技术文章请往: [http://www.guosisoft.com/article](http://www.guosisoft.com/article) [http://www.rdiframework.net/article](http://www.rdiframework.net/article) 大家一起共同交流和进步呀!!
正文到此结束
本文标签:
.NET
RDIF.NET
常用工具
版权声明:
本站原创文章,由
guosisoft.com
发布,遵循
CC 4.0 by-sa
版权协议,转载请附上原文出处链接和本声明。
上一篇
国思RDIF低代码快速开发框架 v6.2.2版本发布
下一篇
已经到最后一篇了
热门推荐
{{article.title}}
热门指数:
浏览({{article.lookCount + 5000}})
相关文章
{{article.title}}
该篇文章的评论功能暂时被站长关闭
说给你听
本文目录
文章标签
RDIF.NET
其他
微信开发
.NET
消息交互
.NetCore
项目管理
常用工具
工作流
Web前端
数据库
挨踢业界
随机文章
.NET快速信息化系统开发框架 V3.2 -> “用户管理”主界面使用多表头展示、增加打印功能
RDIFramework.NET V3.3 Web版新增报表管理功能模块-重量级实用功能
.NET敏捷开发框架-RDIFramework.NET V5.1发布(跨平台)
C#实现Hash应用全解
.NET快速信息化系统开发框架 V3.2->Web版本“产品管理”事例编辑界面新增KindEditor复文本编辑控件
ORACLE常见问题一千问[901至1000](不怕学不成、就怕心不诚!)
史上最全面的SignalR系列教程-4、SignalR 自托管全解(使用Self-Host)-附各终端详细实例
经典的52条产品交互设计原则
微信公众号开发C#系列-3、搭建微信本地调试环境-借助花生壳实现内网穿透
RDIFramework.NET ━ .NET敏捷开发框架V3.5版本全新发布 100%源码授权
干货|工作中要使用Git,看这篇文章就够了
RDIFramework.NET敏捷开发框架 ━ 工作流程组件Web业务平台-3.6Ace版本
ORACLE常见问题一千问[301至400](不怕学不成、就怕心不诚!)
ORACLE PL/SQL编程之八:把触发器说透
值得一看的35个Redis常用问题总结
RDIFramework.NET WinForm版新增通知公告、系统新闻模块
[特别公告]RDIFramework.NET微信公众号迁移通知
ORACLE常见问题一千问[1至100](不怕学不成、就怕心不诚!)
RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2版本 正式发布
.NET分离exe和dll在不同的目录让你的程序更整洁
网站信息
文章总数:599 篇
标签总数:8 个
分类总数:8 个
留言数量:1385 条
在线人数:
89
人
运行天数:1321天
最后更新:2023-05-18
QQ:406590790
13005007127