跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
SQL

Docker 镜像构建优化与 MySQL 主从集群容器化部署

Docker 镜像构建优化涉及多阶段构建、缓存利用及 .dockerignore 配置,CMD 与 ENTRYPOINT 组合使用可提升灵活性。MySQL 主从同步包含全同步、异步、半同步等模式,通过 Docker Compose 可实现一主二从集群的快速部署与数据一致性保障。

性能调优发布于 2026/3/15更新于 2026/9/961 浏览
Docker 镜像构建优化与 MySQL 主从集群容器化部署

Dockerfile 基础与 C++ 镜像编写

对应 Dockerfile:

FROM centos:7
ENV VERSION 1.0
RUN sed -i.bak \
-e 's|^mirrorlist=|#mirrorlist=|g' \
-e 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.ustc.edu.cn/centos-vault/centos|g' \
/etc/yum.repos.d/CentOS-Base.repo
WORKDIR /src
COPY demo.c .
RUN yum makecache && yum install -y gcc
RUN gcc demo.c -o demo && \
rm -f demo.c && \
yum remove -y gcc
CMD ["/src/demo"]

执行构建命令:

docker build -t my-cpp-image .

等待镜像制作完成并运行。

CMD 与 ENTRYPOINT 的正确使用

基本功能

ENTRYPOINT 和 CMD 均用于定义容器启动时执行的命令。若镜像未设置这两个指令,运行时会报错。

覆盖行为

Dockerfile 中后写的指令会覆盖同类型的前置指令。用户运行容器时可通过命令行参数覆盖 Dockerfile 中的 CMD,但 ENTRYPOINT 需用 --entrypoint 强制覆盖。

模式区别

  • Shell 模式(如 CMD echo "hello"):命令通过 /bin/sh -c 启动,导致主进程 PID 非 1,无法正常接收信号(如优雅终止容器)。
  • Exec 模式(如 CMD ["echo", "hello"]):直接运行命令,PID 为 1,支持信号转发,强烈推荐使用。

组合使用

ENTRYPOINT 定义固定执行命令,CMD 提供默认参数。最终命令为拼接形式:<ENTRYPOINT> <CMD>,运行时可覆盖 CMD 参数。

应用建议

  • 若希望容器始终执行固定程序,使用 ENTRYPOINT;
  • 若需保留参数灵活性,可组合使用 ENTRYPOINT(Exec 模式)+ CMD(提供默认参数)。

多次指令覆盖测试

如果 Dockerfile 出现两次 CMD 或 ENTRYPOINT,后面的指令会覆盖前面的指令。手动输入参数也会覆盖 CMD。

Exec 与 Shell 模式对比

Shell 模式下启动后容器主进程是 /bin/sh。Exec 模式下主进程是对应命令,PID 为 1。

CMD 配合 ENTRYPOINT 使用

CMD 做参数,ENTRYPOINT 做命令,实时修改 CMD,实现解耦性;两者相互配合,使得操作更加灵活。

使用 .dockerignore 测试

Docker 是 C/S 架构。构建镜像时,客户端会把当前目录所有文件打包发送给服务端,这个包叫做 build context。用 .dockerignore 文件可以忽略不需要的文件(如日志、缓存),让镜像更小更安全。

构建命令:

docker build -t image-name .

一句话总结:build context 是客户端发给服务端的'材料包',用 .dockerignore 过滤掉多余文件。

测试显示,忽略 txt 结尾的文件后,启动后发现只有指定文件,无 txt 结尾的文件,说明 ignore 成功。

基于 Dockerfile 的多级构建

Docker 镜像构建的三种方式:

  1. 全部塞一起(一个镜像干所有事)
    • 问题:Dockerfile 又长又难维护,镜像超大,部署慢。
  2. 分多个步骤(用多个 Dockerfile+ 脚本)
    • 镜像变小了,但要写多个文件 + 脚本,太麻烦。
  3. 多阶段构建(一个 Dockerfile 搞定)
    • 只需一个文件,自动把编译和运行分开,最终镜像只留需要的东西,又小又干净!

结论:直接用第三种(多阶段构建),高效又省事!

演示:

