一、搭建单节点服务

使用Docker来下载并启动MySQL,主要步骤包括:拉取MySQL镜像、运行容器、以及一些常见的配置(如设置密码、映射端口、挂载数据卷等)。

  1. 拉取MySQL官方镜像
  2. 创建本地数据存储目录和自定义配置文件目录(用于持久化和配置)
  3. 创建自定义配置文件(可选,但建议)
  4. 运行容器,并设置环境变量、端口映射、数据卷等
  5. 验证连接

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容器。以下是一些常用参数:

  1. -p:端口映射,后面紧接着的3306:3306是要进行映射的端口,冒号左边的3306是宿主机的端口号,冒号右边的3306是mysql容器的端口,-p的作用是将mysql容器的3306端口映射到宿主机的3306端口,这样就可以通过宿主机的ip+映射到宿主机的3306端口就能连接上启动的mysql容器。
  2. -e:后面紧接着的MYSQL_ROOT_PASSWORD=root,是指定mysql容器的root用户登陆密码。
  3. -d:表示以守护进程的方式启动服务,服务在后台运行。
  4. --name:指定启动后的容器名。
  5. -v:持久化数据,将容器的数据交给宿主机管理,主要也是为了同步数据,防止容器被删除后数据找不到的问题。/root/data 这是宿主机的数据存放路径;/var/lib/mysql 这是mysql容器存放数据的地方。
  6. --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来部署一个主节点和两个从节点。以下是步骤:

  1. 创建目录结构
  2. 编写Docker Compose文件
  3. 配置MySQL主从节点的配置文件
  4. 启动和配置主从复制

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 方法一:进入容器修改

  1. 进入 MySQL 容器

    # 直接连接 MySQL
    docker exec -it mysql-container mysql -u root -p
    # 输入当前密码
    
  2. 修改密码(MySQL 8.0+)

    -- 登录后执行
    ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';
    FLUSH PRIVILEGES;
    
    -- 如果是远程访问用户
    ALTER USER 'root'@'%' IDENTIFIED BY '新密码';
    FLUSH PRIVILEGES;
    
  3. 修改密码(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 忘记密码时重置(需要重启容器)

  1. 停止容器

    docker stop mysql-container
    
  2. 以跳过权限验证方式启动

    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
    
  3. 进入临时容器重置密码

    # 进入临时容器
    docker exec -it mysql-temp mysql
    
    # 首先刷新权限,退出 skip-grant-tables 模式
    FLUSH PRIVILEGES;
    # 修改密码
    ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';
    # 再次刷新权限
    FLUSH PRIVILEGES;
    EXIT;
    
  4. 重启原容器

    # 停止临时容器
    docker stop mysql-temp
    docker rm mysql-temp
    
    # 正常启动原容器
    docker start mysql-container
    

更多推荐