📝 前言
最近我刚完成了一个"校园后勤维修工单管理系统"的全栈开发。项目采用了目前最主流的 技术栈:前端 Vue3 + Vite,后端 Spring Boot + MyBatis-Plus,数据库 MySQL 8.0 。
随着项目顺利跑通,如何把这套系统优雅、稳定地部署到云服务器上(CentOS)成了一个新的挑战。传统的部署方式需要手动装 JDK、配 MySQL、配 Node.js 和 Nginx,极其繁琐且容易因为环境不一致导致"在我电脑上明明跑得通"的玄学问题。
所以,我果断选择了 Docker / Docker Compose!本系列将分为上、中、下三篇,带你体验如何把一个前后端分离项目进行"现代化"的一键部署!
本篇为上篇,主要讲解:CentOS 服务器 Docker 环境搭建 以及数据库的容器化与自动初始化。
🛠️ 第一步:服务器 Docker 与 Docker Compose 环境搭建
拥有一台 CentOS 服务器后,第一件事就是安装 Docker。因为不可抗力原因,国内拉取 Docker 镜像可能很慢,所以我们要配置好国内的镜像加速。
1. 安装 Docker
bash
# 卸载旧版本(如果有)
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
# 配置阿里云 Docker Yum 源
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装 Docker 引擎
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 启动并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker
2. 配置镜像加速器
为了解决 docker pull 拉不到镜像或超时的问题,建议配置国内加速器服务。
bash
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://registry.aliyuncs.com"
]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
📂 第二步:梳理项目结构
针对 Docker 部署,我们在项目根目录新建一个 docker-compose.yml。部署版的基本结构如下:
text
project001/
├── docker-compose.yml # 核心编排文件
├── .env # 环境变量抽取(非常关键的坑,后续会讲)
├── backend/
│ └── SpringBoot/
│ ├── Dockerfile # 后端打包镜像配置
│ └── src/main/resources/sql/
│ ├── schema.sql # 建库建表SQL
│ └── seed.sql # 基础数据SQL
└── frontend/
└── vue/
├── Dockerfile # 前端打包配置
└── nginx.conf # Nginx反向代理配置
🐬 第三步:MySQL 数据库的容器化配置
传统方式我们需要自己去执行建表、导数据,而利用 Docker,我们可以让 MySQL 容器在第一次启动时,自动执行 SQL 脚本!
我们在 docker-compose.yml 中编写 MySQL 的配置:
yaml
version: '3.8'
services:
project001-mysql:
image: docker.m.daocloud.io/mysql:8.0
container_name: project001-mysql
restart: always # 宕机自动重启
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} # 从 .env 文件读取
MYSQL_DATABASE: campus_maintenance_sys
command:
- --default-authentication-plugin=mysql_native_password
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql # 数据持久化防止丢失
- ./backend/SpringBoot/src/main/resources/sql:/docker-entrypoint-initdb.d # 初始化导入脚本
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot", "-p${MYSQL_ROOT_PASSWORD}"]
interval: 10s
timeout: 5s
retries: 12
volumes:
mysql_data:
💡 这里的神仙操作解析:
- 自动初始化 :看
volumes第二行,我们把包含schema.sql和seed.sql的目录映射到了容器内部的/docker-entrypoint-initdb.d。MySQL 容器在首次启动,且数据目录为空 时,会自动按字母顺序执行这个目录下的所有.sql文件!这直接省去了我们手动连 Navicat 导数据的麻烦,一键搞定! - 字符集 :在
command里指定了utf8mb4,彻底避免中文乱码问题。 - 健康检查(healthcheck) :非常重要!后续我们的 Spring Boot 容器必须等待 MySQL 完全启动就绪后才能连数据库,光光看容器 status 变成 Up 是不够的。配置了健康检查,Docker 会用
mysqladmin ping不断去探测,直到 MySQL 真正能够对外提供服务。
⚠️ 一个价值好几个小时的避坑指南
请看 MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD},这里使用了外部环境变量。一定要在与 docker-compose.yml 同级的目录下新建一个 .env 文件:
env
MYSQL_ROOT_PASSWORD=你的复杂密码
**避坑:**如果你不小心在没有 .env 文件的情况下启动了 Docker compose(默认密码为空),事后再加上 .env 重启是没用的!因为 MySQL 只有在首次创建数据卷时才会读取环境变量初始化密码。如果你遇到了 Access denied for user 'root' (using password: NO/YES) 错误,必须删掉旧的错误数据卷重新初始化:
docker compose down -v (一定要带上 -v,清空残次品数据卷,再重新启动!)
🎯 总结
到这里,我们的服务器环境已经搭建完毕,且 MySQL 已经可以全自动地完成了建表与数据导入。在下一篇文章中,我将手把手带你编写 Spring Boot 的多阶段构建 Dockerfile,并将其和数据库做完美的编排串联,敬请期待!