一个 Dockerfile,先编译 C 程序,再把生成的可执行文件拷贝到小镜像里运行。

之前是默认一个 centos 的镜像同时编译运行等操作,下载了很多相关包文件没有清理干净。

下面采取多级构建:

最后采取的是一个非常小的镜像源作为最终镜像(真正 build 的最后镜像以最后一个为主,其他中间镜像都会被清除);因此对应只需要对应程序的镜像就可以采取多级构建,把对应的 exe 只需要放在一个能跑程序的小镜像里即可(如 busybox)。

总结:

多阶段构建可以很好的解决镜像的层次多,体积大,部署时间长、维护性低等问题;我们编译使用的软件,都没有打到我们的运行态的软件里面,所以可以变得更小。

合理使用缓存

  1. 顺序执行与缓存复用
    Docker 会按 Dockerfile 中的指令顺序构建,每步都会优先查找并使用缓存中已有的镜像层,避免重复工作。
  2. 修改即失效原则
    Dockerfile 中每条指令都会生成一个镜像层。一旦某一层的内容被修改,它之后的所有层缓存都会失效,需要重新构建。
  3. 可手动禁用缓存
    可以通过 docker build --no-cache=true 命令选项来完全禁用缓存,但合理利用缓存能极大提升构建效率。

例子:

这里的镜像只在 COPY 开始到以上有改变,因此再次构建镜像的时候下面的镜像就可以复用。

比如在频繁更改代码来编译程序:

这样更改就可以减少对应安装软件的频繁安装,直接复用上面的层。

演示:

还是以之前的 c++ 镜像制作为例:

这里发现很多都复用了之前构建的镜像的内容。

下面因为代码频繁更改,可以把对应的安装过程搞到上面,复用下对应缓存:

这里发现改了顺序时间更长了;因为之前的那一次完全复用缓存。

然后这一次从跑到 yum 这里发现上面的层就不同了;因此地下的复用(看到的就是过程的 cached 效果);然后下面重新构建。

下面测试下更改源代码效果:

可以发现现在比第一次快;可以看出先跑到更改层;然后发现之前的层都没动,直接复用之前的;然后更改层上面的重新构建(这里其实对应的重新安装软件也是比较耗时间的)。

总结:

因此对应镜像构建的过程中;尽量让它不变化的放一起,变化的放一起都在上层;让它尽量能复用之前的缓存层;加快构建镜像的速度。

MySQL 主从同步

docker compose build 使用

在 docker-compose.yml 里写 build,就能直接编译镜像,不用手动敲命令。

  • 用途:一键把代码打包成镜像
  • 用法:指定 Dockerfile 所在目录
  • 好处:省事、自动化

两种方式进行 docker-compose.yml 使用:

成功位于不同位置的 dockerfile 进行构建镜像,但是不启动。

MySQL 主从同步

主从同步概览
  1. 核心机制
    数据从一个 MySQL 主节点自动复制到一个或多个从节点,默认采用异步方式。
  2. 主要目的(三大好处)
    • 读写分离:主库处理写操作,从库处理读操作,提升整体性能和可用性。
    • 数据备份:从库作为主库的实时数据备份,防止主库故障导致数据丢失。
    • 高可用 (HA):主库出现故障时,可以快速切换到从库继续提供服务。
  3. 灵活配置
    从库可以复制主库的全部数据,也可以只复制特定的数据库或表。
主从同步大致流程
  1. 主库记录日志
    主库(Master)收到写操作(增、删、改)后,先将数据更新,同时将变更操作记录到二进制日志(binlog) 中。
  2. 主库发送日志
    主库为每个连接的从库(Slave)创建一个 binlog dump 线程。该线程负责读取主库的 binlog,并将其发送给从库的 I/O 线程。
  3. 从库接收日志
    从库的 I/O 线程 接收到 binlog 内容后,将其写入到本地的中继日志(relay log) 中。
  4. 从库应用日志
    从库的 SQL 线程 读取本地的 relay log,解析并执行其中的 SQL 事件,从而在从库上重做数据变更,最终实现与主库的数据同步。

