1. 为什么选择Docker部署MySQL?
十年前我第一次在生产环境部署MySQL时,光是处理依赖冲突就花了一整天。现在用Docker容器化部署,从下载镜像到服务可用只需5分钟。这种效率提升让我彻底爱上了容器化技术。
Docker版MySQL最大的优势在于环境隔离。传统安装方式常遇到"这个服务器上已经装了MariaDB"、"系统自带的libmysqlclient版本不兼容"等问题。而容器化的MySQL自带完整运行环境,不会污染宿主机,也不会被其他软件影响。更重要的是,你可以同时运行多个不同版本的MySQL实例进行测试,这在传统部署中几乎是不可能完成的任务。
2. 准备工作与环境配置
2.1 安装Docker引擎
在开始之前,确保你的系统已经安装了Docker CE(社区版)。以Ubuntu 20.04为例:
bash复制# 更新软件包索引
sudo apt-get update
# 安装依赖包
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
# 添加Docker官方GPG密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# 添加稳定版仓库
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
# 安装Docker引擎
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
# 验证安装
sudo docker run hello-world
注意:生产环境建议使用特定版本而非最新版,避免兼容性问题。可以通过
apt-cache madison docker-ce查看可用版本。
2.2 配置Docker加速器(国内用户)
国内拉取Docker镜像可能较慢,建议配置镜像加速器。创建或修改/etc/docker/daemon.json:
json复制{
"registry-mirrors": [
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com"
]
}
然后重启服务:
bash复制sudo systemctl daemon-reload
sudo systemctl restart docker
3. MySQL容器部署全流程
3.1 拉取官方MySQL镜像
Docker Hub提供了官方MySQL镜像,建议选择明确版本号而非latest标签:
bash复制# 拉取MySQL 8.0版本
docker pull mysql:8.0
# 查看已下载镜像
docker images | grep mysql
为什么选择8.0而不是最新版?因为MySQL 8.0是目前最稳定的生产版本,而某些应用可能还不兼容8.1+的新特性。我在去年就遇到过WordPress插件与MySQL 8.1的兼容性问题。
3.2 启动MySQL容器
最基本的启动命令:
bash复制docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:8.0
但这远远不够。生产环境应该考虑以下参数:
bash复制docker run --name=prod-mysql \
-e MYSQL_ROOT_PASSWORD=Str0ngP@ss \
-e MYSQL_DATABASE=app_db \
-e MYSQL_USER=app_user \
-e MYSQL_PASSWORD=UserP@ss \
-p 3306:3306 \
-v /data/mysql:/var/lib/mysql \
--restart=unless-stopped \
-d mysql:8.0 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci \
--default-time-zone=+8:00
参数解析:
-v /data/mysql:/var/lib/mysql:将数据目录挂载到宿主机,避免容器销毁后数据丢失--restart=unless-stopped:容器意外退出时自动重启utf8mb4字符集:支持完整的emoji和特殊字符- 时区设置为东八区
3.3 验证容器状态
bash复制# 查看运行中的容器
docker ps
# 查看MySQL日志
docker logs prod-mysql
# 检查MySQL服务状态(容器内)
docker exec prod-mysql mysqladmin -uroot -p status
如果看到"Uptime"信息,说明MySQL已正常启动。第一次启动可能需要30秒左右进行初始化。
4. 高级配置与优化
4.1 自定义配置文件
默认配置可能不适合生产环境,我们可以挂载自定义my.cnf:
bash复制# 创建配置目录
mkdir -p /data/mysql/conf.d
# 创建配置文件
cat > /data/mysql/conf.d/custom.cnf <<EOF
[mysqld]
max_connections=200
innodb_buffer_pool_size=1G
query_cache_size=64M
slow_query_log=1
long_query_time=2
log_queries_not_using_indexes=1
EOF
# 重新启动容器并挂载配置
docker run ... -v /data/mysql/conf.d:/etc/mysql/conf.d ...
重要提示:修改innodb_buffer_pool_size不要超过容器可用内存的70%。可以通过
docker inspect prod-mysql | grep Memory查看容器内存限制。
4.2 性能优化参数
根据服务器配置调整以下参数:
ini复制# 对于8核CPU、16GB内存的服务器
innodb_buffer_pool_size=12G
innodb_log_file_size=2G
innodb_flush_method=O_DIRECT
innodb_io_capacity=2000
innodb_io_capacity_max=4000
4.3 安全加固建议
- 修改root密码并创建应用专用用户
- 限制连接IP(通过MySQL的GRANT命令)
- 启用SSL连接(需要生成证书并挂载到容器)
- 定期备份数据(即使有volume也要额外备份)
5. 日常操作与维护
5.1 进入MySQL命令行
bash复制# 交互式登录
docker exec -it prod-mysql mysql -uroot -p
# 执行单条命令
docker exec prod-mysql mysql -uroot -p -e "SHOW DATABASES;"
5.2 备份与恢复
bash复制# 备份所有数据库
docker exec prod-mysql sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > /backup/all-databases.sql
# 恢复备份
cat /backup/all-databases.sql | docker exec -i prod-mysql mysql -uroot -p"$MYSQL_ROOT_PASSWORD"
5.3 监控与日志
bash复制# 查看慢查询日志
docker exec prod-mysql cat /var/lib/mysql/mysql-slow.log
# 实时监控
docker exec prod-mysql mysqladmin -uroot -p extended-status
6. 常见问题排查
6.1 容器启动失败
现象:docker ps看不到MySQL容器,docker logs显示权限错误。
解决方案:
bash复制# 检查volume目录权限
chown -R 999:999 /data/mysql
MySQL容器内默认以mysql用户(UID 999)运行,宿主机volume目录需要相应权限。
6.2 连接数不足
现象:应用程序报"Too many connections"错误。
解决方案:
bash复制# 临时增加连接数
docker exec prod-mysql mysql -uroot -p -e "SET GLOBAL max_connections=300;"
# 永久修改需要更新配置文件并重启容器
6.3 性能下降
排查步骤:
- 检查慢查询日志
- 分析当前连接数:
show status like 'Threads_connected'; - 查看InnoDB状态:
show engine innodb status\G - 检查锁等待:
select * from performance_schema.events_waits_current;
7. 生产环境最佳实践
-
使用Docker Compose:对于复杂环境,建议使用docker-compose.yml管理多个相关容器(如MySQL+Redis+应用)
-
资源限制:为容器设置合理的CPU和内存限制
yaml复制deploy: resources: limits: cpus: '2' memory: 4G -
监控集成:将MySQL指标导出到Prometheus等监控系统
-
定期维护:每周执行
OPTIMIZE TABLE对频繁更新的表进行维护 -
版本升级:小版本升级可以直接修改镜像标签,大版本升级需要dump/restore
我在去年迁移一个5.7到8.0的实例时,就因为直接修改标签导致兼容性问题。后来通过以下步骤安全升级:
- 在新容器启动8.0实例
- 使用mysqldump导出5.7数据
- 使用mysql_upgrade工具处理兼容性问题
- 导入数据到8.0
- 测试确认后切换应用连接
整个过程耗时约2小时,但实现了零停机升级(通过负载均衡切换)。