Docker 搭建MySQL服务
·
一、搭建单节点服务
使用Docker来下载并启动MySQL,主要步骤包括:拉取MySQL镜像、运行容器、以及一些常见的配置(如设置密码、映射端口、挂载数据卷等)。
- 拉取MySQL官方镜像
- 创建本地数据存储目录和自定义配置文件目录(用于持久化和配置)
- 创建自定义配置文件(可选,但建议)
- 运行容器,并设置环境变量、端口映射、数据卷等
- 验证连接
1. 拉取mysql镜像
首先,我们需要从镜像仓库中拉取MySQL镜像。可以选择特定版本(如8.0, 5.7等)或使用默认的最新版本。
-
如果不指定版本,默认拉取最新版。
docker pull mysql -
拉取指定版本,例如拉取MySQL 8.0。
docker pull mysql:8.0
2. 创建目录
我们将在主机上创建三个目录:主要用于存储MySQL数据、自定义配置以及日志文件。
# 存储MySQL数据
mkdir -p /usr/local/src/mysql/data
# 存储MySQL自定义配置文件
mkdir -p /usr/local/src/mysql/conf
# 存储日志文件
mkdir -p /usr/local/src/mysql/logs
3. 创建自定义配置文件(可选)
在 /usr/local/src/mysql/conf 目录下创建一个名为 my.cnf 的文件,用于设置MySQL的配置。
cat > /usr/local/src/mysql/conf/my.cnf << 'EOF'
[mysqld]
# 基础设置
user = mysql
port = 3306
socket = /var/run/mysqld/mysqld.sock
# 字符集设置
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect = 'SET NAMES utf8mb4'
# 存储引擎
default-storage-engine = InnoDB
# 连接设置
max_connections = 1000
max_connect_errors = 100000
wait_timeout = 28800
interactive_timeout = 28800
# 缓冲区设置
key_buffer_size = 256M
max_allowed_packet = 64M
thread_stack = 512K
thread_cache_size = 128
sort_buffer_size = 4M
read_buffer_size = 4M
read_rnd_buffer_size = 8M
join_buffer_size = 4M
# InnoDB 设置
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
innodb_log_buffer_size = 16M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50
innodb_file_per_table = 1
innodb_flush_method = O_DIRECT
# 日志设置
log_error = /var/log/mysql/error.log
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
log_queries_not_using_indexes = 1
# 二进制日志(主从复制用)
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 7
max_binlog_size = 100M
binlog_format = row
[mysql]
default-character-set = utf8mb4
[client]
default-character-set = utf8mb4
port = 3306
socket = /var/run/mysqld/mysqld.sock
EOF
4. 运行容器
使用docker run命令来启动一个MySQL容器。以下是一些常用参数:
-p:端口映射,后面紧接着的3306:3306是要进行映射的端口,冒号左边的3306是宿主机的端口号,冒号右边的3306是mysql容器的端口,-p的作用是将mysql容器的3306端口映射到宿主机的3306端口,这样就可以通过宿主机的ip+映射到宿主机的3306端口就能连接上启动的mysql容器。-e:后面紧接着的MYSQL_ROOT_PASSWORD=root,是指定mysql容器的root用户登陆密码。-d:表示以守护进程的方式启动服务,服务在后台运行。--name:指定启动后的容器名。-v:持久化数据,将容器的数据交给宿主机管理,主要也是为了同步数据,防止容器被删除后数据找不到的问题。/root/data 这是宿主机的数据存放路径;/var/lib/mysql 这是mysql容器存放数据的地方。--restart=unless-stopped:容器退出时自动重启,除非用户明确执行了 docker stop 命令。
-
示例1:基本运行
docker run -d --name mysql-server -e MYSQL_ROOT_PASSWORD=my-secret-pw -p 3306:3306 mysql:8.0 -
示例2:使用数据卷持久化数据
- 为了持久化MySQL数据(即使容器删除,数据也不会丢失),我们可以将MySQL的数据目录挂载到主机上。
- /host/path/to/mysql/data是主机上的一个目录,用于存储MySQL的数据。
docker run -d --name mysql-server \ -e MYSQL_ROOT_PASSWORD=root123 \ -p 3306:3306 \ -v /usr/local/src/mysql/data:/var/lib/mysql \ mysql:8.0 -
示例3:使用自定义配置文件
- 如果需要自定义MySQL配置,可以将自定义的my.cnf文件挂载到容器中。
- 首先,确保主机上有一个自定义的配置文件,例如/host/path/to/my.cnf。然后运行:
docker run -d --name mysql-server \ -e MYSQL_ROOT_PASSWORD=root123 \ -p 3306:3306 \ -v /usr/local/src/mysql/data:/var/lib/mysql \ -v /usr/local/src/mysql/conf/my.cnf:/etc/mysql/my.cnf \ mysql:8.0 -
完整配置示例:
docker run -d \ --name mysql-server \ -e MYSQL_ROOT_PASSWORD=root123 \ -p 3306:3306 \ -v /usr/local/src/mysql/data:/var/lib/mysql \ -v /usr/local/src/mysql/conf/my.cnf:/etc/mysql/my.cnf \ -v /usr/local/src/mysql/logs:/var/log/mysql \ --restart=unless-stopped \ mysql:8.0 \ --character-set-server=utf8mb4 \ --collation-server=utf8mb4_unicode_ci
3. 连接MySQL
容器启动后,你可以使用任何MySQL客户端连接它。
-
从容器内部连接:
# 进入容器 docker exec -it mysql-server bash # 连接MySQL mysql -u root -p -
从外部连接:
# 使用MySQL客户端 mysql -h 127.0.0.1 -P 3306 -u root -p然后输入密码,即可连接到MySQL。
-
使用Navicat连接通过宿主机的ip+运行命令时映射的端口联连接数据库了:

