4. MySQL 8.0 容器化部署:拉取镜像、编写 docker-compose 服务、端口映射、数据持久化(volume)、字符集设置
在支付订单系统的本地开发环境中,MySQL 作为核心关系型数据库,承担着订单表、支付流水表、账户余额表等关键数据的存储。采用 Docker 容器化部署 MySQL 8.0,可以快速搭建与生产环境一致的数据库服务,避免因操作系统差异导致的兼容性问题。本节将详细讲解从镜像拉取到完整配置的每一步操作。
4.1 拉取 MySQL 8.0 官方镜像
首先,从 Docker Hub 拉取 MySQL 8.0 的官方镜像。建议指定具体的小版本号(如 8.0.32)以确保环境可复现,避免因镜像更新导致行为变化。
# 拉取 MySQL 8.0.32 版本
docker pull mysql:8.0.32
# 验证镜像是否拉取成功
docker images | grep mysql
4.2 编写 docker-compose.yml 服务定义
使用 Docker Compose 可以统一管理 MySQL 容器的配置。以下是一个面向支付订单系统的完整 docker-compose.yml 示例,包含端口映射、数据持久化、字符集设置等关键配置。
version: '3.8'
services:
mysql-payment:
image: mysql:8.0.32
container_name: payment-mysql
restart: unless-stopped
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: Payment@2024!
MYSQL_DATABASE: payment_order
MYSQL_USER: payment_app
MYSQL_PASSWORD: App@2024!
volumes:
- mysql_data:/var/lib/mysql
- ./mysql-init:/docker-entrypoint-initdb.d
- ./mysql-config:/etc/mysql/conf.d
command: >
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
--default-authentication-plugin=mysql_native_password
--max_connections=200
--innodb_buffer_pool_size=512M
--binlog_format=ROW
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
volumes:
mysql_data:
driver: local
4.3 端口映射与网络规划
端口映射是容器化部署的基础配置。MySQL 默认监听 3306 端口,通过 ports 指令将宿主机端口映射到容器端口。在支付系统中,通常需要规划多个数据库实例(如订单库、支付库、日志库),因此端口映射需要避免冲突。
| 场景 | 宿主机端口 | 容器端口 | 说明 |
|---|---|---|---|
| 单实例开发 | 3306 | 3306 | 直接映射,简单易用 |
| 多实例开发 | 3307 | 3306 | 订单库实例 |
| 多实例开发 | 3308 | 3306 | 支付流水库实例 |
| 生产环境 | 3306 | 3306 | 通过防火墙限制访问 |
sudo lsof -i :3306 查看占用进程,或修改宿主机映射端口为 3307 等未占用端口。
4.4 数据持久化:Volume 挂载策略
容器默认存储的数据在容器删除后会丢失,这对支付系统来说是不可接受的。通过 Docker Volume 将 MySQL 数据目录挂载到宿主机,可以确保数据持久化。同时,初始化脚本和自定义配置文件的挂载也是关键环节。
- mysql_data(命名卷): 由 Docker 自动管理,存放路径为
/var/lib/docker/volumes/,适合生产环境,备份时使用docker run --rm -v mysql_data:/data alpine tar -czf backup.tar.gz /data。 - ./mysql-init(绑定挂载): 存放建表、初始化数据的 SQL 脚本,容器首次启动时自动执行。支付系统可在此创建订单表、支付流水表、账户表等核心表结构。
- ./mysql-config(绑定挂载): 存放自定义的 my.cnf 配置文件,用于覆盖默认字符集、连接数、缓冲池大小等参数。
4.5 字符集设置:utf8mb4 与排序规则
支付订单系统需要存储多语言字符(如用户姓名、商品描述)以及 Emoji 表情(如支付成功通知中的图标),因此必须使用 utf8mb4 字符集。MySQL 8.0 默认字符集已改为 utf8mb4,但显式配置可以确保一致性。
在 docker-compose.yml 的 command 指令中,通过 --character-set-server=utf8mb4 和 --collation-server=utf8mb4_unicode_ci 设置服务端字符集。此外,还可以通过自定义配置文件进行更精细的控制。
# 创建自定义配置文件 ./mysql-config/custom.cnf
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init-connect = 'SET NAMES utf8mb4'
# 支付系统推荐参数
innodb_default_row_format = DYNAMIC
skip-character-set-client-handshake
| 字符集配置项 | 推荐值 | 说明 |
|---|---|---|
| character-set-server | utf8mb4 | 服务端默认字符集,支持 4 字节 UTF-8 |
| collation-server | utf8mb4_unicode_ci | 基于 Unicode 的排序规则,支持多语言排序 |
| init-connect | SET NAMES utf8mb4 | 客户端连接时自动设置字符集 |
| innodb_default_row_format | DYNAMIC | 支持 utf8mb4 的变长列存储,避免索引过长 |
CREATE DATABASE payment_order CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;。同时,应用层的 JDBC 连接字符串也要添加 characterEncoding=utf8mb4 参数。
4.6 启动与验证
完成 docker-compose.yml 编写后,通过以下命令启动 MySQL 容器并验证配置是否生效。
# 启动容器(后台运行)
docker-compose up -d
# 查看容器运行状态
docker-compose ps
# 进入容器内部验证字符集
docker exec -it payment-mysql mysql -uroot -p'Payment@2024!'
# 在 MySQL 命令行中执行
mysql> SHOW VARIABLES LIKE 'character_set_server';
mysql> SHOW VARIABLES LIKE 'collation_server';
mysql> SHOW VARIABLES LIKE 'character_set_database';
# 验证数据持久化:停止并删除容器后,数据是否保留
docker-compose down
docker-compose up -d
# 检查之前创建的数据库和表是否仍然存在
docker inspect payment-mysql --format='{{json .State.Health}}' 查看容器健康状态。在支付系统中,建议在应用启动前等待 MySQL 健康检查通过,避免连接失败。
4.7 支付系统初始化脚本示例
在 ./mysql-init 目录下创建初始化脚本,容器首次启动时会自动执行。以下是一个支付订单系统的建表示例。
-- ./mysql-init/01_create_tables.sql
USE payment_order;
-- 订单主表
CREATE TABLE IF NOT EXISTS t_order (
order_id BIGINT AUTO_INCREMENT PRIMARY KEY,
order_no VARCHAR(64) NOT NULL COMMENT '订单号',
user_id BIGINT NOT NULL COMMENT '用户ID',
total_amount DECIMAL(18,2) NOT NULL COMMENT '订单总金额',
status TINYINT NOT NULL DEFAULT 0 COMMENT '订单状态:0-待支付 1-已支付 2-已取消',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_order_no (order_no),
INDEX idx_user_id (user_id),
INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单主表';
-- 支付流水表
CREATE TABLE IF NOT EXISTS t_payment_transaction (
trans_id BIGINT AUTO_INCREMENT PRIMARY KEY,
order_no VARCHAR(64) NOT NULL COMMENT '关联订单号',
trans_no VARCHAR(64) NOT NULL COMMENT '支付流水号',
pay_amount DECIMAL(18,2) NOT NULL COMMENT '支付金额',
pay_channel VARCHAR(32) NOT NULL COMMENT '支付渠道:WECHAT- ALIPAY-支付宝',
status TINYINT NOT NULL DEFAULT 0 COMMENT '流水状态:0-处理中 1-成功 2-失败',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_trans_no (trans_no),
INDEX idx_order_no (order_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='支付流水表';
通过以上步骤,一个面向支付订单系统的 MySQL 8.0 容器化环境就搭建完成了。该环境具备数据持久化、正确的字符集配置、以及自动初始化的表结构,为后续的本地调试和功能开发提供了稳定可靠的数据库基础。