配置开发环境:使用 Docker 管理多版本 MySQL 与 Redis
本文是「从 Windows 到 Ubuntu:迁移与配置完全指南」系列的开发环境篇。
适合已经完成 Ubuntu 系统安装,希望搭建高效、隔离、多版本数据库环境的开发者。
为什么要用 Docker 管理数据库?
在 Windows 下我习惯用 WSL2 + Docker 跑独立的数据库容器,迁移到 Ubuntu 后自然延续这一方式。相比直接在宿主机安装:
- 多版本共存:同一台机器同时运行 MySQL 5.7 和 8.0,Redis 任意版本,互不干扰。
- 环境隔离:每个项目的数据库独立或按版本共享,配置不打架。
- 轻量易清理:容器停止即释放资源,数据卷保留,删除无残留。
- 版本锁死:
mysql:5.7镜像永远对应 5.7 最新版,不会因系统升级自动变更。
本文以 MySQL 5.7、MySQL 8.0、Redis 7.2 为例,搭建三个独立容器,供后续 Go/PHP 项目共用。
一、安装 Docker 引擎(纯命令行,不用 Docker Desktop)
Ubuntu 的“软件”或“应用中心”无法搜到 Docker Desktop,这是 Linux 发行版软件分发的特点——专业工具通常需要手动添加官方软件源。官方源安装更轻量、稳定。
1. 卸载可能冲突的旧包(全新系统可跳过)
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do
sudo apt remove -y $pkg
done
如果你是全新安装的 Ubuntu 26.04,这些包本来就不存在,此步骤可跳过。
2. 添加 Docker 官方 GPG 密钥和软件源
sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl --http1.1 -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
踩坑记录:如果
curl下载 GPG 时报curl: (16) Error in the HTTP2 framing layer,加上参数--http1.1即可解决。
3. 安装 Docker 引擎及 Compose 插件
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
4. 将当前用户加入 docker 组(免 sudo 执行)
sudo usermod -aG docker $USER
必须注销并重新登录(或重启),否则 docker 命令仍需要 sudo。
5. 验证安装
docker --version # 输出如 Docker version 29.5.2
docker compose version # 输出 Docker Compose version v2.x
二、网络与镜像拉取问题排查(真实踩坑实录)
在 VPN 环境下,拉取第一个测试镜像时就遇到了网络超时。以下是完整的排查和解决过程。
2.1 第一次尝试:直接运行 hello-world
docker run hello-world
输出:
Unable to find image 'hello-world:latest' locally
docker: Error response from daemon: failed to resolve reference "docker.io/library/hello-world:latest": failed to do request: Head "https://registry-1.docker.io/v2/library/hello-world/manifests/latest": dial tcp 128.242.240.85:443: i/o timeout
2.2 重启 Docker 服务,再次尝试
sudo systemctl restart docker
docker run hello-world
仍然超时,这次 IP 变成了 31.13.69.245:
dial tcp 31.13.69.245:443: i/o timeout
2.3 检查宿主机能否访问 Docker Hub
curl -I https://registry-1.docker.io/v2/
输出:
HTTP/1.1 200 Connection established
HTTP/2 401
date: Sun, 31 May 2026 10:04:04 GMT
content-type: application/json
content-length: 87
...
这说明宿主机网络正常(返回 401 是因为没有认证,但连接已建立),问题出在 Docker 守护进程自身。
2.4 配置国内镜像加速器(第一次尝试)
创建 /etc/docker/daemon.json,使用中科大、网易、百度镜像:
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com"
]
}
EOF
sudo systemctl daemon-reload
docker run hello-world
结果依然超时(IP 变为 103.97.3.19):
dial tcp 103.97.3.19:443: i/o timeout
2.5 再次重启 Docker,问题依旧
sudo systemctl restart docker
docker run hello-world
这次错误变了:
dial tcp: lookup docker.mirrors.ustc.edu.cn on 127.0.0.53:53: no such host
说明镜像加速器的域名无法解析 —— VPN 影响了 DNS。
2.6 最终方案:使用 DaoCloud 镜像 + 指定公共 DNS
修改 /etc/docker/daemon.json,同时配置镜像和 DNS:
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://docker.m.daocloud.io"],
"dns": ["8.8.8.8", "1.1.1.1"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
docker run hello-world
这次终于成功拉取并运行:
latest: Pulling from library/hello-world
4f55086f7dd0: Pull complete
d5e71e642bf5: Download complete
Digest: sha256:0e760fdfbc48ba8041e7c6db999bb40bfca508b4be580ac75d32c4e29d202ce1
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
...
结论:在 VPN 环境下,Docker 守护进程可能无法正确使用系统 DNS,需要显式指定公共 DNS(如 8.8.8.8)并配合一个可用的镜像加速器。DaoCloud 镜像 docker.m.daocloud.io 在此环境中可用。
三、部署 MySQL 5.7 / 8.0 和 Redis 7.2 容器
3.1 创建项目目录
mkdir -p ~/docker/services
cd ~/docker/services
3.2 编写 docker-compose.yml
cat > docker-compose.yml << 'EOF'
version: "3.8" # 新版 Docker Compose 可省略该行,会有警告但无影响
networks:
dev-network:
driver: bridge
services:
mysql57:
image: mysql:5.7
container_name: mysql57
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: mystrongpwd57
ports:
- "3306:3306"
volumes:
- ./data/mysql57:/var/lib/mysql
networks:
- dev-network
mysql80:
image: mysql:8.0
container_name: mysql80
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: mystrongpwd80
ports:
- "3307:3306"
volumes:
- ./data/mysql80:/var/lib/mysql
networks:
- dev-network
command: --default-authentication-plugin=mysql_native_password
redis:
image: redis:7.2
container_name: redis72
restart: unless-stopped
ports:
- "6379:6379"
volumes:
- ./data/redis72:/data
command: redis-server --requirepass myredispass --appendonly yes
networks:
- dev-network
EOF
避坑提醒:MySQL 8.0 需要添加
--default-authentication-plugin=mysql_native_password,否则某些旧客户端连接会报caching_sha2_password错误。
3.3 第一次启动(遇到网络波动)
docker compose up -d
输出显示:
WARN[0000] the attribute `version` is obsolete...
[+] up 19/24
✘ Image mysql:8.0 Error failed to resolve reference ... EOF
错误原因是拉取 MySQL 8.0 时认证失败(EOF),可能是镜像加速器暂时性问题。
3.4 直接重试,成功
docker compose up -d
这次所有镜像都拉取成功:
[+] up 25/34
✔ Image mysql:5.7 Pulled
✔ Image redis:7.2 Pulled
✔ Image mysql:8.0 Pulled
✔ Network services_dev-network Created
✔ Container mysql57 Started
✔ Container redis72 Started
✔ Container mysql80 Started
经验:Docker Hub 或镜像加速器偶发性网络问题,重试一次往往就能解决。
四、验证容器运行及连接测试
4.1 查看容器状态
docker ps
输出:
CONTAINER ID IMAGE COMMAND STATUS PORTS NAMES
9ec38ca384b6 redis:7.2 "docker-entrypoint.s…" 45 seconds ago Up 42 seconds 0.0.0.0:6379->6379/tcp, [::]:6379->6379/tcp redis72
4e93fd2e2c3f mysql:8.0 "docker-entrypoint.s…" 45 seconds ago Up 42 seconds 33060/tcp, 0.0.0.0:3307->3306/tcp, [::]:3307->3306/tcp mysql80
29598dd51087 mysql:5.7 "docker-entrypoint.s…" 45 seconds ago Up 42 seconds 0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp, 33060/tcp mysql57
4.2 连接 MySQL 5.7
docker exec -it mysql57 mysql -uroot -pmystrongpwd57
进入 MySQL 命令行,执行 exit 退出。
4.3 连接 MySQL 8.0
docker exec -it mysql80 mysql -uroot -pmystrongpwd80
同样成功进入。
4.4 连接 Redis
docker exec -it redis72 redis-cli -a myredispass
输出提示 Warning: Using a password with '-a' ... may not be safe(仅安全警告,不影响使用),然后进入 127.0.0.1:6379> 提示符。
至此,三个数据库容器均已正常运行。

五、供项目容器连接(网络互通)
数据库容器位于自定义网络 services_dev-network(由 docker-compose 自动创建)。项目容器只需加入同一外部网络,即可通过 容器名 访问。
示例 docker-compose.yml 片段:
networks:
default:
external:
name: services_dev-network
services:
go-app:
image: golang:1.26-alpine
networks:
- default
environment:
DB_HOST: mysql57 # 或 mysql80
REDIS_HOST: redis72
代码中连接 mysql57:3306、redis72:6379 即可。
六、版本选择说明与注意事项
| 服务 | 版本 | 主流程度 | 生命周期提醒 |
|---|---|---|---|
| MySQL 5.7 | 5.7.44 | 占约 18.8%,属于遗留系统常用版本 | 已于 2023 年 10 月 EOL,不再有官方安全更新,非必要不建议新项目使用 |
| MySQL 8.0 | 8.0.46 | 当前最主流(占比 58%) | 官方支持将于 2026 年 4 月 30 日 结束,后续需升级到 8.4 LTS |
| Redis 7.2 | 7.2.x | 稳定且成熟 | 开源分支 Valkey 的基础版本,可放心使用 |
若为新项目,推荐直接使用 MySQL 8.4 LTS(支持至 2031 年)和 Redis 7.2。
七、日常管理命令速查
| 操作 | 命令 |
|---|---|
| 启动所有服务 | cd ~/docker/services && docker compose up -d |
| 停止所有服务 | cd ~/docker/services && docker compose down |
| 单独重启 MySQL 8.0 | docker restart mysql80 |
| 查看 MySQL 5.7 日志 | docker logs -f mysql57 |
| 进入 Redis 命令行 | docker exec -it redis72 redis-cli -a 密码 |
| 清理未使用的镜像/容器 | docker system prune -a |
| 备份数据卷 | tar -czf mysql57-backup.tar.gz ~/docker/services/data/mysql57 |
八、总结
至此,我们完成了一套干净、可复用的数据库容器环境:
- MySQL 5.7 → 端口 3306
- MySQL 8.0 → 端口 3307
- Redis 7.2 → 端口 6379
所有数据持久化在 ~/docker/services/data/,容器随系统启动自动运行。后续任何 Go、PHP、Node.js 项目,只需通过 Docker 网络连接这些容器名,即可快速获得多版本数据库支持。
本文命令均在 Ubuntu 26.04 下验证通过,Docker 版本 29.5.2。
如有疑问或交流,欢迎在评论区留言。