MySQL实战篇04_Docker入门实战:从零搭建MySQL容器环境
作者:进击的圆儿
日期:2025年10月10日
标签:DockerMySQL容器化实战后端开发
📑 目录
- 前言:为什么要学Docker?
- 第一部分:Docker核心概念理解
- Docker是什么?
- Docker vs 虚拟机
- Docker核心组件
- 第二部分:Docker环境准备
- 安装Docker Desktop
- WSL2的作用
- 验证Docker安装
- 第三部分:实战操作
- 创建Docker网络
- 启动MySQL容器
- 容器管理命令
- 第四部分:核心问题探讨
- 为什么需要端口映射?
- Docker网络如何工作?
- 容器与镜像的区别
- 写在最后

🎯 前言:为什么要学Docker?
在准备2026春招的MySQL主从复制学习过程中,我遇到了一个难题:
如何在一台电脑上模拟多台MySQL服务器?
传统方案:
- 安装多个MySQL实例?端口冲突、配置复杂
- 使用虚拟机?占用内存太大,我的电脑跑不动3个虚拟机
这时候,Docker出现了!
Docker能做什么?
- 5秒启动一个MySQL实例
- 占用内存极小(几百MB vs 虚拟机的几GB)
- 环境隔离,互不影响
- 删除容器后,宿主机不留任何痕迹
这篇博客记录了我从零学习Docker的全过程,包括遇到的问题和思考。
📚 第一部分:Docker核心概念理解
Docker是什么?
在学习Docker之前,我被问到了一个问题:
Q:Docker容器 vs 虚拟机,有什么区别?
我最初的理解:
假设我要在电脑上同时运行3个MySQL实例:
方案A:用虚拟机
我的电脑(Windows)
├─ VMware虚拟机1(需要4GB内存,完整的Linux系统)
│ └─ MySQL实例1
├─ VMware虚拟机2(需要4GB内存,完整的Linux系统)
│ └─ MySQL实例2
└─ VMware虚拟机3(需要4GB内存,完整的Linux系统)└─ MySQL实例3总消耗:12GB内存 + 3个完整操作系统
启动时间:每个虚拟机约2分钟
方案B:用Docker容器
我的电脑(Windows + WSL2)
└─ Docker引擎├─ MySQL容器1(共享宿主机内核,仅MySQL进程)├─ MySQL容器2(共享宿主机内核,仅MySQL进程)└─ MySQL容器3(共享宿主机内核,仅MySQL进程)总消耗:约2GB内存 + 共享1个Linux内核
启动时间:每个容器约2秒
我的结论:
- Docker快速:仅需创建进程,不需要启动完整系统
- Docker占用小:不需要完整系统内存,只包含应用和依赖库
- Docker依赖WSL2:Windows上需要Linux子系统支持
Docker vs 虚拟机架构对比
关键区别:
| 特性 | 虚拟机 | Docker容器 |
|---|---|---|
| 启动速度 | 分钟级 | 秒级 |
| 资源占用 | GB级(完整OS) | MB级(仅应用) |
| 隔离性 | 完全隔离 | 进程级隔离 |
| 性能 | 有损耗 | 接近原生 |
| 适用场景 | 需要不同OS | 相同OS,不同应用 |
Docker核心组件
学习过程中,我逐渐理解了Docker的3个核心概念:
1. 镜像(Image)
- 类比:软件安装包(.exe、.apk)
- 特点:只读、可复用
- 例子:
mysql:8.0= MySQL 8.0的镜像
2. 容器(Container)
- 类比:运行中的应用程序
- 特点:可读写、独立运行
- 例子:从
mysql:8.0镜像启动的MySQL实例
3. 网络(Network)
- 类比:局域网
- 特点:容器间互相通信
- 例子:
mysql-cluster网络,让Master和Slave能互相访问
关系图:
🛠️ 第二部分:Docker环境准备
安装Docker Desktop
我的环境:
- 操作系统:Windows 10
- 下载地址:Docker Desktop官(https://www.docker.com/products/docker-desktop/)
安装过程中的发现:
-
首次安装时,Docker提示需要下载WSL2

这让我有了一个疑问…
WSL2的作用是什么?
Q:这个"适用于Linux的Windows子系统"是干什么的?
我的理解过程:
┌─────────────────────────────────────────┐
│ 我的Windows 10/11电脑 │
│ ┌───────────────────────────────────┐ │
│ │ WSL2 (适用于Linux的Windows子系统) │ │ ← 今天下载的就是这个
│ │ - 真正的Linux内核 │ │
│ │ - 轻量级虚拟化 │ │
│ │ ┌─────────────────────────────┐ │ │
│ │ │ Docker引擎 (运行在WSL2上) │ │ │
│ │ │ ┌──────┐ ┌──────┐ ┌──────┐ │ │ │
│ │ │ │MySQL1│ │MySQL2│ │MySQL3│ │ │ │ ← Docker容器
│ │ │ └──────┘ └──────┘ └──────┘ │ │ │
│ │ └─────────────────────────────┘ │ │
│ └───────────────────────────────────┘ │
└─────────────────────────────────────────┘
为什么需要WSL2?
- Docker容器需要Linux内核支持
- Windows不能直接运行Linux容器
- WSL2提供轻量级Linux环境
WSL2 vs 完整虚拟机:
- WSL2启动速度:秒级
- 完整虚拟机启动:分钟级
- WSL2内存占用:动态分配
- 虚拟机内存:固定分配
验证Docker安装
步骤1:启动Docker Desktop
- 双击桌面图标
- 等待任务栏小鲸鱼图标不再转圈
步骤2:验证Docker版本
PS D:\pythontest\c++_learn> docker --version
Docker version 28.5.1, build e180ab8
✅ 成功!Docker已安装!
步骤3:查看运行中的容器
PS D:\pythontest\c++_learn> docker ps
CONTAINER ID IMAGE PORTS NAMES
70d72e14f5ab docker/welcome-to-docker:latest 0.0.0.0:8088->80/tcp welcome-to-docker
我的疑问来了:
Q1:这个
welcome-to-docker容器是Docker本身吗?
A:不是!Docker引擎是管理容器的"平台",welcome-to-docker是Docker官方提供的示例容器(一个Web应用)。
- Docker引擎 = 物业管理公司
- 容器 = 住户
welcome-to-docker= 第1个搬进来的住户
Q2:
8088->80是什么意思?
A:宿主机的8088端口映射到容器内部的80端口。访问localhost:8088就能访问容器内的Web服务。

🚀 第三部分:实战操作
目标:搭建1主2从MySQL集群
Master (mysql-master, 端口3307)↓ 主从复制├─→ Slave1 (mysql-slave1, 端口3308)└─→ Slave2 (mysql-slave2, 端口3309)
步骤1:创建Docker网络
在创建容器之前,我遇到了一个问题:
Q:我们要搭建1主2从的集群,为什么需要创建Docker网络?
我的思考过程:
Slave要连接Master,需要Master的什么信息?
- IP地址?
- 端口号?
方案对比:
| 方案 | Slave配置 | 问题 |
|---|---|---|
| 不创建网络 | MASTER_HOST='192.168.65.2' | IP重启后可能变化 |
| 创建网络 | MASTER_HOST='mysql-master' | 容器名自动解析为IP ✅ |
创建网络的优势:
- 容器名自动解析为IP(Docker内部DNS)
- 重启后容器名不变,配置不用改
- 配置简洁易读
执行命令:
PS D:\pythontest\c++_learn> docker network create mysql-cluster
877ed48bf8a2e6f7568976ce9d226ab18c6eb2053435a2afa0b7a3d5bac1fdbe
✅ 看到这一长串ID就表示成功了!
验证网络创建:
PS D:\pythontest\c++_learn> docker network ls
NETWORK ID NAME DRIVER SCOPE
f64587901f9d bridge bridge local
5fc40af8017e host host local
877ed48bf8a2 mysql-cluster bridge local ← 我们创建的网络
fd6ab0a7c172 none null local

步骤2:启动MySQL容器
在启动之前,先理解参数含义
Master容器启动命令:
docker run -d \--name mysql-master \ # 容器名--network mysql-cluster \ # 使用刚创建的网络-p 3307:3306 \ # 端口映射-e MYSQL_ROOT_PASSWORD=root123 \ # 环境变量mysql:8.0 # 镜像名
我的3个疑问:
Q1:为什么端口映射是
3307:3306,而不是3306:3306?
我的回答: 会端口冲突!
如果3个容器都用3306:3306:
宿主机端口3306 只能映射到1个容器 ❌
第2个容器启动时报错:"端口3306已被占用"
正确做法:
宿主机 容器内部
3307 → Master:3306
3308 → Slave1:3306
3309 → Slave2:3306
- 宿主机端口不能重复
- 容器内部都用3306(各自隔离)
Q2:
-e MYSQL_ROOT_PASSWORD=root123是什么意思?
我的回答: 配置环境变量,登录时用。
-e= environment(环境变量)- MySQL镜像启动时,读取这个变量
- 自动创建root用户,密码为
root123
Q3:
mysql:8.0中的:8.0是什么?
我的回答: 版本号!
mysql:8.0 ← 镜像名:版本号(标签)↑ ↑| └─ tag(标签),指定版本└────── 镜像名称
启动Master容器
PS D:\pythontest\c++_learn> docker run -d --name mysql-master --network mysql-cluster -p 3307:3306 -e MYSQL_ROOT_PASSWORD=root123 mysql:8.0
首次启动时,Docker会自动下载镜像:

✅ 看到这一长串ID就表示容器启动成功!
启动Slave1和Slave2容器
Slave1:
PS D:\pythontest\c++_learn> docker run -d --name mysql-slave1 --network mysql-cluster -p 3308:3306 -e MYSQL_ROOT_PASSWORD=root123 mysql:8.0
fd009cb4a90e77a3ebb4a55b012ea9d6b4639102c771f6c8a71de4a4a5a3c8f5
Slave2:
PS D:\pythontest\c++_learn> docker run -d --name mysql-slave2 --network mysql-cluster -p 3309:3306 -e MYSQL_ROOT_PASSWORD=root123 mysql:8.0
83ec709ec55b
因为镜像已经下载过了,这次启动非常快!
查看所有容器
PS D:\pythontest\c++_learn> docker ps
CONTAINER ID IMAGE PORTS NAMES
83ec709ec55b mysql:8.0 0.0.0.0:3309->3306/tcp mysql-slave2 ✅
fd009cb4a90e mysql:8.0 0.0.0.0:3308->3306/tcp mysql-slave1 ✅
d915377e1987 mysql:8.0 0.0.0.0:3307->3306/tcp mysql-master ✅

🎉 完美!1主2从MySQL集群容器全部启动成功!
Docker常用命令总结
| 命令 | 作用 | 示例 |
|---|---|---|
docker ps | 查看运行中的容器 | docker ps |
docker ps -a | 查看所有容器(包括停止的) | docker ps -a |
docker stop | 停止容器 | docker stop mysql-master |
docker start | 启动容器 | docker start mysql-master |
docker restart | 重启容器 | docker restart mysql-master |
docker rm | 删除容器 | docker rm mysql-master |
docker exec -it | 进入容器 | docker exec -it mysql-master bash |
docker logs | 查看容器日志 | docker logs mysql-master |
docker network ls | 查看网络列表 | docker network ls |
🤔 第四部分:核心问题探讨
为什么需要端口映射?
我最初的理解: “便于管理?”
实际原因:容器网络隔离!
没有端口映射:
- 外部无法访问容器的3306端口(网络隔离)
- 容器内部互相可以访问(通过容器名)
有端口映射 3307->3306:
- 访问宿主机3307 → 自动转发到容器3306
- 安全性:只暴露需要的端口
Docker网络如何工作?
Docker网络的作用:
关键特性:
- 容器名自动解析:
mysql-master→172.18.0.2 - 重启IP不变:容器重启后,IP可能变,但Docker DNS自动更新
- 网络隔离:不在同一网络的容器无法互相访问
容器与镜像的区别
我的类比理解:
| 对比项 | 镜像(Image) | 容器(Container) |
|---|---|---|
| 类比 | 软件安装包 | 运行中的程序 |
| 状态 | 只读 | 可读写 |
| 数量 | 1个镜像 | 可以启动多个容器 |
| 存储 | 分层存储(节省空间) | 在镜像基础上加一层可写层 |
| 删除 | 删除镜像不影响容器 | 删除容器不影响镜像 |
示例:
# 从mysql:8.0镜像启动3个容器
docker run -d --name mysql-master mysql:8.0
docker run -d --name mysql-slave1 mysql:8.0
docker run -d --name mysql-slave2 mysql:8.0# 3个容器共享同一个mysql:8.0镜像
# 但各自有独立的数据(可写层)
📝 写在最后
今天的收获
通过这次Docker实战,我掌握了:
✅ 概念理解
- Docker vs 虚拟机的本质区别
- WSL2的作用和意义
- 镜像、容器、网络的关系
✅ 实战技能
- 安装和配置Docker Desktop
- 创建Docker网络
- 启动和管理多个MySQL容器
- 理解端口映射原理
✅ 问题解决能力
- 通过提问和思考,深入理解每个参数的作用
- 学会了类比思维(物业管理公司、软件安装包等)
下一步计划
容器环境已经搭建好了,下一步要做的是:
-
配置MySQL主从复制
- Master开启binlog
- 创建复制用户
- Slave连接Master
-
测试主从复制
- 验证数据同步
- 测试读写分离
- 分析主从延迟
这些内容将在下一篇博客《MySQL主从复制Docker实战(上)》中详细记录!
参考资料
- Docker官方文档
- MySQL官方Docker镜像
- WSL2官方文档
如果这篇文章对你有帮助,欢迎点赞收藏!
有问题欢迎在评论区讨论~
系列文章:
- 上一篇:《MySQL模糊查询LIKE优化深度研究》
- 下一篇:《MySQL主从复制Docker实战(上):1主2从集群搭建与问题解决》
