xiaoming728

xiaoming728

Docker 部署 MariaDB 指南

3
2025-09-18
Docker 部署 MariaDB 指南

本文档基于常见的 Docker 部署实践(拉取镜像 -> 运行一次获取配置 -> 挂载配置与数据目录)并扩展为适用于生产环境的 MariaDB 部署与调优建议。

参考文章:Docker 环境安装 Mysql。


目录

  1. 目标与适用场景

  2. 前提条件

  3. 拉取镜像

  4. 初次运行(生成默认配置 & 初始化数据目录)

  5. 拷贝并自定义 my.cnf

  6. 使用 Docker Run 持久化部署(数据与配置卷)

  7. 推荐的 docker-compose.yml 示例

  8. 性能与大表(千万/亿级)调优建议

  9. 备份 / 恢复方案

  10. 安全性与网络配置

  11. 监控与日志

  12. 常见问题与排查要点


1. 目标与适用场景

本文档适用于希望用 Docker 快速部署 MariaDB 的开发/测试及小到中型生产环境。重点考虑:

  • 数据目录持久化

  • 可定制配置(字符集、innodb 调优)

  • 针对单表大数据量(千万/亿行)的查询性能优化建议

若需要线性扩展或分布式能力(例如 sharding / HTAP),请考虑 TiDB / Vitess 等分布式方案。

MySQL 版本

MariaDB 对应大致版本

说明

MySQL 5.5

MariaDB 5.5

基本兼容,社区广泛使用

MySQL 5.6

MariaDB 10.0

功能增强,InnoDB 改进

MySQL 5.7

MariaDB 10.2

JSON 支持、虚拟列等

MySQL 8.0

MariaDB 10.3~10.11

MariaDB 10.3+ 引入窗口函数、CTE、JSON 函数等,功能与 MySQL 8.0 接近,但不是完全一致

2. 前提条件

  • 已安装 Docker Engine(建议 20.x+)和 docker-compose(v2+)

  • 主机有稳定磁盘(SSD 推荐)和足够内存(建议至少 8GB)

  • 对 MariaDB 基本配置(my.cnf)和 SQL 执行计划(EXPLAIN)有基本认识

3. 拉取镜像

以 MariaDB 官方镜像为例:

# 列出可用镜像
docker search mariadb

# 拉取指定版本(示例:10.11)
docker pull mariadb:10.11

选择固定版本以保证可重复部署与回滚能力。

4. 初次运行(生成默认配置 & 初始化数据目录)

建议第一步先用临时容器初始化数据目录并导出默认配置作为模版:

docker run --name mariadb-temp -e MYSQL_ROOT_PASSWORD='StrongRootPass123!' -d mariadb:10.11

# 等待容器初始化数据库(查看日志)
docker logs -f mariadb-temp

# 将容器内的 /etc/mysql 或 /etc/mysql/mariadb.conf.d 拷贝到主机
mkdir -p /opt/docker/mariadb/{data,conf}
docker cp mariadb-temp:/etc/mysql /opt/docker/mariadb/conf

# 停止并删除临时容器
docker stop mariadb-temp && docker rm mariadb-temp

# 将容器内的数据目录拷贝到宿主机(如果已有数据)
# docker cp mariadb-temp:/var/lib/mysql /opt/docker/mariadb/data

目的:获取官方默认配置,便于以后在主机上编辑 my.cnf 并通过挂载生效。

5. 拷贝并自定义 my.cnf

把刚才拷贝出的配置目录下的 my.cnf(或 mariadb.conf.d 下文件)做为基础,调整为适合大表与查询密集场景的配置。下面给出推荐项(示例,仅供参考,请结合实际硬件调整):

[mysqld]
user=mysql
bind-address=0.0.0.0
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
skip-name-resolve = 1

# InnoDB
innodb_buffer_pool_size = 6G         # 根据内存分配,通常 = 60%-80% 可用内存
innodb_buffer_pool_instances = 4
innodb_file_per_table = 1
innodb_log_file_size = 1G
innodb_flush_log_at_trx_commit = 2  # 权衡性能与持久性
innodb_io_capacity = 2000
innodb_io_capacity_max = 4000

# 临时表/排序/并发
tmp_table_size = 256M
max_heap_table_size = 256M
sort_buffer_size = 4M
join_buffer_size = 8M

# 连接
max_connections = 500
table_open_cache = 4000
open_files_limit = 65535

# 日志与慢查询
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_error = /var/log/mysql/error.log

# 其他
query_cache_type = 0
query_cache_size = 0

说明

  • innodb_buffer_pool_size 对查询性能决定性影响最大;单表很大时尽量将热点数据放到 buffer pool。

  • innodb_file_per_table=1 便于表级别管理与压缩。

  • innodb_flush_log_at_trx_commit=2 可以显著提升写性能,但在断电时可能会丢失最后一秒的数据(权衡可接受时使用)。

6. 使用 Docker Run 持久化部署(数据与配置卷)

下面给出一个生产可用的 docker run 示例,包含主机目录挂载与重启策略:

