简介:OpenMetadata 容器化部署手册面向开发者与运维人员,聚焦这款开源一站式元数据管理平台在 CentOS 7 环境下的落地实践,帮助读者搭建覆盖数据发现、数据血缘、数据质量与数据治理的服务实例。压缩包内仅含 1 个 doc 文件,体积约 693KB,内容按安装流程分章组织:从系统环境与 Python3、JDK 依赖准备,到 Docker 镜像源替换与 docker-ce 安装,再到 docker-compose 部署、编排文件下载及 MySQL 密码、主机端口等参数修改,最后给出服务启动与首页访问的验证方式,结构清晰,可对照逐步执行。手册还针对基础镜像拉取失败、版本差异等常见卡点给出替代思路与官方文档查阅建议,便于在离线或网络受限场景中排查问题。已有 1354 人学习下载,适合具备一定容器基础、希望低成本体验元数据管理平台的工程师参考。
1. 版本先对齐:OpenMetadata 1.5.6 的 docker 安装到底卡在哪
先说我见过最典型的一次 openMetadata docker 安装翻车:一台 CentOS 7 的机器,docker 装好了,docker-compose.yml 也拉下来了,docker-compose up -d回车之后屏幕刷过去一百多行 Pulling,最后停在浏览器打不开 8585,docker ps一看容器全是 Up,可 server 每隔两分钟重启一次。查了两个多小时才发现是三件事叠在一起:MySQL 密码只改了一处、Elasticsearch 堆内存没往下调、基础镜像走的地址在目标网络里拉不动。
这套环境不算复杂,但它是 MySQL + Elasticsearch + 迁移容器 + JVM 主服务 + Airflow 采集端一起编排,任何一个环节没对齐都会表现成「页面打不开」,很有迷惑性。这篇按「装什么版本、怎么装、参数怎么改、坏了怎么救」走一遍,环境固定为 CentOS 7 + docker-ce 24 一线 + python3 版 docker-compose 1.29.2 + OpenMetadata 1.5.6 的官方 compose 文件。适合已经会用 docker、但第一次碰这套元数据平台组合的开发者,新手照着能跑通,熟手重点看第 4、5 章的参数取舍和排查记录。
2. 环境底座:CentOS 7 上装 docker-ce 24 与 python3.6
2.1 开工前先核资源:这台机器扛不扛得住
OpenMetadata 不是单个容器,它至少要跑起 MySQL、Elasticsearch、主服务三个常驻容器,迁移容器是一次性的,采集端还带一套 Airflow。主服务和 Elasticsearch 都是 JVM,内存是第一个要算清楚的账。4G 内存能起来,但不留余量,稍微点几下数据探查就可能触发 OOM;8G 是跑得舒服的起点,16G 以上再考虑开采集任务。
磁盘同样容易低估。镜像本身占一部分,Elasticsearch 的索引目录会随着元数据量和血缘关系增长,50G 起步比较稳妥,而且/var/lib/docker所在分区要留够,别让根分区先满。
| 资源项 | 最低可跑 | 建议配置 | 说明 |
|---|---|---|---|
| CPU | 2 核 | 4 核 | 迁移和索引重建时吃 CPU |
| 内存 | 4G | 8G 及以上 | ES 与主服务各占一个 JVM |
| 磁盘 | 30G | 50G 及以上 | 索引目录随血缘数据增长 |
| 系统 | CentOS 7.6+ | CentOS 7.9 | 内核 3.10 及以上 |
端口也要提前核对,别等容器起来了才发现撞车。8585 是主服务 Web 端口,3306 是 MySQL,9200/9300 是 Elasticsearch 的 HTTP 与节点通信口,采集端那条链路默认还会占 8080。上机第一件事:
# 看这几个端口有没有被别的服务先占了,有输出说明冲突 ss -lntp | grep -E '8585|3306|9200|9300|8080'ss -lntp里-l只看监听态,-n不做域名解析,-t限定 TCP,-p带上进程名。有输出就逐个确认是不是非本机的业务,占用了就得在 compose 里改宿主机侧端口,或者先腾出来。
2.2 装 docker-ce:锁版本、换仓库、验证三项
CentOS 7 上直接yum install -y docker-ce现在不一定好使,仓库里最新几版对 CentOS 7 的支持在收缩,容易报找不到包或者依赖不满足。我的习惯是锁 24 一线,配合--nobest让 yum 在依赖冲突时退而求其次,而不是直接失败。
# 1. 基础依赖,device-mapper 与 lvm2 是存储驱动的前置包 yum install -y yum-utils device-mapper-persistent-data lvm2 --skip-broken # 2. 加 docker-ce 仓库,尖括号处换成你环境里能访问的镜像站域名 yum-config-manager --add-repo https://<mirror-host>/docker-ce/linux/centos/docker-ce.repo # 3. 仓库文件里默认写的是官方地址,整体替换成镜像站,否则后面装包还是会去外网 sed -i 's/download.docker.com/<mirror-host>\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo # 4. 清掉旧缓存重建索引,不然 yum 还在用老元数据 yum makecache fast # 5. 装指定版本,三个包版本要一致 yum install -y docker-ce-24.0.9 docker-ce-cli-24.0.9 containerd.io --nobest # 6. 启动并设为开机自启,少这一句重启机器后容器全没了 systemctl start docker systemctl enable docker--skip-broken的作用是跳过那些装不上的可选依赖,不让整条命令回滚;--nobest是告诉 yum 不要死磕最高版本,允许它挑一个能装上的组合。第 3 步的sed不能省,很多「装是装上了但拉镜像还是慢」的情况,根子就在这里:仓库地址换了,包描述里的源地址没换。
装完做两个层次的验证,一个看客户端,一个看服务端:
# 客户端版本,能输出说明二进制在 docker -v # 服务端信息,重点看这三行 docker info | grep -E 'Server Version|Storage Driver|Docker Root Dir'Server Version和客户端对得上,说明 daemon 正常;Storage Driver在 CentOS 7 上通常是 overlay2,如果是 vfs 说明文件系统不支持,性能会差一个量级;Docker Root Dir默认/var/lib/docker,磁盘紧张时在/etc/docker/daemon.json里改># 四个包一起装,devel 是后面编译依赖时用的,tools 里有调试工具 yum install -y python3 python3-devel python3-libs python3-tools # 补 pip 模块,有些最小化安装的镜像是没有 pip 的 python3 -m ensurepip # 升级 pip,但必须压在 22 以下,3.6 装不了更新的版本 python3 -m pip install --upgrade "pip<22" # 装 wheel,否则后面装 docker-compose 时可能报 bdist_wheel 缺失 python3 -m pip install wheel # 验证,两条都要看 python3 -V python3 -m pip -V
注意这里全程用python3 -m pip而不是直接敲pip。CentOS 7 上/usr/bin/pip很可能还指向 python2.7 的 pip,用它装出来的包 python3 看不见,症状是「明明装成功了,执行 docker-compose 还是 command not found」。python3 -m pip -V的输出里会带上 pip 自己所在的路径,一眼就能看出装到哪个解释器下面了。
提示:python3.6 已经停止维护,作为 compose 的运行环境没问题,但不要把公网可达的业务接口跑在它上面。
2.4 防火墙与 SELinux:先把 8585 放出来
CentOS 7 默认开 firewalld,容器做了端口映射,宿主机防火墙不放行的话外面照样连不上。这一步很多人留到最后才想起来,结果把排查方向带偏到容器网络上去。
# 永久放行 8585,加 --permanent 才是写进配置 firewall-cmd --add-port=8585/tcp --permanent # 重载生效 firewall-cmd --reload # 确认端口在放行列表里 firewall-cmd --list-ports如果机器上 firewalld 没启用,直接systemctl status firewalld看一眼,别盲目执行。SELinux 方面,卷挂载报Permission denied时先setenforce 0临时验证是不是它拦的,确认后用semanage加规则,而不是一直关着——这是我一直坚持的做法,临时关可以,长期关是给自己埋雷。
3. 编排层准备:docker-compose 1.29.2 与 1.5.6 版 compose 文件
3.1 pip 装 docker-compose,为什么锁 1.29.2
docker-compose 从 2.x 开始换成 Go 重写并以 docker 插件形式分发,python3.6 的 pip 根本装不上。1.29.2 是最后一个支持 py3.6 的版本,所以在这里不是「保守」,是唯一选择。
# 锁版本安装,不加版本号会去拿 2.x 然后编译失败 python3 -m pip install docker-compose==1.29.2 # 验证,输出里应该有 1.29.2 docker-compose -v # 顺手确认命令落在哪,通常是 /usr/local/bin/docker-compose which docker-compose装完docker-compose -v报ImportError之类,八成是 pip 版本过新或者 setuptools 太旧,回退python3 -m pip install "setuptools<60"再重装一次基本能解决。
如果你的 docker 是 20.10 以上,其实还有另一条路:直接用 compose v2 插件,二进制丢到/usr/libexec/docker/cli-plugins/docker-compose,命令变成docker compose(中间是空格)。两者的差别要提前知道:v2 会忽略 compose 文件顶部的version字段,v1 则认它;v1 的docker-compose down默认不删卷,v2 的docker compose down -v才会连卷一起删。这篇主线走 v1,因为 1.5.6 的官方文件是按 v1 的写法给的,照抄最省事。
3.2 建目录,把 1.5.6 的 compose 文件拿下来
文件别放家目录,放/opt下,权限清晰,磁盘位置也好确认。目录建好之后第一件事是把原始文件备份一份,改配置改崩了能立刻回滚。
# 建工作目录并进入 mkdir -p /opt/openmetadata-docker && cd /opt/openmetadata-docker # 下载 1.5.6 对应的 compose 文件 wget https://github.com/open-metadata/OpenMetadata/releases/download/1.5.6-release/docker-compose.yml # 确认文件下下来了,大小不是 0 ls -lh docker-compose.yml # 备份原始文件,改坏了直接 cp 回来 cp docker-compose.yml docker-compose.yml.bak命令里带1.5.6-release这一段,版本号改一位,拉到的就是另一套服务定义,配置文件里的字段可能对不上。执行wget时报连接超时是常事,那就用浏览器打开同一个地址手动下载,再通过文件传输工具传到这台机器上,落点还是/opt/openmetadata-docker。别在服务器上反复重试,浪费时间。
3.3 打开文件先认服务:这几个容器分别干什么
第一次看这个文件容易以为是单容器部署,其实是一整套。先认清楚谁是谁,后面排查日志才知道该看哪个。
| 服务名 | 作用 | 默认端口 | 是否常驻 |
|---|---|---|---|
| mysql | 元数据库,存用户、表结构、配置 | 3306 | 是 |
| elasticsearch | 搜索与索引,页面搜索、血缘图依赖它 | 9200 / 9300 | 是 |
| executeMigrations | 一次性执行数据库迁移脚本 | 无 | 否,跑完退出 |
| openmetadata_server | 主服务,Web UI 和 API 都在这 | 8585 | 是 |
| ingestion | 采集与数据探查,内部带 Airflow | 8080 | 视使用情况 |
executeMigrations是最容易被误判的一个:docker ps看不到它,用docker ps -a才会看到一个 Exited (0) 的记录,这是正常的、期望的结果。反过来,如果它频繁重启或者退出码不是 0,那主服务一定起不来,因为表结构没建好。这一点在第 5 章还会展开。
3.4 哪些字段该改,哪些碰都别碰
改配置最怕整段替换。这份文件里,环境变量之间是有联动关系的,改一处不改另一处,症状往往隔了好几层才显现。我的划分是:
该改的:MySQL 的 root 密码与业务账号密码、主服务和迁移容器里对应的数据库密码、端口映射的宿主机侧、镜像地址前缀、Elasticsearch 的堆内存参数。
不该动任意值的:服务名(mysql、elasticsearch这些名字被写进了别处的连接串)、DB_HOST这类指向服务名的变量、容器内部的端口号、depends_on顺序、DB_SCHEMA库名。服务名一改,主服务就找不到数据库,报的还是「连接被拒绝」,很容易查偏。
改之前拿diff记录自己的改动,出问题时diff docker-compose.yml docker-compose.yml.bak一眼看出动过什么,这比回忆改了哪里靠谱得多。
4. 改配置:docker-compose.yml 里 MySQL 密码、端口与镜像地址
4.1 MySQL 密码:三处必须同步,改一处等于没改
这是我在第 1 章提到的那次翻车的第一个原因。文件里数据库密码分散在至少三个位置,它们的值必须完全一致,否则主服务连库直接被拒。下面是我改完后的片段,字段名以你下载到的 1.5.6 文件为准,位置对应上就行。
services: mysql: environment: MYSQL_ROOT_PASSWORD: "ChangeMe_Root_2024" # root 密码,只在容器内部用 MYSQL_USER: openmetadata_user # 业务账号,别用 root MYSQL_PASSWORD: "ChangeMe_OM_2024" # 业务账号密码,第 1 处 MYSQL_DATABASE: openmetadata_db openmetadata_server: environment: DB_USER: openmetadata_user DB_USER_PASSWORD: "ChangeMe_OM_2024" # 第 2 处,必须和第 1 处一致 DB_HOST: mysql # 服务名,别换成 IP DB_PORT: 3306 executeMigrations: environment: DB_USER_PASSWORD: "ChangeMe_OM_2024" # 第 3 处,迁移容器也要连库三处指的是MYSQL_PASSWORD、openmetadata_server的DB_USER_PASSWORD、executeMigrations的DB_USER_PASSWORD。只改第一处,MySQL 容器会正常起来(它只认自己的环境变量),但主服务的日志里会出现Access denied for user 'openmetadata_user'@'172.x.x.x',然后不停重启。看到这个报错,先回去比对这三行,别急着怀疑网络。
密码本身也有讲究。含$、#、:这类字符时要用双引号包起来,YAML 里#后面是注释,不引起来会被截断,症状是「明明写了长密码,登录却说不匹配」。密码里带$在 compose 里还可能被当成变量插值,最稳的做法是只用字母数字加下划线和短横线。
4.2 端口映射:8585 要暴露,3306 和 9200 只给本机
端口映射的写法是「宿主机:容器」,左边能改,右边不能动。右边是容器内部的监听端口,改了服务本身不知道,直接连不上。
openmetadata_server: ports: - "8585:8585" # 左侧宿主机端口可按需改,右侧保持容器端口 mysql: ports: - "127.0.0.1:3306:3306" # 只绑回环,外部访问不到 elasticsearch: ports: - "127.0.0.1:9200:9200" # 同理,需要直连时用跳板机转发加127.0.0.1:前缀的意思是只监听本机回环网卡,公网 IP 上不开放。这份文件原样跑起来,MySQL 和 Elasticsearch 是对外裸奔的,而在真实环境里,元数据库里存着用户和权限信息,Elasticsearch 里是全部元数据,不该直接暴露。需要临时连库排查时,在本机用客户端连127.0.0.1:3306,或者用 SSH 端口转发,别为了省事改成0.0.0.0。
另外注意只写一个端口(比如- "8585")会让 Docker 随机分配宿主机端口,docker ps里显示成0.0.0.0:32768->8585/tcp,这种写法在只做内网访问时有用,但排查时容易看花眼,我不太用。
4.3 镜像拉不动:把镜像前缀换成自己能访问的仓库
1.5.6 的 compose 文件里,每个服务的image都指向公共镜像仓库。目标机器拉不动的时候,docker-compose up会一直卡在 Pulling,最后抛TLS handshake timeout或者manifest unknown。常见的做法是找一台能拉的机器先把镜像取下来,打标签推到自己的私有仓库,再改 compose 里的前缀。
# 先把文件里所有 image 列出来,一次性看清楚要处理多少个 grep -E '^\s+image:' docker-compose.yml | awk '{print $2}' | sort -ugrep抓 image 行,awk '{print $2}'取第二个字段也就是镜像名,sort -u去重排序,输出就是一个完整的待处理清单。
然后按清单逐个搬运,以主服务为例:
# 在能访问公共仓库的机器上拉取,tag 必须原样保留 docker pull openmetadata/server:1.5.6 # 重新打标签,指向自己的仓库地址 docker tag openmetadata/server:1.5.6 <your-registry>/openmetadata/server:1.5.6 # 推送到私有仓库 docker push <your-registry>/openmetadata/server:1.5.6compose 文件里对应改一行:
openmetadata_server: image: <your-registry>/openmetadata/server:1.5.6 # 只换前缀,tag 不动tag 一定不能改。1.5.6换成latest或者别的版本,服务之间会出现协议不兼容,表现出来是迁移失败或者页面 500。改完之后docker-compose config会把渲染后的完整配置打出来,顺便校验 YAML 语法,比直接 up 然后看报错快。
4.4 数据落地与 Elasticsearch 内存:两个必须一起调的参数
Elasticsearch 默认的 JVM 堆对这台机器来说偏大,4G 内存的机器上它一起来就把系统挤爆,然后被内核 OOM killer 干掉,容器退出码 137。堆参数和虚拟内存映射区两个都要处理。
elasticsearch: environment: ES_JAVA_OPTS: "-Xms512m -Xmx512m" # 4G 机器调到 512m,8G 可保持 1g volumes: - ./data/es:/usr/share/elasticsearch/data # 索引目录落到宿主机,重建容器不丢-Xms和-Xmx设成相等,避免堆在运行中反复扩缩带来的停顿。容器里的目录映射出来之后,docker-compose down再 up,索引还在,不用重新采集。同理可以给 MySQL 加一条./data/mysql:/var/lib/mysql,这个我强烈建议加,不然手滑down -v一次,元数据全没,这个后悔药没地方买。
宿主机侧还要放开内存映射限制,不然 Elasticsearch 启动时 bootstrap checks 直接失败:
# 临时生效,重启机器后回到默认值 sysctl -w vm.max_map_count=262144 # 写入配置持久化,重启后依然有效 echo "vm.max_map_count=262144" >> /etc/sysctl.conf参数值 262144 是 Elasticsearch 要求的下限,低于它会拒绝启动。写进/etc/sysctl.conf比只敲临时命令稳,容器重启不受影响,机器重启也不受影响。
5. 避坑记录:compose up 之后起不来的五种现场
5.1 卡在 Pulling,最后报 TLS handshake timeout
现象:docker-compose -f docker-compose.yml up --detach执行后长时间停在Pulling mysql ...或某个镜像名上,几分钟后抛出net/http: TLS handshake timeout,容器一个都没起来。
原因:宿主机访问公共镜像仓库的链路不通,或者带宽极低导致握手阶段就超时。这一步和 compose 文件本身没关系,配置文件写得再对也拉不下来。
解决:按 4.3 的方式把镜像逐个搬到私有仓库,改 compose 里的image前缀。急的时候可以先在能访问的机器上docker save成 tar 包传过来docker load,但长期用还是要有自己的仓库。判断是不是这个问题很简单:docker pull单独拉一个基础镜像,同样超时就说明是链路问题。
5.2 容器全是 Up,浏览器打开 8585 还是连不上
现象:docker ps里openmetadata_server状态 Up,宿主机上curl 127.0.0.1:8585有响应,但外面浏览器打不开。
原因:按出现频率排,依次是宿主机 firewalld 没放行 8585、端口映射写成了127.0.0.1:8585:8585(只绑回环)、云环境的安全组没开、以及主服务 JVM 冷启动还没完成。
解决:先在宿主机上curl -I http://127.0.0.1:8585,本机能通就是防火墙或安全组的问题,firewall-cmd --list-ports确认;本机也不通就看docker-compose logs -f openmetadata_server,如果是Started Application之前的日志在滚,等一到三分钟,JVM 起来没那么快。别看到 Up 就以为服务好了。
5.3 executeMigrations 反复重启,日志是 Communications link failure
现象:docker ps -a里迁移容器的状态在Restarting和Exited (1)之间来回跳,主服务一直起不来。
原因:MySQL 容器还处在初始化阶段,depends_on只保证启动顺序,不保证对方「能用」。迁移脚本连过去时数据库还没准备好接连接,直接抛连接失败,容器按重启策略再来一次。
解决:等 MySQL 的日志出现ready for connections再执行 up;或者干脆分两步,先docker-compose up -d mysql elasticsearch,docker-compose logs -f mysql看到就绪,再docker-compose up -d。如果反复失败并且日志是Access denied,那就回到 4.1,三处密码没对齐。
5.4 elasticsearch 起来几十秒就消失,退出码 137
现象:ES 容器启动后一阵子自己没了,docker inspect看ExitCode是 137,主服务日志里全是索引连接的异常。
原因:137 是 128+9,被 SIGKILL 杀掉,绝大多数是宿主机内存不足被 OOM killer 选中。第二种可能是vm.max_map_count没调,启动阶段 bootstrap checks 失败。
解决:先free -h看内存水位,按 4.4 把ES_JAVA_OPTS调小;再dmesg | tail -30确认有没有 OOM 记录,有的话就是内存问题无疑。参数没调的执行sysctl -w vm.max_map_count=262144。把 ES 和主服务挤在一台 4G 机器上本来就紧,把采集任务放到别的机器是更彻底的做法。
5.5 登录页提示账号密码错误,或者中文显示成问号
现象:用默认的admin@open-metadata.org登录,提示凭据无效;或者元数据里的中文描述全变成问号。
原因:密码在users表里存的是 bcrypt 哈希,不是明文,直接UPDATE成明文值会导致哈希校验永远失败。中文乱码则是数据库和连接串的字符集不是 utf8mb4。
解决:忘记密码时不要去改明文,用平台提供的重置方式,或者在库里写入一段已知密码的 bcrypt 哈希值。字符集方面,MySQL 侧建库参数用utf8mb4,连接串带上对应参数,容器起来之前就把这些定好,比事后改表省事得多。这类问题没有捷径,只能一开始就配对。
6. 装完怎么验证:8585 首页到容器健康的三层确认
装完就打开浏览器点一遍,是我早期最常犯的错——页面能开,不代表后台的迁移、索引、采集链路都是通的。后来我固定按三层往下确认,任何一层不对就停下来查,不往下走。
第一层看容器状态和退出码:
# 看常驻容器是否都在 Up,注意 STATUS 里有没有 Restarting docker-compose -f docker-compose.yml ps # 单独看一次性容器,迁移容器的期望值是 Exited (0) docker ps -a --filter "name=executeMigrations"docker-compose ps比docker ps好用的地方在于它只列这个编排文件里的服务,标签和端口一目了然。迁移容器只要是Exited (0),说明表结构已经建完,这是主服务能起来的前提。
第二层看接口和端口是不是真的通了:
# 主服务健康检查,返回 200 说明 Web 层已经就绪 curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8585 # 看最近的启动日志,正常会看到 Started Application docker-compose -f docker-compose.yml logs --tail=50 openmetadata_server # 确认 ES 索引侧没有报错 docker-compose -f docker-compose.yml logs --tail=30 elasticsearch | grep -i errorcurl那条返回000是连不上,502一般是反向代理层的问题,200才算过关。日志里--tail=50只取最后 50 行,避免一屏刷完找不到重点。
第三层落到页面上,逐项过一遍:
| 验证项 | 操作 | 期望结果 |
|---|---|---|
| 首页可访问 | 浏览器打开http://<宿主机IP>:8585/ | 出现登录页 |
| 默认账号可登录 | admin@open-metadata.org加初始密码 | 进入主界面 |
| 服务状态 | 设置页看各服务连通性 | 数据库与搜索均为正常 |
| 数据可见 | 建一个测试库连接或导入示例数据 | 能搜到对应表 |
默认管理员账号是admin@open-metadata.org,初始密码在部署文档里有说明,第一次登录后立刻改掉,别留着默认值跑在能被访问的网段上。改密码走界面里的账号设置,别去数据库里直接改字段,原因在第 5.5 条说过。
页面能打开之后,我还会做一件很多人跳过的事:docker-compose down再up -d一次,确认数据卷挂载生效,重启后元数据和账号都还在。这一步花两分钟,能提前发现卷没挂对的问题——等平台里录了几百张表的元数据再发现,就不是两分钟的事了。
从那以后我每次装这类多容器平台,都强制走一遍「容器状态 → 接口返回码 → 页面登录 → 重启一致性」这四步,不管前面看起来多顺利。装环境这件事,能跑起来和能一直跑是两码事,前面多花二十分钟,后面少熬两个晚上。希望帮到你。
本文还有配套的精品资源,点击获取