Docker 部署 MySQL
快速启动
1. 基本运行
docker run -d \
--name mysql \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=your_password \
mysql:8.0
2. 带数据持久化
docker run -d \
--name mysql \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=your_password \
-v mysql_data:/var/lib/mysql \
mysql:8.0
Docker Compose 部署
- 基础配置
- 生产配置
- .env 文件
version: '3.8'
services:
mysql:
image: mysql:8.0
container_name: mysql
restart: always
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: your_password
MYSQL_DATABASE: mydb
MYSQL_USER: myuser
MYSQL_PASSWORD: mypassword
volumes:
- mysql_data:/var/lib/mysql
command:
--default-authentication-plugin=mysql_native_password
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
volumes:
mysql_data:
version: '3.8'
services:
mysql:
image: mysql:8.0
container_name: mysql
restart: always
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
TZ: Asia/Shanghai
volumes:
- mysql_data:/var/lib/mysql
- mysql_config:/etc/mysql/conf.d
- mysql_log:/var/log/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
command:
--default-authentication-plugin=mysql_native_password
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
--max_connections=1000
--innodb_buffer_pool_size=1G
--innodb_log_file_size=256M
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 3
volumes:
mysql_data:
mysql_config:
mysql_log:
# .env
MYSQL_ROOT_PASSWORD=YourStrongPassword@123
MYSQL_DATABASE=myapp
MYSQL_USER=appuser
MYSQL_PASSWORD=AppPassword@123
自定义配置
创建配置文件
# 创建配置目录
mkdir -p ./mysql/conf.d
# 创建自定义配置文件
cat > ./mysql/conf.d/custom.cnf << 'EOF'
[mysqld]
# 基础配置
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
default-time-zone='+08:00'
# 连接配置
max_connections=1000
max_connect_errors=100
# 缓存配置
innodb_buffer_pool_size=1G
innodb_log_file_size=256M
innodb_flush_log_at_trx_commit=2
innodb_flush_method=O_DIRECT
# 慢查询日志
slow_query_log=1
slow_query_log_file=/var/log/mysql/mysql-slow.log
long_query_time=2
# 二进制日志(用于主从复制)
log_bin=/var/log/mysql/mysql-bin.log
binlog_format=ROW
expire_logs_days=7
max_binlog_size=100M
[client]
default-character-set=utf8mb4
EOF
挂载配置文件
services:
mysql:
# ...
volumes:
- ./mysql/conf.d:/etc/mysql/conf.d:ro
初始化脚本
创建初始化 SQL
-- init.sql
CREATE DATABASE IF NOT EXISTS myapp DEFAULT CHARACTER SET utf8mb4;
USE myapp;
CREATE TABLE IF NOT EXISTS users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 创建索引
CREATE INDEX idx_username ON users(username);
CREATE INDEX idx_email ON users(email);
-- 插入测试数据
INSERT INTO users (username, email) VALUES
('admin', 'admin@example.com'),
('user1', 'user1@example.com');
-- 创建应用用户并授权
CREATE USER IF NOT EXISTS 'appuser'@'%' IDENTIFIED BY 'AppPassword@123';
GRANT ALL PRIVILEGES ON myapp.* TO 'appuser'@'%';
FLUSH PRIVILEGES;
常用命令
连接数据库
# 使用 Docker 命令连接
docker exec -it mysql mysql -uroot -p
# 使用 mysql 客户端连接
mysql -h localhost -P 3306 -uroot -p
备份和恢复
- 备份
- 恢复
# 备份单个数据库
docker exec mysql mysqldump -uroot -p${MYSQL_ROOT_PASSWORD} myapp > backup.sql
# 备份所有数据库
docker exec mysql mysqldump -uroot -p${MYSQL_ROOT_PASSWORD} --all-databases > all_backup.sql
# 压缩备份
docker exec mysql mysqldump -uroot -p${MYSQL_ROOT_PASSWORD} myapp | gzip > backup.sql.gz
# 定时备份脚本
cat > backup_mysql.sh << 'EOF'
#!/bin/bash
BACKUP_DIR="/backups/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
docker exec mysql mysqldump -uroot -p${MYSQL_ROOT_PASSWORD} --all-databases | \
gzip > $BACKUP_DIR/mysql_backup_$DATE.sql.gz
# 保留最近 7 天的备份
find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete
EOF
chmod +x backup_mysql.sh
# 添加到 crontab (每天凌晨 2 点备份)
# 0 2 * * * /path/to/backup_mysql.sh
# 恢复数据库
docker exec -i mysql mysql -uroot -p${MYSQL_ROOT_PASSWORD} < backup.sql
# 恢复压缩备份
gunzip < backup.sql.gz | docker exec -i mysql mysql -uroot -p${MYSQL_ROOT_PASSWORD}
# 恢复到指定数据库
docker exec -i mysql mysql -uroot -p${MYSQL_ROOT_PASSWORD} myapp < backup.sql
数据库管理
# 查看数据库列表
docker exec mysql mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "SHOW DATABASES;"
# 查看表列表
docker exec mysql mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "USE myapp; SHOW TABLES;"
# 查看用户权限
docker exec mysql mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "SELECT user, host FROM mysql.user;"
# 查看数据库大小
docker exec mysql mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "
SELECT
table_schema AS 'Database',
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'Size (MB)'
FROM information_schema.tables
GROUP BY table_schema;"
主从复制
主库配置
# docker-compose-master.yml
version: '3.8'
services:
mysql-master:
image: mysql:8.0
container_name: mysql-master
environment:
MYSQL_ROOT_PASSWORD: root_password
volumes:
- ./master/data:/var/lib/mysql
- ./master/conf.d:/etc/mysql/conf.d
ports:
- "3306:3306"
# master/conf.d/master.cnf
[mysqld]
server-id=1
log_bin=/var/log/mysql/mysql-bin.log
binlog_do_db=myapp
从库配置
# docker-compose-slave.yml
version: '3.8'
services:
mysql-slave:
image: mysql:8.0
container_name: mysql-slave
environment:
MYSQL_ROOT_PASSWORD: root_password
volumes:
- ./slave/data:/var/lib/mysql
- ./slave/conf.d:/etc/mysql/conf.d
ports:
- "3307:3306"
# slave/conf.d/slave.cnf
[mysqld]
server-id=2
relay-log=/var/log/mysql/mysql-relay-bin.log
read_only=1
配置主从同步
-- 在主库创建复制用户
CREATE USER 'repl'@'%' IDENTIFIED BY 'repl_password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
-- 查看主库状态
SHOW MASTER STATUS;
-- 在从库配置主库信息
CHANGE MASTER TO
MASTER_HOST='mysql-master',
MASTER_USER='repl',
MASTER_PASSWORD='repl_password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS= 154;
-- 启动从库
START SLAVE;
-- 查看从库状态
SHOW SLAVE STATUS\G
性能监控
使用 mysqladmin
# 查看状态
docker exec mysql mysqladmin -uroot -p${MYSQL_ROOT_PASSWORD} status
# 查看进程列表
docker exec mysql mysqladmin -uroot -p${MYSQL_ROOT_PASSWORD} processlist
# 查看扩展状态
docker exec mysql mysqladmin -uroot -p${MYSQL_ROOT_PASSWORD} extended-status
查看慢查询
# 进入容器查看慢查询日志
docker exec mysql tail -f /var/log/mysql/mysql-slow.log
# 分析慢查询
docker exec mysql mysqldumpslow /var/log/mysql/mysql-slow.log
最佳实践
最佳实践清单
1. 安全配置
- ✅ 使用强密码
- ✅ 限制 root 用户远程访问
- ✅ 为应用创建专用用户
- ✅ 使用环境变量管理密码
- ✅ 定期更新 MySQL 版本
2. 性能优化
- ✅ 根据服务器配置调整
innodb_buffer_pool_size
- ✅ 启用慢查询日志分析性能问题
- ✅ 合理设置连接数
max_connections
- ✅ 使用索引优化查询
- ✅ 定期优化表
OPTIMIZE TABLE
3. 数据安全
- ✅ 定期备份数据库
- ✅ 测试备份恢复流程
- ✅ 使用数据卷持久化数据
- ✅ 配置主从复制提高可用性
- ✅ 监控磁盘空间使用
4. 监控告警
- ✅ 监控数据库连接数
- ✅ 监控慢查询数量
- ✅ 监控磁盘使用率
- ✅ 监控复制延迟
- ✅ 设置告警阈值
故障排查
常见问题
- 无法连接数据库
# 检查容器状态
docker ps -a | grep mysql
# 查看日志
docker logs mysql
# 检查端口占用
netstat -tunlp | grep 3306
- 权限问题
-- 更新用户权限
GRANT ALL PRIVILEGES ON *.* TO 'username'@'%';
FLUSH PRIVILEGES;
- 字符集问题
-- 查看字符集
SHOW VARIABLES LIKE 'character%';
-- 修改表字符集
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
总结
关键要点
- 使用 Docker Compose 管理 MySQL 容器
- 配置数据持久化避免数据丢失
- 使用自定义配置文件优化性能
- 定期备份数据库
- 监控数据库性能指标
- 配置主从复制提高可用性