
简介面向需要快速部署数据库迁移工具DBmotion的开发与运维人员这份下载包提供了开箱即用的完整容器化运行方案。资源共11个文件其中10个gzip格式的镜像压缩包用于离线导入另1个为可执行的docker-compose.yaml编排文件整体738.34MB。镜像包涵盖数据库、数据迁移服务、代理网关、监控告警Prometheus/Grafana/Alertmanager及Web管理界面等组件编排文件则预先定义了各容器的镜像来源、端口映射、卷挂载、网络与依赖关系可确保各服务按正确顺序启动并互相连通执行一条docker-compose up命令即可拉起整套环境。已有46人学习/下载。相比自行搜索镜像和手动配置这套集合省去大量调试成本适合需要快速启动DBmotion、验证迁移流程、搭建演示环境或构建内部测试环境的团队文件结构简洁镜像版本与配置相对固定也便于离线分发、私有化部署与后期扩展。1. DBmotion 到底是什么为什么一定要用容器集合DBmotion 这个名字做数据库迁移和同步的朋友应该不陌生。它定位是一套跨数据库的数据迁移/同步工具支持从 MySQL、Oracle、PostgreSQL 等常见关系型数据库把数据搬到目标库也支持 Kafka、ClickHouse 这类大数据生态组件。实际用下来最吸引人的地方是它的“全量增量”衔接设计——全量迁移跑完后能通过日志回放或位点续传的方式继续同步增量数据不需要业务停机太久这对生产环境迁移来说几乎是刚需。但问题也出在这里DBmotion 本身不是一个单二进制文件跑完所有事情的工具它依赖不少周边组件。拿全量迁移场景来说调度服务、执行引擎、元数据库、消息中间件、监控面板每一块都有自己的运行环境要求。假设你手动部署光是环境兼容性这一关就能耗掉大半天——Java 版本对不对、Python 依赖冲不冲突、MySQL 客户端库版本和远端数据库协议匹不匹配全是坑。所以当我看到“DBmotion 全量所需要容器集合包含可执行的 docker-compose.yaml”这个项目时第一反应是这玩意儿把最烦人的环境问题直接掐掉了。它把 DBmotion 全量迁移要用的所有组件打包成一套容器镜像再用一个 docker-compose.yaml 把服务编排起来执行 docker compose up -d 就能拉起一整套环境。对于只想快速验证迁移流程、或者没有专职运维团队的中小团队来说这种交付方式比看一叠部署文档舒服太多了。这篇文章我不打算只贴一份 yaml 文件我会把这份 compose 文件背后“为什么要这么设计”的逻辑拆开讲清楚。包括每个容器承担什么职责、服务之间怎么通信、数据卷怎么挂、哪些参数必须调整、启动顺序为什么有讲究。就算你之前没接触过 DBmotion看完也能照着部署一套可用环境并且知道出了问题该从哪里排查。2. 容器集合的整体设计思路拆解2.1 为什么要用 Compose而不是逐个 docker run很多人习惯用一个超长的 docker run 命令把所有参数堆在一起这种方式的缺点很明显参数不可复用、顺序容易记错、一旦要改端口配置就得把整条命令翻出来改。一套容器集合里有七八个服务每个服务又有环境变量、端口映射、数据卷、依赖关系用 docker run 管理就是给自己找罪受。docker-compose.yml 的核心价值是把“服务拓扑”用声明式的方式固定下来。你写清楚哪几个服务、各自用什么镜像、暴露哪些端口、挂载哪些目录、谁依赖谁之后在任何一台装了 Docker 和 Compose 插件的机器上执行两条命令就能复现一整套环境。这对迁移工具的交付尤其重要因为迁移工具本身就要求环境一致性用容器化编排文件正好把“在我机器上是好的”这种问题从根上杜绝。2.2 这套“全量容器集合”里都装了什么根据 DBmotion 做全量迁移的典型链路整个执行流程大致是管理端接收迁移任务把任务拆分成多个分片分发给执行节点执行节点从源库抽取数据、经过缓冲队列、写入目标库同时把任务状态和元数据记录下来。这个链路落到组件上至少需要四类角色元数据库容器DBmotion 自己的元数据任务配置、分片状态、同步位点要落库存储。通常用 MySQL 或 PostgreSQL 承担这个角色。调度/管理服务容器接收 Web 操作和 API 请求负责任务编排和分发是整套系统的控制面。执行引擎容器真正干活的部分负责连接源端和目标端执行数据抽取与写入。DBmotion 的执行引擎依赖 Java 运行时不同版本对 JDK 版本有要求。辅助组件容器根据迁移方案不同可能包括消息队列做数据缓冲、监控面板看迁移进度和指标等。这套容器集合的 compose 文件就是把上述角色全部装进来的“全家桶”并且通过自定义网络让它们互相能通。所谓“全量所需要”就是指你不需要再去外部部署任何一个依赖服务——从零到能跑通一次全量迁移只靠这一份编排文件。2.3 编排方案选型的几个关键考量点在决定用 Compose 编排这套环境时有几个关键点我分析下来觉得值得特别说明。首先是网络模式的选择。compose 默认会给项目创建独立的 bridge 网络服务之间通过服务名互相访问。这套容器集合里DBmotion 主服务要连接元数据库执行引擎要连接 DBmotion 主服务如果每个容器单独联网服务名解析会变得很麻烦。所以我在 compose 文件里定义了一个名为 dbmotion-net 的自定义网络所有服务都加入这个网络这样在容器里直接通过服务名加端口访问对方配置简单且稳定。其次是数据卷的规划。元数据库容器如果不挂载数据卷容器重建后任务元数据全部丢失这在迁移任务进行到一半时是灾难性的。我把 MySQL 数据目录挂载到宿主机 ./data/mysqlDBmotion 的日志目录挂载到 ./data/logs这样即使容器挂了重建数据也还在。第三是启动顺序的处理。DBmotion 主服务启动时需要等待元数据库就绪执行引擎又需要等待主服务就绪。compose 本身提供了 depends_on 指令但默认的 depends_on 只保证依赖服务的容器先启动不保证依赖服务内部进程已经可用。所以我在 compose 文件里结合了 healthcheck 和 depends_on 的 condition 用法让元数据库通过健康检查后DBmotion 主服务才开始拉起。这份 compose 文件的高明之处在于它把“可执行”这个标签落实到了细节——不是启动不报错就算完而是真正能完成服务间的初始化依赖。3. docker-compose.yaml 核心配置逐段解析3.1 顶层结构与网络定义先看这份 compose 文件使用的 Compose 版本约定。新版本的 Docker Compose V2 已经默认支持 version 字段省略建议直接省略避免版本号写旧了触发兼容警告。顶层结构分为 services、networks、volumes 三个核心段落其中 volumes 是可以省略的因为数据卷可以直接在 service 里用相对路径挂载。网络定义我单独拿出来讲因为它决定了整个容器集合能不能互相通信。自定义网络配置如下networks: dbmotion-net: driver: bridge ipam: config: - subnet: 172.28.0.0/16这段的意思是创建一个 bridge 类型的自定义网络网段固定为 172.28.0.0/16。固定网段有几个好处一是服务 IP 不会因为 Docker 重启而变化二是如果你要保持固定的网络环境比如给数据库容器配置防火墙白名单就能按网段放行三是避免 Docker 自动分配的网段和公司内网网段冲突。不过要提醒一句如果宿主机的内网网段恰好也是 172.28.0.0/16需要改掉这个网段。换一个不冲突的私有网段比如 172.30.0.0/16。3.2 元数据服务配置我以 MySQL 作为元数据库配置如下mysql: image: mysql:8.0 container_name: dbmotion-mysql restart: always environment: MYSQL_ROOT_PASSWORD: dbmotion123 MYSQL_DATABASE: dbmotion MYSQL_USER: dbmotion MYSQL_PASSWORD: dbmotion123 TZ: Asia/Shanghai ports: - 13306:3306 volumes: - ./data/mysql:/var/lib/mysql - ./init-sql:/docker-entrypoint-initdb.d:ro networks: dbmotion-net: ipv4_address: 172.28.0.10 command: - --character-set-serverutf8mb4 - --collation-serverutf8mb4_general_ci healthcheck: test: [CMD, mysqladmin, ping, -h, 127.0.0.1, -pdbmotion123] interval: 10s timeout: 5s retries: 10 start_period: 30s逐一解释关键点。MYSQL_DATABASE、MYSQL_USER、MYSQL_PASSWORD 表示容器首次初始化时自动创建名为 dbmotion 的数据库以及对应的账号密码。后面 DBmotion 主服务连接数据库就用这套账号密码注意密码不要设置得太复杂因为 DBmotion 的数据库连接串需要明文写在配置文件里不同容器之间传密码也不是很安全简单但强密码即可。把宿主机的 13306 映射到容器内的 3306是为了在宿主机上也能用 Navicat 等工具直连 MySQL 查看任务元数据。检查时如果发现没报错但连不上先看看宿主机的防火墙有没有放行 13306 端口。TZ 环境变量设置为 Asia/Shanghai避免容器时间和宿主机差 8 小时导致日志时间对不上。挂载 ./init-sql 目录是为了初始化建表DBmotion 的 SQL 脚本可以放到这个目录里容器首次启动时会自动执行后面不会再执行。最关键的是 healthcheck 段。mysqladmin ping 命令能探测 MySQL 进程是否正常响应。如果不加 healthcheck后续的 DBmotion 主服务启动时 MySQL 可能还没初始化完成连接就会报错。start_period 给容器留了 30 秒“预热”时间60 秒内探活失败不会标记为 unhealthy避免慢一点的服务器误报。3.3 DBmotion 主调度服务配置dbmotion-server: image: dbmotion-server:latest container_name: dbmotion-server restart: always depends_on: mysql: condition: service_healthy environment: DB_MOTION_DB_HOST: mysql DB_MOTION_DB_PORT: 3306 DB_MOTION_DB_NAME: dbmotion DB_MOTION_DB_USER: dbmotion DB_MOTION_DB_PASSWORD: dbmotion123 TZ: Asia/Shanghai ports: - 8080:8080 - 8081:8081 volumes: - ./conf/application.yml:/app/config/application.yml - ./data/logs:/app/logs networks: dbmotion-net: ipv4_address: 172.28.0.11主服务依赖 mysql且条件是 service_healthy只有 MySQL 健康检查通过后 Server 容器才启动。这避免了启动时频繁报错重试的问题。8080 端口一般给 Web 管理界面8081 端口一般给 API 服务或内部通信端口。具体端口以你自己使用的 DBmotion 版本为准容器内部端口和宿主映射端口都是可以在 compose 文件里调整的。应用配置 application.yml 是 DBmotion 主服务读取的核心配置里面包含源数据库连接信息、目标数据库连接信息、调度策略等。这里选择用挂载的方式把宿主机上的配置文件映射进容器原因是配置改动不需要重新构建镜像改完宿主机上的文件执行 docker compose restart dbmotion-server 就能生效调试效率高很多。3.4 执行引擎与辅助组件配置执行引擎容器负责实际的数据抽取和写入配置和主服务类似但是网络地址不同dbmotion-worker: image: dbmotion-worker:latest container_name: dbmotion-worker restart: always depends_on: dbmotion-server: condition: service_started environment: DB_MOTION_SERVER_HOST: dbmotion-server DB_MOTION_SERVER_PORT: 8081 TZ: Asia/Shanghai volumes: - ./data/logs/worker:/app/logs networks: dbmotion-net: ipv4_address: 172.28.0.12执行引擎不直接连接 MySQL而是通过主服务获取任务。所以它的环境变量只需要知道主服务的地址和端口。在自定义网络里这些地址通过服务名 dbmotion-server 直接解析不用关心容器的 IP 是否变化。如果你的迁移规模比较大比如数据量达到几十 GB 甚至 TB 级别一个执行引擎容器就是性能瓶颈了。这种情况下不需要改 compose 文件结构直接复制一套 service 配置换个容器名和 IP就能横向扩展执行引擎。它们会从主服务拉取不同的任务分片并行执行。这套容器集合可能还会包含一个辅助监控面板用来实时查看迁移进度、源端和目标端的连接状态。监控面板容器通过读取主服务暴露的 metrics 接口拿数据端口映射看个人需求不在此展开。3.5 完整可复用 compose 文件模板把上述内容整合成一份完整的 compose 文件供各位参考。你需要根据自己的 DBmotion 镜像版本做调整但整体框架可以直接套用networks: dbmotion-net: driver: bridge ipam: config: - subnet: 172.28.0.0/16 services: mysql: image: mysql:8.0 container_name: dbmotion-mysql restart: always environment: MYSQL_ROOT_PASSWORD: dbmotion123 MYSQL_DATABASE: dbmotion MYSQL_USER: dbmotion MYSQL_PASSWORD: dbmotion123 TZ: Asia/Shanghai ports: - 13306:3306 volumes: - ./data/mysql:/var/lib/mysql networks: dbmotion-net: ipv4_address: 172.28.0.10 command: - --character-set-serverutf8mb4 - --collation-serverutf8mb4_general_ci healthcheck: test: [CMD, mysqladmin, ping, -h, 127.0.0.1, -pdbmotion123] interval: 10s timeout: 5s retries: 10 start_period: 30s dbmotion-server: image: dbmotion-server:latest container_name: dbmotion-server restart: always depends_on: mysql: condition: service_healthy environment: DB_MOTION_DB_HOST: mysql DB_MOTION_DB_PORT: 3306 DB_MOTION_DB_NAME: dbmotion DB_MOTION_DB_USER: dbmotion DB_MOTION_DB_PASSWORD: dbmotion123 TZ: Asia/Shanghai ports: - 8080:8080 - 8081:8081 volumes: - ./conf/application.yml:/app/config/application.yml - ./data/logs:/app/logs networks: dbmotion-net: ipv4_address: 172.28.0.11 dbmotion-worker: image: dbmotion-worker:latest container_name: dbmotion-worker restart: always depends_on: dbmotion-server: condition: service_started environment: DB_MOTION_SERVER_HOST: dbmotion-server DB_MOTION_SERVER_PORT: 8081 TZ: Asia/Shanghai volumes: - ./data/logs/worker:/app/logs networks: dbmotion-net: ipv4_address: 172.28.0.12注意上面的 application.yml 是 DBmotion 主服务的核心配置里面有迁移任务的源库和目标库连接信息。根据自己的实际库地址改就行格式一般如下dbmotion: datasource: source: url: jdbc:mysql://源库IP:3306/源库名 username: root password: yourpassword target: url: jdbc:mysql://目标库IP:3306/目标库名 username: root password: yourpassword4. 实操部署过程与核心环节实现4.1 部署前需要准备好的目录结构和文件在执行 docker compose 之前先按下面的结构把文件备好dbmotion-deploy/ ├── docker-compose.yml ├── conf/ │ └── application.yml ├── data/ │ ├── mysql/ │ └── logs/ └── init-sql/ └── dbmotion-init.sql如果没有 dbmotion-init.sql数据库启动时不会自动建表需要在 DBmotion Web 界面里手动执行初始化脚本或者等 DBmotion 主服务启动时自动初始化。不同版本的 DBmotion 行为不一样稳妥的做法是手动准备好建表脚本放到 init-sql 目录里。data 目录可以留空容器启动时自动在对应目录写入数据。4.2 从零启动整套环境的操作步骤确认你已经安装了 Docker 和 Compose 插件。执行 docker compose version如果输出中包含 Docker Compose version v2.x 就说明可用。如果只输出了 docker 版本没有 compose 信息说明没装 Compose 插件需要先装。进入 dbmotion-deploy 目录先执行配置文件校验docker compose config这条命令会校验 docker-compose.yml 的语法如果文件有错误会直接报错并提示在哪一行。确认无报错后启动整套环境docker compose up -d-d参数是后台运行不加的话日志会刷屏CtrlC 后容器也会停止。首次启动会因为镜像拉取花费较长时间耐心等待。启动完成后用下面这条命令查看所有容器的状态docker compose ps正常状态应该是三个服务的 STATUS 列都显示 Up。验证服务是否全部正常最直接的方法是打开浏览器访问主服务的 Web 界面地址是 http://宿主机IP:8080。能看到登录页说明主服务正常能登录并且能看到任务管理菜单说明主服务到元数据库的连接也正常。如果要查看启动日志排查问题用命令docker compose logs -f dbmotion-server-f表示持续跟踪日志输出任务启动时的报错信息都会打在这里比去容器里翻日志文件方便很多。4.3 启动顺序为什么要这样安排这套 compose 文件把 MySQL 放在最前面且只有 MySQL healthcheck 通过 dbmotion-server 才会启动最后才拉起 worker。这背后的逻辑其实很朴实DBmotion 主服务启动时会去连接元数据库把任务的元数据表初始化好如果元数据库还没起好主服务可能启动到一半直接退出或者进入反复重试的状态。而 worker 服务启动时会主动注册到主服务如果主服务还没起来虽然不会导致容器退出但注册会失败后续任务分配会出问题。一个值得注意的细节是Compose 的 depends_on 默认只保证启动顺序不保证依赖服务内部可用。所以我们给 MySQL 加 healthcheck并且用 condition: service_healthy 等待健康检查通过。如果不用这个配置会出现 MySQL 容器起来了但内部还在初始化DBmotion Server 一启动就连库失败的情况。我在本地测试时第一次就踩了这个坑加了 healthcheck 之后问题消失。4.4 如何验证整套环境能正常跑通一次全量迁移环境起来之后建议先用一个小数据量的库做迁移验证而不是直接上生产大库。我个人的流程是先在 Web 界面上创建一个迁移任务源库填一个测试库目标库填另一个测试库表结构保持一致。任务创建后观察任务状态变化从“待执行”到“执行中”再到“已完成”。执行中可以看到迁移进度条和当前处理的行数这个信息在主服务的日志中也能看到。迁移完成后去目标库执行 count(*) 对比源库和目标库的行数。如果数字对得上说明全量迁移这条链路是通的。这一步很重要不要看界面显示“已完成”就直接下结论数字校验是最终的裁判。4.5 数据卷备份和恢复的快速操作建议迁移环境跑了一段时间后元数据库里积累了不少任务记录和调度状态信息。建议定期备份 data/mysql 目录。备份过程中有一个细节容易踩坑直接复制 data 目录里的 ibdata1 和 ib_logfile 文件是没问题的但必须在 MySQL 容器停止状态下复制否则复制出来的是热备份数据可能因为文件不一致导致恢复失败。更稳妥的方式是进入容器用 mysqldump 导出逻辑数据。执行这条命令备份docker exec dbmotion-mysql mysqldump -udbmotion -pdbmotion123 dbmotion backup.sql恢复时把 backup.sql 复制到 init-sql 目录下然后删掉 data/mysql 目录里的所有文件重启容器脚本就会自动执行建库建表和数据导入。5. 常见问题与排查技巧实录5.1 MySQL 容器启动后又退出的原因与处理这是我遇到过的最多的情况。先看容器退出时的日志命令是 docker logs dbmotion-mysql。最常见的原因是 data/mysql 目录不是空的有残留数据文件导致 MySQL 初始化失败。解决方法很简单停掉所有容器把 data/mysql 目录改名备份再重新启动容器。第二个常见原因是 MySQL 8.0 对新环境的初始化需要一定内存如果你的宿主机内存只有 1G 或更少初始化可能超时报错。解决方案有两个一是换用 mysql:5.7 镜像内存占用更低二是给容器设置资源限制比如在 service 里加 mem_limit: 1g。第三个原因和端口冲突有关。宿主机 13306 端口被占用时MySQL 容器也起不来。用 docker compose ps 查看状态时会显示 Ports 这一列为空或者点击端口时提示错误。执行 netstat -tlnp | grep 13306 排查占用情况找到占用进程杀掉或者改宿主机映射端口。5.2 dbmotion-server 启动后 Web 界面打不开先看进程状态docker compose ps 确认 dbmotion-server 是 Up。然后看容器内部的日志命令同上。如果日志里报连接 MySQL 超时第一件事是确认 MySQL 容器的健康状态docker inspect --format{{.State.Health.Status}} dbmotion-mysql输出应该是 healthy。如果输出是 unhealthy 或 starting说明 MySQL 没有正常初始化。再往下查 MySQL 日志多半是初始化脚本有问题或者数据卷目录权限不对。如果是权限问题在宿主机执行 chown -R 997:997 data/mysql把目录给 MySQL 用户。如果 MySQL 正常但 server 依然连不上检查 application.yml 里的数据库连接地址是不是写了 mysql而不是 127.0.0.1 或 localhost。在 docker compose 网络内数据库地址一定要是服务名 mysql写 localhost 会指向 server 容器自身永远连不上。5.3 任务提交后一直卡在“执行中”状态这个问题的排查思路要先分方向。如果任务状态卡在执行中很久第一步看 worker 日志docker compose logs -f dbmotion-workerworker 日志里通常会打印当前正在迁移的表名和行数。如果日志一直不动先怀疑源数据库的连接被防火墙限制导致 worker 无法读取数据。执行 telnet 命令测试 worker 容器到源数据库的网络连通性docker exec dbmotion-worker telnet 源库IP 3306不通的话检查源库白名单要把 worker 容器的 IP也就是 172.28.0.12加入源库的访问白名单。如果网络通再看是不是源库有大表没有主键。DBmotion 在做全量迁移时如果分片键没有合适的索引会退化成单线程全表扫描速度极慢。解决办法是在源库为目标表增加一个自增主键或唯一索引然后重新提交任务。5.4 一个容易忽略的问题时区不一致容器默认时区是 UTC宿主机是东八区时DBmotion 任务日志里显示的迁移时间会和实际差了 8 个小时。排查问题的时候看到日志里记录的启动时间和当前时间对不上会误以为任务已经卡了很久。建议在 compose 文件的每个 service 里都加上环境变量 TZ: Asia/Shanghai统一的时区在排查问题时能省很多不必要的疑惑。另外迁移带有时间字段的数据时如果源库和目标库的时区不一致可能导致数据写入后时间偏移。DBmotion 的 JDBC 连接串里最好显式配置 serverTimezoneAsia/Shanghai比如在 application.yml 的数据库连接 URL 后面加参数url: jdbc:mysql://源库IP:3306/源库名?serverTimezoneAsia/ShanghaiuseSSLfalse5.5 宿主机重启后容器没有自动恢复restart: always 配置已经写上了按理说 Docker 服务启动时容器应该自动恢复。但 Docker 服务本身不会随着宿主机开机自动启动这是系统层面的设置。执行 systemctl enable docker把 Docker 服务设置为开机自启这样才能保证宿主机重启后容器集合自动拉起。如果还是没起来查一下 Docker 服务状态是不是 failed磁盘满了也会导致 Docker 起不来。6. 这套容器集合的适用场景与扩展建议写到这里这套容器集合能解决什么问题、不能解决什么问题我心里已经比较清楚了。它最适合的场景是需要快速搭建一套 DBmotion 全量迁移环境做 POC 验证或者企业内部多个项目组需要隔离的迁移环境时用 compose 一份一份拉起来用完就销毁成本几乎为零。但它不适合直接拿去做生产环境大规模迁移的“最终部署”。原因很简单compose 是单机编排工具如果源库和目标库在另一个机房或者迁移数据量特别大需要多机并行执行引擎compose 文件里的 worker 扩展能力受限于单台宿主机的资源。生产环境建议在 compose 文件跑通流程后把镜像推到私有化仓库再用 Kubernetes 或 Docker Swarm 做多节点调度。不过如果你只是想把一次迁移任务跑完然后把环境留着做后续增量的验证这套组合完全够用。最后还有一个从实际使用中总结的小技巧所有容器的 hostname 尽量保持稳定不要依赖容器 ID。在 compose 文件里给每个 service 设置 container_name 后日志文件里记录的就是可读的容器名比如 dbmotion-server而不是一串无意义的十六进制 ID。排查问题时扫一眼日志就能看出哪条日志属于哪个组件效率提升不是一点点。容器集合这个事踩坑的次数多了会发现大部分问题都出在“环境不规范”上而一份精心设计的 docker-compose.yaml 恰恰从源头把“环境规范”四个字落实了。本文还有配套的精品资源点击获取