一句话总结:主库将写操作记入 binlog,从库的 IO 线程取、SQL 线程执行,最终实现数据同步。

那什么是 binlog?

MySQL 的 binlog 是记录数据库写操作(增删改)的日志,主要用于数据同步和恢复。它有三种记录模式:

  1. Statement:记 SQL 语句(日志小,但可能出错,比如使用了 now() 主从同步就可能会出问题)
  2. Row:记每行数据变化(绝对准,但日志大)
  3. Mixed:混合模式(默认推荐,智能选择前两种,兼顾效率和准确性)
主从同步五大方式
全同步方式
  1. 做法:主库干完活,必须等所有从库也干完,才能告诉你成功了。
  2. 好处:主从数据100% 一致。
  3. 坏处:超级慢(被最慢的从库拖垮(多从的时候)),且一个从库挂了,主库也卡住。

一句话:用速度和可用性换绝对的数据一致。

异步方式
  1. 默认模式:MySQL 主从复制默认采用的就是异步方式。
  2. 主库优先:主库在自己成功执行完事务后,会立即向客户端返回成功响应,而不会等待从库的同步结果。
  3. 弱一致性:主库不保证从库是否收到日志、是否已完成数据处理。这会导致主从数据存在短暂延迟,无法保证强一致性。

一句话:主库追求自身处理速度和响应能力,牺牲了数据的强一致性(比如主在同步过程,自己写了但是正在写从的时候挂了)。

半同步复制
  1. 核心机制
    主库(Master)在自己完成事务后,必须等待至少一个从库(Slave)确认收到数据日志(binlog),才能向客户端返回成功响应。
  2. 最大优点(与异步复制比)
    数据一致性更强
    。因为确保了至少一个从库有最新数据,降低了主库宕机导致数据完全丢失的风险。
  3. 主要缺点(与异步复制比)
    • 性能较低:因为主库需要等待从库的确认,增加了事务处理的延迟。
    • 存在幻读风险:如果主库在等待确认后、但在返回响应前宕机,客户端可能认为事务已成功,但实际上从库可能还未完全应用该数据。

一句话:半同步是异步和全同步的折衷方案,用部分性能换取比异步更好的一致性,但不如全同步可靠。

增强半同步复制
  1. 主库干活:收到请求,先记日志(binlog),发给从库(相当于半同步只是对应的主库存储在从库完成后进行的,数据一致性增强)。
  2. 主库等待:必须等至少一个从库回复'收到',才能写入主库;告诉用户'成功了'。
  3. 从库备份:从库收日志、存日志(relaylog)、执行日志,然后通知主库。

好处:数据更安全(主从一致),解决了'幻读'问题。
代价:比纯异步慢一点(因为要等从库回信)。

一句话:主库等一个从库确认后才算成功,保证了数据不丢不错。

组复制
  1. 统一共识:所有写操作必须先发送到中央的 'Consensus' (共识模块) 进行协调和冲突检测,确保所有节点认可该操作的有效性和顺序。这是实现多主复制的核心(分发给所有主节点;这样防止多主挂了;只要有一个主从在就保证数据一致)。
  2. 并行处理:
    • 发起节点 (Master 1):执行事务 -> 提交共识 -> 记录 binlog -> 提交。
    • 同步节点 (Master 2/3):从共识层获取操作 -> 写入 relay log -> 应用操作 -> 记录自身 binlog -> 提交。
  3. 最终一致:通过此流程,所有节点最终都会以相同的顺序应用所有写操作,从而保证整个集群的数据最终一致性。

一句话:所有写操作必须经过共识层审批,确保所有节点按相同顺序执行,最终实现多主数据同步。

MySQL 主从形式
  1. 一主多从

一主一从
一个主库配一个从库,最基本、最常用的备份与读写分离架构。

一个主库配多个从库,显著提高系统的读性能,是扩展读能力的标准做法。

  1. 多主一从

多个主库的数据同步到一个从库,用于将多个数据库备份到一台高性能存储服务器。

  1. 双主复制

两个主库互为主从,任何一方的修改都会同步到另一方,实现双向同步。

  1. 级联复制

