Skip to main content

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 部署

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:

自定义配置

创建配置文件

# 创建配置目录
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 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. 监控告警

  • ✅ 监控数据库连接数
  • ✅ 监控慢查询数量
  • ✅ 监控磁盘使用率
  • ✅ 监控复制延迟
  • ✅ 设置告警阈值

故障排查

常见问题

  1. 无法连接数据库
# 检查容器状态
docker ps -a | grep mysql

# 查看日志
docker logs mysql

# 检查端口占用
netstat -tunlp | grep 3306
  1. 权限问题
-- 更新用户权限
GRANT ALL PRIVILEGES ON *.* TO 'username'@'%';
FLUSH PRIVILEGES;
  1. 字符集问题
-- 查看字符集
SHOW VARIABLES LIKE 'character%';

-- 修改表字符集
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

总结

关键要点
  • 使用 Docker Compose 管理 MySQL 容器
  • 配置数据持久化避免数据丢失
  • 使用自定义配置文件优化性能
  • 定期备份数据库
  • 监控数据库性能指标
  • 配置主从复制提高可用性

相关资源