做容器化部署时,单靠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 安装、命令执行失败:

# 更新系统软件包(可选,建议执行,避免依赖版本过低)
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 依赖):

# 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 守护进程配置文件:

# 创建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 版本(官方推荐):

# 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 防火墙,避免前端、后端、数据库端口被拦截,生产环境可按需开放端口:

# 1. 立即停止防火墙服务
systemctl stop firewalld

# 2. 禁止防火墙开机自启(避免虚拟机重启后防火墙又开启)
systemctl disable firewalld

# 3. 验证防火墙状态(输出inactive即成功关闭)
systemctl status firewalld

三、项目目录结构整理(规范目录,避免后续混乱)

将本地准备好的所有文件,上传到 CentOS7 虚拟机的/root/rdif-docker目录(自定义目录,方便记忆),最终目录结构如下(重点:前后端仅保留打包 / 发布文件,无源码、无多余文件):

项目目录结构

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 密码已替换为通用虚拟密码):

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命令,逐个拉取镜像(按本次部署的版本号拉取,确保版本一致):

# 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

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