从库再作为其他从库的主库,减轻主库压力,避免主库连接过多而性能下降(比如对应分析数据库,时长进行读操作,不追求性能,此时就可以把它作为以从为主的从库)。

所有形式都是为了实现数据备份、读写分离、提升性能和可用性。

一主二从 MySQL 集群搭建

下面基于一下流程进行搭建:

  1. 主节点 Dockerfile-初始化脚本 注:这里主默认初始化故无需脚本了
  2. 2 个从节点 Dockerfile-初始化脚本
  3. 编写 docker-compose.yml
  4. 构建镜像
  5. 启动服务,检查服务和同步状态
  6. 创建库表写入数据,检查是否同步

首先看下对应目录:

构建主库的 dockerfile(默认初始化,故无需 copy 对应 sql 脚本):

在这里插入图片描述

俩从库的 dockerfile(需要手动同步):

在这里插入图片描述

对应的从的初始化 sql:

在这里插入图片描述

对应的总的 docker-compose 文件:

services:
  mysql-master:
    build:
      context: ./
      dockerfile: ./master/Dockerfile-master
    image: mysqlmaster:v1.0
    restart: always
    container_name: mysql-master
    volumes:
      - ./master/var/lib/mysql:/var/lib/mysql
    ports:
      - 9306:3306
    environment:
      MYSQL_ROOT_PASSWORD: root
      privileged: true
    command: ['--server-id=1','--log-bin=mysql-bin','--binlog-ignore-db=mysql','--binlog_cache_size=256M','--binlog_format=mixed','--lower_case_table_names=1','--character-set-server=utf8','--collation-server=utf8_general_ci']
  mysql-slave:
    build:
      context: ./
      dockerfile: ./slave/Dockerfile-slave
    image: mysqlslave:v1.0
    restart: always
    container_name: mysql-slave
    volumes:
      - ./slave/var/lib/mysql:/var/lib/mysql
    ports:
      - 9307:3306
    environment:
      MYSQL_ROOT_PASSWORD: root
      privileged: true
    command: ['--server-id=2','--relay-log=slave-relay-bin','--lower_case_table_names=1','--character-set-server=utf8','--collation-server=utf8_general_ci']
    depends_on:
      - mysql-master
  mysql-slave2:
    build:
      context: ./
      dockerfile: ./slave2/Dockerfile-slave2
    image: mysqlslave2:v1.0
    restart: always
    container_name: mysql-slave2
    volumes:
      - ./slave2/var/lib/mysql:/var/lib/mysql
    ports:
      - 9308:3306
    environment:
      MYSQL_ROOT_PASSWORD: root
      privileged: true
    command: ['--server-id=3','--relay-log=slave2-relay-bin','--lower_case_table_names=1','--character-set-server=utf8','--collation-server=utf8_general_ci']
    depends_on:
      - mysql-master

这里对应的 master 的密码用户都是 root;然后在两个从的初始化 sql 中都设置了用户名和密码都是 root。

下面熟悉了之前的 docker compose 配置参数后;这里就值介绍对应 command 了:

主节点 (mysql-master) 参数

  1. --server-id=1
    • 设置 MySQL 实例的唯一 ID(主从集群中每个节点必须不同)。
  2. --log-bin=mysql-bin
    • 启用二进制日志(binlog),记录所有数据更改,用于主从同步。
  3. --binlog-ignore-db=mysql
    • 忽略系统库 mysql 的变更,避免不必要的同步。
  4. --binlog_format=mixed
    • 设置 binlog 格式为混合模式(兼顾效率和可靠性)。

从节点 (mysql-slave, mysql-slave2) 参数

  1. --server-id=2 / --server-id=3
    • 设置从库的唯一 ID(不能与主库或其他从库重复)。
  2. --relay-log=slave-relay-bin
    • 启用中继日志(relay log),暂存从主库接收的 binlog 数据。
  3. --lower_case_table_names=1
    • 表名不区分大小写(避免主从同步因大小写问题失败)。
  4. --character-set-server=utf8
    • 设置默认字符集为 UTF-8,支持中文等字符。
  5. --collation-server=utf8_general_ci
    • 设置默认排序规则,确保字符串比较一致。