docker run -d \
  --name mariadb \
  -p 3306:3306 \
  -v /opt/docker/mariadb/data:/var/lib/mysql \
  -v /opt/docker/mariadb/conf:/etc/mysql \
  -v /opt/docker/mariadb/logs:/var/log/mysql \
  -e MYSQL_ROOT_PASSWORD='StrongRootPass123!' \
  -e TZ='Asia/Shanghai' \
  --restart=always \
  mariadb:10.11 \
  --character-set-server=utf8mb4 \
  --collation-server=utf8mb4_general_ci

注意:第一次使用宿主机空目录作为 /var/lib/mysql 时,容器会自动初始化数据;若之前有残留数据请确保权限(UID/GID)一致。

7. 推荐的 docker-compose.yml 示例

生产或多容器场景建议使用 docker-compose(便于扩展、备份/恢复):

version: '3.8'
services:
  mariadb:
    image: mariadb:10.11
    container_name: mariadb
    ports:
      - "3306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=StrongRootPass123!
      - TZ=Asia/Shanghai
    volumes:
      - /opt/docker/mariadb/data:/var/lib/mysql
      - /opt/docker/mariadb/conf:/etc/mysql
      - /opt/docker/mariadb/logs:/var/log/mysql
    restart: always
    command: --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 8G

8. 性能与大表(千万/亿级)调优建议

针对单表很大、以查询为主的场景,除了上面的 my.cnf 调整,还应考虑如下策略:

8.1 索引策略

  • 合理建索引:覆盖索引优先,避免全表扫描。使用联合索引时注意索引前缀原则(leftmost)。

  • 避免冗余索引:过多索引会影响写入和占用空间。定期审查索引使用情况(EXPLAINperformance_schema)。

  • 分区(Partitioning):对历史数据或按时间范围查询频繁的表使用 RANGE 或 LIST 分区,减小单次扫描数据量。

8.2 表设计

  • 垂直拆表/水平拆分:当单表列非常多时考虑垂直拆表;当单表行数影响性能时考虑水平拆分(sharding)。

  • 归档冷数据:将不常访问的历史数据迁移到归档库或冷存储(例如单独实例或对象存储 + MyRocks)。

8.3 查询优化

  • EXPLAIN 分析慢查询,避免 SELECT *、过多子查询和不走索引的 JOIN

  • 对大范围 ORDER BYGROUP BY 使用合适索引或预聚合表。

  • 利用批量分页(WHERE id > last_id LIMIT N)替代 OFFSET分页。

8.4 硬件与系统参数

  • SSD(NVMe 更佳)可显著提升 IO 性能。

  • 提高系统 vm.swappiness=1,避免频繁 swap。

  • 为 MariaDB 容器预留足够内存与 CPU,避免与 host 上其他容器争抢资源。

8.5 使用查询缓存 / 缓存层

  • MariaDB 的 query cache 在高并发写场景中并不推荐启用(容易锁竞争)。推荐使用 Redis / Varnish 等外部缓存层缓存热点数据或结果。

9. 备份 / 恢复方案

9.1 逻辑备份(mysqldump)

docker exec -i mariadb mysqldump -u root -p'password' --single-transaction --routines --events --databases mydb > mydb.sql

9.2 物理备份(xtrabackup / mariabackup)

  • 使用 Percona XtraBackup 或 MariaDB 官方的 mariabackup 做热备份,适合大数据量快速恢复。

  • 示例(容器内运行 mariabackup):

# 在宿主机安装 mariabackup 或将备份工具打包到容器
docker exec mariadb mariabackup --backup --target-dir=/backupdir --user=root --password='password'

9.3 备份存储与策略

  • 备份文件建议上传到对象存储(S3/MinIO)并设置生命周期策略。

  • 建议保留:每日备份 7 天、周备份 4 周、月备份 12 个月。

10. 安全性与网络配置

  • 不要把数据库端口暴露到公网,使用私有网络或 VPN。若必须暴露,请用防火墙(安全组)限制访问来源。

  • 强制使用强密码并关闭匿名账户。

  • 定期更新镜像并修补安全漏洞。

  • 启用 TLS 加密(--ssl-ca--ssl-cert--ssl-key)以保护传输层数据。

11. 监控与日志

  • 建议接入 Prometheus + Grafana 或使用 Percona Monitoring and Management(PMM)来监控:

    • QPS / TPS、慢查询数、Innodb Buffer Pool 命中率、磁盘 IO、连接数等。

  • 打开慢查询日志并定期分析(pt-query-digest)。

12. 常见问题与排查要点

  • 容器无法启动:检查 /var/lib/mysql 目录权限(UID/GID)、日志文件(/var/log/mysql/error.log)。

  • 性能下降:排查慢查询、Buffer Pool 命中率、IO 阻塞、swap 使用。

  • 数据目录损坏:从最近备份恢复或用 --innodb_force_recovery 参数尝试导出数据(谨慎使用)。


附录:快速操作命令汇总

# 查看容器日志
docker logs -f mariadb

# 进入容器
docker exec -it mariadb bash

# 备份示例
docker exec -i mariadb mysqldump -u root -p'password' --single-transaction mydb > mydb.sql

# 恢复示例
cat mydb.sql | docker exec -i mariadb mysql -u root -p'password'