4.常用管理命令
# 查看运行中的容器
docker ps
# 查看MySQL日志
docker logs mysql-server
# 查看实时日志
docker logs -f mysql-server
# 停止容器
docker stop mysql-server
# 启动容器
docker start mysql-server
# 重启容器
docker restart mysql-server
# 删除容器
docker rm mysql-server
# 删除容器和数据卷
docker rm -v mysql-server
5. 数据库备份脚本 backup-mysql.sh
cat > backup-mysql.sh << 'EOF'
#!/bin/bash
source .env
BACKUP_FILE="backup_$(date +%Y%m%d_%H%M%S).sql"
echo "开始备份数据库..."
docker exec ${CONTAINER_NAME} mysqldump \
-u root \
-p${MYSQL_ROOT_PASSWORD} \
--single-transaction \
--routines \
--triggers \
--databases ${MYSQL_DATABASE} > ${BACKUP_DIR}/${BACKUP_FILE}
if [ $? -eq 0 ]; then
echo "✅ 备份成功: ${BACKUP_DIR}/${BACKUP_FILE}"
# 压缩备份文件
gzip ${BACKUP_DIR}/${BACKUP_FILE}
echo "📦 已压缩: ${BACKUP_DIR}/${BACKUP_FILE}.gz"
else
echo "❌ 备份失败!"
fi
EOF
chmod +x backup-mysql.sh
docker exec mysql-server: 在名为mysql-server的容器中执行命令。sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"': 这是要在容器内执行的命令。sh -c: 启动一个shell来执行后面的字符串命令。exec: 用后面的命令替换当前shell进程(这样就不会有额外的shell进程残留)。mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD": 使用mysqldump工具备份所有数据库,以root用户登录,并使用环境变量MYSQL_ROOT_PASSWORD的值作为密码。
> backup.sql: 将容器内命令的标准输出重定向到宿主机上的backup.sql文件。
6. 常用维护命令
# 检查容器状态
docker ps -a
# 查看容器日志
docker logs mysql-server
# 查看实时日志
docker logs -f mysql-server
# 进入容器
docker exec -it mysql-server bash
# 查看容器资源使用
docker stats mysql-server
# 重启容器
docker restart mysql-server
7. 性能监控
# 查看MySQL状态
docker exec mysql-server mysql -uroot -p -e "SHOW STATUS LIKE 'Threads_connected';"
# 查看进程列表
docker exec mysql-server mysql -uroot -p -e "SHOW PROCESSLIST;"
# 查看变量设置
docker exec mysql-server mysql -uroot -p -e "SHOW VARIABLES LIKE '%buffer%';"
二、搭建MySQL主从复制集群
使用Docker Compose来部署一个主节点和两个从节点。以下是步骤:
- 创建目录结构
- 编写Docker Compose文件
- 配置MySQL主从节点的配置文件
- 启动和配置主从复制
2.1 创建目录结构
cd /usr/local/src/mysql
mkdir -p mysql-cluster/{master,slave1,slave2}/{data,conf,logs}
2.2 创建 Docker Compose 文件
进入到mysql-cluster目录,创建docker-compose-master-slave.yml:
version: '3.8'
services:
mysql-master:
image: mysql:8.0
container_name: mysql-master
environment:
MYSQL_ROOT_PASSWORD: root123
ports:
- "3306:3306"
volumes:
- ./master/data:/var/lib/mysql
- ./master/conf:/etc/mysql/conf.d
command:
- --server-id=1
- --log-bin=mysql-bin
- --binlog-format=ROW
- --gtid-mode=ON
- --enforce-gtid-consistency=ON
- --bind-address=0.0.0.0 # 确保绑定到所有接口
networks:
mysql-net:
aliases:
- mysql-master
mysql-slave-1:
image: mysql:8.0
container_name: mysql-slave-1
environment:
MYSQL_ROOT_PASSWORD: root123
ports:
- "3307:3306"
volumes:
- ./slave1/data:/var/lib/mysql
- ./slave1/conf:/etc/mysql/conf.d
command:
- --server-id=2
- --log-bin=mysql-bin
- --binlog-format=ROW
- --gtid-mode=ON
- --enforce-gtid-consistency=ON
- --read-only=1
- --bind-address=0.0.0.0
depends_on:
- mysql-master
networks:
mysql-net:
aliases:
- mysql-slave-1
mysql-slave-2:
image: mysql:8.0
container_name: mysql-slave-2
environment:
MYSQL_ROOT_PASSWORD: root123
ports:
- "3308:3306"
volumes:
- ./slave2/data:/var/lib/mysql
- ./slave2/conf:/etc/mysql/conf.d
command:
- --server-id=3
- --log-bin=mysql-bin
- --binlog-format=ROW
- --gtid-mode=ON
- --enforce-gtid-consistency=ON
- --read-only=1
- --bind-address=0.0.0.0
depends_on:
- mysql-master
networks:
mysql-net:
aliases:
- mysql-slave-2
networks:
mysql-net:
driver: bridge
name: mysql-cluster-network # 明确指定网络名称
2.3 创建 MySQL 配置文件
-
主节点配置 (master/conf/my.cnf):
cat > ./master/conf/my.cnf << 'EOF' [mysqld] # 服务器ID,必须唯一 server-id=1 # 二进制日志配置 log-bin=mysql-bin binlog-format=ROW expire_logs_days=7 # GTID 配置 gtid-mode=ON enforce-gtid-consistency=ON # 认证插件配置 - 使用旧版认证插件 default_authentication_plugin=mysql_native_password # 网络配置 bind-address=0.0.0.0 # 性能优化 innodb_buffer_pool_size=256M innodb_log_file_size=128M max_connections=200 # 复制配置 relay-log=mysql-relay-bin log-slave-updates=ON [mysql] prompt="Master [\\d]> " EOF -
从节点配置 (slave1/conf/my.cnf, slave2/conf/my.cnf):
for slave_dir in slave1 slave2; do cat > "./$slave_dir/conf/my.cnf" << EOF [mysqld] # 服务器ID,必须唯一 server-id=$([ "$slave_dir" = "slave1" ] && echo "2" || echo "3") # 二进制日志配置 log-bin=mysql-bin binlog-format=ROW expire_logs_days=7 # GTID 配置 gtid-mode=ON enforce-gtid-consistency=ON # 认证插件配置 - 使用旧版认证插件 default_authentication_plugin=mysql_native_password # 从节点只读 read_only=1 # 网络配置 bind-address=0.0.0.0 # 性能优化 innodb_buffer_pool_size=256M innodb_log_file_size=128M max_connections=200 # 复制配置 relay-log=mysql-relay-bin log-slave-updates=ON [mysql] prompt="Slave$([ "$slave_dir" = "slave1" ] && echo "1" || echo "2") [\\\\d]> " EOF done
2.4 启动和配置主从复制
# 启动服务
docker-compose -f docker-compose-master-slave.yml up -d
# 等待 MySQL 启动
sleep 30
# 在主节点创建复制用户
docker exec -it mysql-master mysql -uroot -proot123 -e "
CREATE USER 'repl'@'%' IDENTIFIED BY 'repl123';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
SHOW MASTER STATUS\G
"
# 在从节点配置复制
for slave in mysql-slave-1 mysql-slave-2; do
docker exec -it $slave mysql -uroot -proot123 -e "
CHANGE MASTER TO
MASTER_HOST='mysql-master',
MASTER_USER='repl',
MASTER_PASSWORD='repl123',
MASTER_AUTO_POSITION=1;
START SLAVE;
SHOW SLAVE STATUS\G
"
done
# 验证复制状态
docker exec mysql-slave-1 mysql -uroot -proot123 -e "SHOW SLAVE STATUS\G" | grep -E "Slave_IO_Running|Slave_SQL_Running"
2.5 数据验证脚本
#!/bin/bash
# verify_replication_working.sh
echo "=== 验证主从复制数据同步 ==="
# 1. 在主节点创建测试数据
echo "1. 在主节点创建测试数据..."
docker exec mysql-master mysql -uroot -proot123 -e "
-- 创建测试数据库
CREATE DATABASE IF NOT EXISTS replication_verified;
USE replication_verified;
-- 创建测试表
CREATE TABLE IF NOT EXISTS sync_test (
id INT AUTO_INCREMENT PRIMARY KEY,
node_name VARCHAR(50),
data_value VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 插入测试数据
INSERT INTO sync_test (node_name, data_value) VALUES
('master', '数据来自主节点'),
('master', '这是第二条测试数据'),
('master', '复制验证测试数据');
-- 显示插入的数据
SELECT '主节点数据:' AS '';
SELECT * FROM sync_test;
-- 显示数据统计
SELECT '数据统计:' AS '';
SELECT COUNT(*) AS total_records FROM sync_test;
"
# 2. 等待复制完成
echo ""
echo "2. 等待数据复制 (3秒)..."
sleep 3
# 3. 验证从节点数据
echo ""
echo "3. 验证从节点数据同步:"
for slave in mysql-slave-1 mysql-slave-2; do
echo "=== $slave 数据验证 ==="
# 检查数据是否存在
docker exec $slave mysql -uroot -proot123 -e "
USE replication_verified;
SELECT '数据记录:' AS '';
SELECT * FROM sync_test;
SELECT '数据统计:' AS '';
SELECT COUNT(*) AS record_count FROM sync_test;
"
# 验证数据一致性
master_count=$(docker exec mysql-master mysql -uroot -proot123 -N -e "USE replication_verified; SELECT COUNT(*) FROM sync_test;")
slave_count=$(docker exec $slave mysql -uroot -proot123 -N -e "USE replication_verified; SELECT COUNT(*) FROM sync_test;")
if [ "$master_count" -eq "$slave_count" ]; then
echo "✅ $slave 数据同步正常 (记录数: $slave_count)"
else
echo "❌ $slave 数据同步异常 (主节点: $master_count, 从节点: $slave_count)"
fi
echo ""
done
echo "=== 数据同步验证完成 ==="
三、容器密码修改
3.1 方法一:进入容器修改
-
进入 MySQL 容器
# 直接连接 MySQL docker exec -it mysql-container mysql -u root -p # 输入当前密码 -
修改密码(MySQL 8.0+)
-- 登录后执行 ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码'; FLUSH PRIVILEGES; -- 如果是远程访问用户 ALTER USER 'root'@'%' IDENTIFIED BY '新密码'; FLUSH PRIVILEGES; -
修改密码(MySQL 5.7 及以下)
-- 方法1 SET PASSWORD FOR 'root'@'localhost' = PASSWORD('新密码'); FLUSH PRIVILEGES; -- 方法2 UPDATE mysql.user SET authentication_string = PASSWORD('新密码') WHERE User = 'root'; FLUSH PRIVILEGES;
3.2 方法二:使用 docker exec 直接执行命令
# 单行命令修改密码
docker exec mysql-container mysql -u root -p原密码 -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';"
3.3 忘记密码时重置(需要重启容器)
-
停止容器
docker stop mysql-container -
以跳过权限验证方式启动
docker run -d \ --name mysql-temp \ -v /usr/local/src/mysql/data:/var/lib/mysql \ -v /usr/local/src/mysql/conf/my.cnf:/etc/mysql/my.cnf \ -v /usr/local/src/mysql/logs:/var/log/mysql \ -e MYSQL_ROOT_PASSWORD=temp \ mysql:8.0 \ --skip-grant-tables -
进入临时容器重置密码
# 进入临时容器 docker exec -it mysql-temp mysql # 首先刷新权限,退出 skip-grant-tables 模式 FLUSH PRIVILEGES; # 修改密码 ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码'; # 再次刷新权限 FLUSH PRIVILEGES; EXIT; -
重启原容器
# 停止临时容器 docker stop mysql-temp docker rm mysql-temp # 正常启动原容器 docker start mysql-container
更多推荐
所有评论(0)