下面同规格 docker compose 进行镜像生成:

等待很长时间。

成功构建。

成功构建好容器。

进入主从 mysql 中。

通过下面的指令进行主从查看:

SHOW MASTER STATUS\G
SHOW SLAVE STATUS\G

下面进行插入数据看是否同步:

主库插入:

mysql> create database db1;
Query OK, 1 row affected (0.00 sec)
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| db1                |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set(0.00 sec)
mysql> use db1;
Database changed
mysql> insert into t1 values("zs",1),("lm",2);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from t1;
+------+------+|
| name | age  ||
+------+------+|
| zs   | 1    ||
| lm   | 2    ||
+------+------+|
2 rows in set(0.00 sec)
mysql>

从库查看:

发现同步成功。

至此可以看到我们搭建的 mysql 集群已经能够正常进行工作。

总结

本篇通过 Dockerfile 多阶段构建大幅精简镜像体积,利用缓存机制提升构建效率;深入解析 MySQL 主从复制五大模式,并完成一主二从集群实战。掌握 ENTRYPOINT+CMD 组合、.dockerignore 过滤等技巧,实现容器化部署的高性能与高可用。

目录

  1. Dockerfile 基础与 C++ 镜像编写
  2. CMD 与 ENTRYPOINT 的正确使用
  3. 基本功能
  4. 覆盖行为
  5. 模式区别
  6. 组合使用
  7. 应用建议
  8. 多次指令覆盖测试
  9. Exec 与 Shell 模式对比
  10. CMD 配合 ENTRYPOINT 使用
  11. 使用 .dockerignore 测试
  12. 基于 Dockerfile 的多级构建
  13. 合理使用缓存
  14. MySQL 主从同步
  15. docker compose build 使用
  16. MySQL 主从同步
  17. 主从同步概览
  18. 主从同步大致流程
  19. 主从同步五大方式
  20. 全同步方式
  21. 异步方式
  22. 半同步复制
  23. 增强半同步复制
  24. 组复制
  25. MySQL 主从形式
  26. 一主二从 MySQL 集群搭建
  27. 总结

更多推荐文章

查看全部
  • 几款支持万方平台的 AIGC 降重工具实测对比
  • AI Agent 框架选型指南:OpenClaw、LangChain、AutoGPT、CrewAI 深度对比
  • 从推荐算法转行大模型推理工程:行业趋势与技术路径
  • MySQL 事务隔离级别与一致性详解
  • Linux 线程控制详解:从 pthread 到 C++11
  • Spring AI 引入 Agent Skills:Java 开发者构建智能应用新范式
  • Google Gemini 3 免费使用渠道与接入指南
  • Flutter eip55 库在 OpenHarmony 上的以太坊地址校验适配
  • C/C++ 线程池详解
  • Go 与 C++ 对比:性能、并发与生态差异分析
  • DeepSeek 使用指南与高阶提示词技巧
  • 【Microi吾码】 发现Microi吾码:低代码世界的超级英雄 ‍
  • Python tkinter 核心组件 IntVar() 用法详解
  • JDK 1.8 在 Windows 系统下的安装与配置教程
  • 深度学习反向传播原理:链式法则与责任分配
  • 浏览器里用微信网页版?这个开源插件帮你绕开限制
  • FPGA低延迟库在高频交易中的实战优化与避坑指南
  • Neo4j Desktop 2.0 安装教程:自定义安装路径
  • JavaScript 中 window.location 对象详解与实战
  • Copilot 实战:如何高效完成 1.5 万行 Python 项目(含提示词模板)

相关免费在线工具

  • SQL 美化和格式化

    在线格式化和美化您的 SQL 查询(它支持各种 SQL 方言)。 在线工具,SQL 美化和格式化在线工具,online

  • SQL转CSV/JSON/XML

    解析 INSERT 等受限 SQL,导出为 CSV、JSON、XML、YAML、HTML 表格(见页内语法说明)。 在线工具,SQL转CSV/JSON/XML在线工具,online

  • CSV 工具包

    CSV 与 JSON/XML/HTML/TSV/SQL 等互转,单页多 Tab。 在线工具,CSV 工具包在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online