Docker MySQL Setup

Docker MySQL 部署指南

本文介绍如何使用 Docker 和 Docker Compose 部署 MySQL 数据库服务。MySQL 是最流行的开源关系型数据库管理系统之一。

📋 前置要求

  • Docker 20.10+ 已安装
  • Docker Compose V2 已安装(推荐)或 Docker Compose V1
  • 如需使用 Docker Swarm,需要初始化 Swarm 集群
  • 如需使用 NFS,需要配置 NFS 服务器

🚀 快速部署(Docker Compose)

1. 克隆项目(如果使用项目模板)

1
2
git clone https://github.com/noahzaozao/docker-mysql.git
cd docker-mysql

2. 配置环境变量

1
2
cp .env-trunk .env
vi .env

编辑 .env 文件,设置 MySQL 配置:

1
2
3
4
MYSQL_ROOT_PASSWORD=your_strong_password_here
MYSQL_DATABASE=myapp
MYSQL_USER=appuser
MYSQL_PASSWORD=appuser_password

3. 使用 Docker Compose 部署

1
2
3
4
5
# 使用 Docker Compose V2(推荐)
docker compose up -d

# 或使用旧版
docker-compose up -d

4. 验证部署

1
2
3
4
5
# 查看容器状态
docker compose ps

# 测试 MySQL 连接
docker compose exec mysql mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT VERSION();"

🐳 Docker Swarm 部署(使用 NFS)

1. 初始化 Swarm(如果尚未初始化)

1
docker swarm init

2. 配置环境变量

1
2
cp .env-trunk .env
vi .env

配置 MySQL 和 NFS 相关参数:

1
2
3
4
5
6
7
8
MYSQL_ROOT_PASSWORD=your_strong_password_here
MYSQL_DATABASE=myapp
MYSQL_USER=appuser
MYSQL_PASSWORD=appuser_password

# NFS 配置(可选,用于数据持久化)
NFS_HOST=addr=192.168.1.100,nolock,soft,rw
NFS_PATH=:/mnt/nfs/mysql

3. 部署 Stack

1
docker stack deploy -c docker-compose.yml stack_mysql

4. 查看服务状态

1
2
docker stack services stack_mysql
docker service logs stack_mysql_mysql

📝 Docker Compose 配置示例

基础配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
version: '3.8'

services:
mysql:
image: mysql:8.0
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE:-myapp}
MYSQL_USER: ${MYSQL_USER:-appuser}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
TZ: Asia/Shanghai
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
- ./conf.d:/etc/mysql/conf.d
restart: unless-stopped
command: --default-authentication-plugin=mysql_native_password
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
interval: 30s
timeout: 10s
retries: 3

volumes:
mysql_data:

使用 NFS 存储(Docker Swarm)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
version: '3.8'

services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE:-myapp}
MYSQL_USER: ${MYSQL_USER:-appuser}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
TZ: Asia/Shanghai
ports:
- "3306:3306"
volumes:
- mysql_nfs:/var/lib/mysql
- ./conf.d:/etc/mysql/conf.d
restart: unless-stopped
command: --default-authentication-plugin=mysql_native_password
deploy:
replicas: 1
placement:
constraints:
- node.role == manager
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
networks:
- mysql_network

volumes:
mysql_nfs:
driver: local
driver_opts:
type: nfs
o: ${NFS_HOST}
device: ${NFS_PATH}

networks:
mysql_network:
driver: overlay

生产环境配置(推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
version: '3.8'

services:
mysql:
image: mysql:8.0
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE:-myapp}
MYSQL_USER: ${MYSQL_USER:-appuser}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
TZ: Asia/Shanghai
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
- ./conf.d:/etc/mysql/conf.d
- ./init:/docker-entrypoint-initdb.d
restart: unless-stopped
command: >
--default-authentication-plugin=mysql_native_password
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
--max_connections=200
--innodb_buffer_pool_size=1G
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
interval: 30s
timeout: 10s
retries: 3

volumes:
mysql_data:

🔧 常用操作

连接 MySQL

1
2
3
4
5
# 使用 Docker Compose
docker compose exec mysql mysql -uroot -p$MYSQL_ROOT_PASSWORD

# 或使用 Docker
docker exec -it mysql mysql -uroot -p

创建数据库

1
docker compose exec mysql mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "CREATE DATABASE newdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

导入 SQL 文件

1
docker compose exec -T mysql mysql -uroot -p$MYSQL_ROOT_PASSWORD myapp < backup.sql

导出数据库

1
docker compose exec mysql mysqldump -uroot -p$MYSQL_ROOT_PASSWORD myapp > backup.sql

查看日志

1
docker compose logs -f mysql

重启服务

1
docker compose restart mysql

🔐 安全配置建议

1. 使用强密码

确保 .env 文件中的密码足够复杂:

1
MYSQL_ROOT_PASSWORD=$(openssl rand -base64 32)

2. 限制网络访问

生产环境建议不暴露端口,或使用防火墙限制:

1
2
3
4
5
6
# 不暴露端口,仅内部网络访问
# ports:
# - "3306:3306"

networks:
- internal_network

3. 自定义 MySQL 配置

创建 conf.d/my.cnf

1
2
3
4
5
6
7
8
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
max_connections=200
innodb_buffer_pool_size=1G
innodb_log_file_size=256M
slow_query_log=1
long_query_time=2

4. 初始化脚本

init/ 目录下放置 .sql.sh 文件,容器首次启动时会自动执行。

📊 备份与恢复

自动备份脚本

创建 backup.sh

1
2
3
4
5
6
7
8
9
#!/bin/bash
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
CONTAINER_NAME="mysql"

docker exec $CONTAINER_NAME mysqldump -uroot -p$MYSQL_ROOT_PASSWORD --all-databases | gzip > $BACKUP_DIR/backup_$DATE.sql.gz

# 保留最近 7 天的备份
find $BACKUP_DIR -name "backup_*.sql.gz" -mtime +7 -delete

恢复备份

1
gunzip < backup_20250127_120000.sql.gz | docker exec -i mysql mysql -uroot -p$MYSQL_ROOT_PASSWORD

🐛 常见问题

1. 连接被拒绝

  • 检查密码是否正确
  • 确认容器是否正常运行:docker compose ps
  • 检查端口是否被占用:netstat -tuln | grep 3306

2. 字符编码问题

确保使用 utf8mb4 字符集:

1
ALTER DATABASE myapp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

3. 数据目录权限问题

1
sudo chown -R 999:999 /var/lib/docker/volumes/mysql_data/_data

4. NFS 挂载失败

  • 检查 NFS 服务器是否正常运行
  • 确认 NFS 路径是否正确
  • 检查防火墙设置

📚 参考资源

0%