
先交代一下背景上周帮项目组把一套 Doris 测试集群从手工部署迁移到 Docker Compose 管理拓扑是 1 个 FE 3 个 BE跑在三台虚拟机里期间踩了网络、权限、元数据好几个坑。这篇文章不是官方文档的复述而是把我实际操作下来的 compose 编排、参数取舍、问题排查全部摊开写一遍给准备用 Docker Compose 部署三节点 Doris 集群的同学做个参考。文章会覆盖从架构原理、镜像选择、compose 文件细节到验证、巡检的完整链路尽量让你照着做就能把集群拉起来。1. 部署前想清楚的三件事架构、选型与资源规划1.1 一分钟看懂 Doris 架构里的 FE 和 BEDoris 的核心组件就两个FEFrontend和 BEBackend。FE 负责 SQL 解析、查询规划、元数据管理、事务协调它本身不存数据BE 负责数据存储、查询执行、副本复制以及后台的 Compaction 合并工作。还有一个可选组件叫 Broker主要用来对接外部数据源做导入导出本文先不展开。理解这个分工非常重要因为很多部署问题都出在“不知道哪个组件该管什么事”。比如建表失败要去 FE 日志里查数据写入慢但查询正常问题大概率在 BE 侧FE 挂了但没有备用 FE整个集群就失去了元数据服务连登录都不行这就是为什么生产环境必须配 3 个 FE 做高可用而测试环境可以先用 1 个 FE 顶着。这里说的三节点集群我建议这样理解一台宿主机上用 docker compose 同时拉起 1 个 FE 容器 3 个 BE 容器模拟出 3 个数据节点的逻辑拓扑。如果你正好手上有三台机器也可以把 3 个 BE 容器分散部署到三台不同的机器FE 放在第一台上原理完全一样只是网络规划要额外注意后面会专门讲。先看一个推荐的角色规划表格节点角色职责建议数量三节点测试环境方案FE Master元数据、查询协调1测试/3生产容器 doris-fe-1BE 节点数据存储与计算3 起步容器 doris-be-1 / be-2 / be-3Broker可选外部数据源对接按需一般测试环境不需要Doris 的副本机制决定了 BE 数量至少是 3 个起步才比较稳。默认副本数replication_num是 3意味着每个分片有 3 份拷贝分别落在 3 个不同的 BE 上任何一个 BE 宕机数据副本还能满足多数派写入要求集群不会立即不可用。如果你只起 1 个 BE把副本数强行设成 3建表就会直接报alive replica insufficient。1.2 为什么是 Docker Compose而不是裸机或 K8s很多人一上来就问Doris 不是有官方二进制包吗直接解压装不就行了为什么还要套一层 Docker Compose我的回答是如果你想快速搭一套测试环境、验证 SQL 和工具链Compose 的性价比确实最高。裸机部署 Doris 的痛点很现实要准备 JDK 环境要手工编辑fe.conf、be.conf要检查ulimit和vm.max_map_countFE 和 BE 的启动顺序还得自己盯着中间任何一个环节出错都得重新排查。尤其当你需要反复推倒重来做实验时手工部署的清理成本很高一不小心就把系统环境搞脏了。K8s 当然适合生产环境但对大多数人来说为了一个测试集群去搞 PVC、Service、StatefulSet学习成本已经超出了部署本身。Docker Compose 的优势在于项目文件就是配置本身一条命令拉起一条命令停止目录删掉就是彻底清理。配置文件写好后换一台机器也能快速复现同样的环境。不过我得说明白Docker Compose 更适合单机编排。如果你是三台独立机器组成的跨主机集群Compose 不是最好的选择它没有跨主机容器通信的原生能力需要靠extra_hosts或者 Docker Swarm 这种额外方案去补复杂度反而上去了。本文以单台机器模拟三节点为主跨主机的差异点会在网络那一节单独说明。1.3 端口、存储与资源规划不然后面要返工部署前把端口和存储规划好后面能省很多事。Doris 有几个核心端口必须清楚端口所属组件用途是否建议映射到宿主机8030FEWeb UI 和 HTTP API是9030FEMySQL 协议端口所有 SQL 客户端都连它是9020FEFE 内部 RPC 通信容器内通信即可8040BEBE 的 HTTP 服务按需9050BE心跳上报端口BE 用它与 FE 通信容器内通信即可9060BEBE 的 Thrift RPC 服务容器内通信即可如果你用单机模拟三节点容器之间通过自定义 bridge 网络互通9050、9060、9020这些端口不需要暴露到宿主机。对外只需要暴露 FE 的8030和9030以及可选的 BE8040端口用于调试。存储规划上最重要的两件事是FE 的元数据目录和 BE 的数据目录必须做成宿主机目录挂载。FE 元数据在容器里默认路径是/opt/apache-doris/fe/doris-metaBE 数据目录默认是/opt/apache-doris/be/storage。不挂载的话容器一删集群就没了挂载后即使容器重建元数据和数据都还在。另外给 FE 至少预留 10G 空间存元数据快照和日志BE 的存储空间要按三副本计算比如你有 100G 的业务数据在 BE 上占用的其实是 300G这个容易被人忽略。内存方面我建议FE 容器至少 4GBE 容器至少 6G宿主机总内存 16G 以上才跑得比较舒服。如果机器资源紧张BE 至少也得 4G再低就会出现大查询 OOM 或者 JVM 之外的进程崩溃排查起来非常痛苦。2. 环境准备与镜像选择避开 Version 坑2.1 Docker 与 Docker Compose 的安装思路我自己用的宿主机是 CentOS 7.9内核 3.10Docker 24.xCompose v2.26.1。如果你的环境是 Ubuntu 或者其他发行版安装方式大同小异核心是两条装好 Docker 引擎装好 compose 插件。很多老教程还在讲docker-compose这个独立二进制但现在 Docker 官方主推的是 compose v2 插件命令是docker compose中间有空格。安装 compose 插件最直接的方式就是把二进制放到~/.docker/cli-plugins/目录下# 安装 Docker 引擎Linux 环境 curl -fsSL https://get.docker.com | bash systemctl enable --now docker # 创建 compose 插件目录 mkdir -p ~/.docker/cli-plugins # 下载 compose 二进制并赋执行权限 curl -SL https://github.com/docker/compose/releases/download/v2.26.1/docker-compose-$(uname -s)-$(uname -m) \ -o ~/.docker/cli-plugins/docker-compose chmod x ~/.docker/cli-plugins/docker-compose # 验证 docker compose version这里有个细节如果下载速度不理想可以考虑用镜像站下载或者在一台有网络的机器上先下载好再拷贝到目标服务器。拷贝过去后记得执行chmod x否则会提示 Permission denied。离线环境更稳妥的做法是直接把 Docker 的离线安装包、Compose 二进制、Doris 镜像文件一起打包带过去Docker 镜像用docker save导出目标机上再用docker load导入整个过程不需要外网。2.2 镜像选型统一镜像和分角色镜像的区别Doris 的官方 Docker 镜像发展分两个阶段选型时一定要看清楚版本不要凭经验乱猜。早期版本2.x 及以前的镜像是按角色拆开的比如apache/doris-fe:2.1.7和apache/doris-be:2.1.7你 FE 拉 FE 镜像BE 拉 BE 镜像。从 3.0 开始官方提供了统一镜像apache/doris:3.0.x一个镜像同时包含 FE、BE、Broker 组件通过环境变量来指定容器角色比如FE_MASTERtrue表示这个容器是 FE 主节点BEtrue表示这个容器充当 BE。本文以apache/doris:3.0.4为例因为这个版本目前的容器化部署方案比较成熟官方也在推。你如果用的是 2.1 版本部署逻辑其实一样只是镜像要拆成两个compose 文件里 image 字段不一样环境变量名也可能有差异以官方文档为准。这里有一个很容易踩的坑镜像 tag 不要用latest。Doris 迭代速度很快latest指不定哪天就成了一个不兼容的版本你的 compose 文件可能上一秒还能用下一秒拉完镜像后起不来了。部署前先把版本定死拉取成功后记录镜像 digest这样可复现性最好。2.3 宿主机内核参数与 ulimitDoris 对操作系统有几个隐性要求不提前设置到位后面启动大概率会出问题。第一个是vm.max_map_count这是进程能拥有的内存映射区域数量上限。Doris 的存储引擎和内存分配对这个参数敏感官方建议调大一些。我参考官方文档的做法在宿主机上执行sysctl -w vm.max_map_count2000000如果只是临时测试这样就可以了如果想持久化就写入/etc/sysctl.conf然后执行sysctl -p生效。第二个是文件句柄数限制。BE 在运行时会打开大量文件默认的ulimit -n 1024完全不够建议至少 65535ulimit -n 65535这个也是临时生效长期设置要改/etc/security/limits.conf。在容器里可以通过 compose 的sysctls和ulimits字段来设置不过很多情况下宿主机设好了容器内也能继承大半实际操作中以容器日志报错为准缺什么补什么。3. docker-compose.yml 逐段拆解每个配置为什么这么写3.1 一个可直接用的三节点 compose 文件下面这个 compose 文件是我在单台宿主机上模拟三节点 Doris 集群的最终版本1 个 FE 3 个 BE。目录结构建议先建好mkdir -p doris-cluster/{fe-1/{doris-meta,log},be-1/{storage,log},be-2/{storage,log},be-3/{storage,log}} chmod -R 777 doris-cluster然后创建docker-compose.ymlservices: doris-fe-1: image: apache/doris:3.0.4 container_name: doris-fe-1 hostname: doris-fe-1 networks: - doris-net ports: - 8030:8030 - 9030:9030 environment: - FE_MASTERtrue - JAVA_OPTS-Xmx2g -Xms2g volumes: - ./fe-1/doris-meta:/opt/apache-doris/fe/doris-meta - ./fe-1/log:/opt/apache-doris/fe/log mem_limit: 4g restart: always doris-be-1: image: apache/doris:3.0.4 container_name: doris-be-1 hostname: doris-be-1 networks: - doris-net ports: - 8040:8040 environment: - BEtrue - BE_MEM_LIMIT4g volumes: - ./be-1/storage:/opt/apache-doris/be/storage - ./be-1/log:/opt/apache-doris/be/log depends_on: - doris-fe-1 mem_limit: 6g restart: always doris-be-2: image: apache/doris:3.0.4 container_name: doris-be-2 hostname: doris-be-2 networks: - doris-net ports: - 8041:8040 environment: - BEtrue - BE_MEM_LIMIT4g volumes: - ./be-2/storage:/opt/apache-doris/be/storage - ./be-2/log:/opt/apache-doris/be/log depends_on: - doris-fe-1 mem_limit: 6g restart: always doris-be-3: image: apache/doris:3.0.4 container_name: doris-be-3 hostname: doris-be-3 networks: - doris-net ports: - 8042:8040 environment: - BEtrue - BE_MEM_LIMIT4g volumes: - ./be-3/storage:/opt/apache-doris/be/storage - ./be-3/log:/opt/apache-doris/be/log depends_on: - doris-fe-1 mem_limit: 6g restart: always networks: doris-net: driver: bridge文件中省略了version字段。Compose v2 已经不建议写version写了反而会看到一个弃用警告所以直接不写更干净。三个 BE 的ports我映射了不同的宿主机端口8040、8041、8042避免本机端口冲突这是单机模拟多容器时容易忽略的细节。3.2 FE 配置JAVA_OPTS 与元数据卷FE 是 Java 进程堆内存通过JAVA_OPTS控制。我给的是-Xmx2g -Xms2g容器mem_limit给了 4g堆外还要留一部分给线程、元数据缓存和 JVM 自身的 overhead。很多人喜欢把堆设成 3g、4g看着是物尽其用实际上容器内存上限一压直接 OOM。比例大致控制在容器内存的 50% 左右比较稳妥。FE_MASTERtrue是 3.0 统一镜像里识别 FE 主节点的办法。生产环境需要 3 个 FE 做高可用时第一个 FE 设FE_MASTERtrue后面两个 FE 设FEtrue并且要额外配置它们加入已有集群的地址。这里的三节点测试环境一个 FE 就够。FE 元数据目录/opt/apache-doris/fe/doris-meta一定要挂载到宿主机。FE 的元数据是所有库表结构、用户权限、副本分布信息的最终归宿一旦容器删除后信息丢失整个集群等于从零开始。bind mount 之后还有个好处是排查问题方便直接看宿主机上的fe.log和audit.log不用每次docker logs。挂载目录的权限问题很常见。官方镜像里的进程不一定是 root 用户运行如果你拉起来发现 FE 一直报Permission denied大概率是./fe-1目录的所有者不是容器内用户。我的处理办法是初始化目录后直接chmod -R 777 doris-cluster测试环境图省事没问题生产环境还是建议查一下镜像里实际的 uid然后用user字段指定匹配的 uid避免权限放开过大。3.3 BE 配置存储路径、内存上限、心跳端口BE 是 C 实现内存管理方式和 FE 完全不同。我用BE_MEM_LIMIT4g这个环境变量限制 BE 进程能使用的最大内存容器mem_limit给了 6g留 2g 给操作系统的 page cache 和其他辅助进程。如果不设BE_MEM_LIMITBE 会尽量占用宿主机空闲内存单机模拟三节点时三个 BE 很可能把机器内存吃穿。BE 的数据目录/opt/apache-doris/be/storage同样必须挂载。这里有一个隐含逻辑BE 内部默认的storage_root_path就是/opt/apache-doris/be/storage所以我们 bind mount 这个目录不需要额外改be.conf里的存储路径。如果你的宿主机有多块数据盘想给 BE 挂多个存储路径就得自定义be.conf用分号分隔多个路径比如storage_root_path /data1/storage;/data2/storageBE 启动后会自动向 FE 上报心跳默认通过9050端口。compose 默认把所有容器放在同一个自定义网络里BE 往 FE 上报时使用的地址是容器 IP 和容器 hostname所以只要 FE 和 BE 在同一个网络SHOW BACKENDS里看到的地址就是容器 IP这是正常的不需要把9050映射到宿主机。如果你映射了反而容易出问题比如多个 BE 都映射同一个 9050 端口到宿主机端口冲突是必然的。3.4 为什么自定义网络而不是 host 模式容器网络模式选择上我推荐自定义 bridge 网络而不是network_mode: host。host 模式看似简单容器直接共享宿主机网络栈FE 和 BE 用127.0.0.1就能互通但代价是端口管理极其混乱三个 BE 的端口全挤在宿主机上稍微一多就冲突而且 Doris 的高可用和后续迁移都会受影响。自定义 bridge 网络有两个直接好处第一容器之间可以用 hostname 互相访问doris-be-1、doris-fe-1这种名字在配置和日志里清晰直观第二容器网络和宿主机网络隔离端口冲突范围小只需要把真正需要对外提供服务的端口映射出来就行。不过要明确一点单机 Compose 的自定义 bridge 网络只在本机有效。如果你要跨三台宿主机部署真实的三节点集群bridge 网络是走不通的需要给每个容器的/etc/hosts注入其他宿主机的 IP 映射或者改用 Docker Swarm 模式。最简单的方式是在每个 compose 服务里加extra_hosts把所有节点的主机名和宿主机 IP 对应起来例如extra_hosts: - doris-fe-1:192.168.1.10 - doris-be-1:192.168.1.10 - doris-be-2:192.168.1.11 - doris-be-3:192.168.1.12这种方式能用但每个容器都要写一份完整的映射维护起来比较烦。所以如果你一开始就规划跨主机我更建议直接用 K8s 或者至少用 Swarm别让 Compose 干它不擅长的事。4. 三节点 Doris 集群一键拉起与验证4.1 启动顺序先 FE再 BEcompose 文件里我写了depends_on但这里必须说清楚depends_on只能保证 FE 容器先启动不能保证 FE 进程已经完全可用。BE 容器启动后要立刻和 FE 通信如果 FE 的 9030 端口还没监听BE 会不断重试通常过一会儿能自己连上但不是每次都那么顺利。我实际操作时习惯分两步走# 第一步先启动 FE docker compose up -d doris-fe-1 # 第二步等 FE 日志出现 ready 标记 docker compose logs -f doris-fe-1看到类似Frontend service is ready或thrift server started的日志后再启动 BEdocker compose up -d doris-be-1 doris-be-2 doris-be-3如果你懒得等也可以一条命令全部拉起然后去日志里确认。实在不放心就写个 shell 循环每隔两秒检测一下 FE 端口是否通通了再拉后面的服务这个脚本网上很多不展开。restart: always一定要加。测试环境经常遇到宿主机重启或者 Docker 服务重启的情况有了它容器会自动拉起来Doris 集群也能恢复在线状态省去手动docker compose start的麻烦。4.2 用 MySQL 客户端完成集群初始化和注册FE 起来后用 MySQL 客户端连 FE 的 9030 端口注意这里不是连 BE是连 FEdocker exec -it doris-fe-1 mysql -uroot -P9030 -h127.0.0.1进入 MySQL 命令行后第一件事是确认 FE 状态SHOW FRONTENDS;如果那一行数据里Join为true、Alive为true说明 FE 正常。接下来看 BESHOW BACKENDS;刚启动完 BE 后SHOW BACKENDS可能会有两种情况一种是你发现 3 个 BE 已经在列表里说明统一镜像的启动脚本自动注册了另一种是列表为空需要手动把 BE 加进集群。后者更常见一些做法是ALTER SYSTEM ADD BACKEND doris-be-1:9050; ALTER SYSTEM ADD BACKEND doris-be-2:9050; ALTER SYSTEM ADD BACKEND doris-be-3:9050;这里必须重点提醒doris-be-1这个 hostname 能不能解析取决于容器是否在同一个 compose 网络里以及你在容器内执行命令时是否找得到这个域名。如果你在宿主机上直接执行mysql而不是docker exec那doris-be-1是无法解析的必须写映射到宿主机的 IP。这也是我推荐用docker exec进 FE 容器执行 SQL 的原因省去一堆网络解析问题。添加成功后重新执行SHOW BACKENDS;表格里应该有 3 行数据每一行的Alive字段都是true。如果有false说明 BE 的注册链路出了问题最常见的两个原因我在第 5 章会细说。4.3 建表、写入、查询的完整链路验证集群已经注册好了接下来建一张表验证副本和数据链路。Doris 支持多种表模型测试环境用最简单的 DUPLICATE KEY 模型就行CREATE DATABASE test; USE test; CREATE TABLE tbl_demo ( id INT, name VARCHAR(50), ts DATETIME ) ENGINEOLAP DUPLICATE KEY(id) DISTRIBUTED BY HASH(id) BUCKETS 3 PROPERTIES ( replication_num 3 );这里两个参数很值得解读。DISTRIBUTED BY HASH(id) BUCKETS 3表示把数据按 id 的哈希值分成 3 个分桶每个分桶是一个 Tabletreplication_num 3表示每个 Tablet 在 3 个 BE 上各存一份正好对应我们的三节点拓扑。如果SHOW BACKENDS里有三个 Alive 的 BE这张表建出来就是 3 个分桶、共 9 个 Tablet 副本。然后插入几条测试数据INSERT INTO tbl_demo VALUES (1, 张三, 2025-01-01 10:00:00), (2, 李四, 2025-01-01 11:30:00), (3, 王五, 2025-01-02 09:15:00); SELECT * FROM tbl_demo;能查到数据说明 FE 的查询计划、BE 的存储和副本读取已经打通。到这里一个基本可用的三节点 Doris 集群就算部署完成了。此时浏览器打开http://宿主机IP:8030用 root 账号也能登录 Web UI界面里能看到 3 个 BE 节点和它们的状态、磁盘使用量。4.4 数据目录验证与重启持久化部署完成后顺手验证一下数据持久化。执行docker compose restart重启所有容器等一两分钟后再进 FE 执行SHOW BACKENDS; SHOW TABLES;如果 BE 仍然全部 Alive表还在数据也能查询说明 Volume 挂载和重启策略都配置正确。这个验证必须做因为很多人部署时能启动一重启就发现 BE 注册信息丢失或者 FE 元数据损坏问题几乎都出在目录权限和 hostname 漂移上。这里再补一个细节宿主机./be-1/storage目录下应该能看到每个 BE 的data目录里面是按照 tablet id 组织的数据文件。如果你发现某个 BE 的 storage 目录是空的但SHOW BACKENDS显示 Alive别慌可能是新集群还没有触发数据均衡写入少量数据后不会立即在所有 BE 上平均分布Doris 后台会自动做迁移属于正常现象。5. 部署完成后最常见的 6 个问题与处理实录5.1 FE 启动失败元数据目录权限与损坏现象FE 容器一直重启日志里出现Permission denied或者Failed to read image之类的错误。原因基本是 bind mount 的宿主机目录权限不对。容器内 FE 进程要往/opt/apache-doris/fe/doris-meta写数据但宿主机./fe-1/doris-meta的所有者对不上容器内用户写不进去FE 自然起不来。解决方式很简单chmod -R 777 doris-cluster然后重启 FE。如果之前已经因为权限问题把元数据目录写坏了那就更麻烦一些。需要先把损坏的doris-meta目录改名备份再创建一个空目录并赋予权限最后重新启动 FE让 FE 重新初始化元数据。注意这样会导致已有库表信息丢失所以只适合测试环境生产环境必须先确认备份。5.2 BE 注册不上priority_networks 配置错误现象SHOW BACKENDS里 BE 一直是AlivefalseBE 日志里有heartbeat failed或者backend ip is not match。这是容器化部署 Doris 时最常见的问题没有之一。BE 启动时需要向 FE 上报自己的 IP如果宿主机上有多个网卡BE 可能选了一个 FE 无法访问的网卡 IP比如 docker0 网桥的172.x地址或者内网之外的虚拟网卡地址。FE 收到心跳发现 IP 不对直接判定 BE 不可用。解决办法是强制指定 BE 的网络。创建be.conf文件放到./be-1目录下内容加上priority_networks 192.168.1.0/24然后挂载到容器内的/opt/apache-doris/be/conf/be.conf重启 BE。这里网段要换成你宿主机实际所在的网段别照抄。FE 侧如果也有多网卡问题同样可以在fe.conf里加priority_networks原理一样。我第一次在虚拟机里部署时就被这个问题卡了两小时三个 BE 全是 Alivefalse加完配置后瞬间全绿。5.3 建表失败alive replica insufficient现象执行CREATE TABLE报错alive replica insufficient表建不出来。原因有两种一是SHOW BACKENDS里 Alive 的 BE 数量小于你设置的replication_num二是虽然 BE 是 Alive但很多 Tablet 副本还没有成功分配短时间内建表请求被拒绝。检查顺序先看SHOW BACKENDS确认 Alive 数量再确认建表语句里的replication_num不超过活着的 BE 数。如果你只是测试只有 1 个 BE 活着那建表时把replication_num改成 1 就能建出来但这不是长久的解决办法本质上还是要让所有 BE 正常注册。另外可以关注一下SHOW PROC /cluster_balance里的均衡信息如果因为数据均衡触发了节奏有异常等一会再重试通常能恢复。5.4 容器重启后 IP 漂移导致集群异常现象重启 Docker 或容器后SHOW BACKENDS里的 BE 还显示旧 IP实际容器已经换了新 IPFE 找不到 BE。compose 的自定义网络会给容器分配 IP但 Docker 服务重启后容器 IP 可能变化。FE 元数据里记录的是 BE 的 IP 和 hostname如果 IP 变了旧记录就失效了。解决办法是尽量固定 hostname并确保priority_networks配置正确。如果是容器重建导致的 IP 变化可以通过ALTER SYSTEM DROP BACKEND 192.168.x.x:9050; ALTER SYSTEM ADD BACKEND 新hostname:9050;来更新 FE 对 BE 的认知。drop 掉副本时会触发 Doris 把该 BE 上的数据副本迁移到其他 BE如果只是临时测试直接 drop 再 add 问题不大生产环境要谨慎最好在业务低峰期操作。5.5 BE OOM 被宿主机 Kill现象docker inspect里看到容器的OOMKilled字段为true或者 BE 进程无故消失BE 日志里报了Out Of Memory。原因基本都是内存分配没限制好。BE 默认会尽量使用宿主机内存单机模拟三节点时每个 BE 如果不限定内存三个 BE 能把几十 G 内存吃光宿主机 OOM Killer 直接把进程杀掉。解决方式就是前面说的compose 里给每个 BE 设置mem_limit同时通过BE_MEM_LIMIT限制 BE 进程自身的内存。另外检查宿主机是否有被其他服务占满内存Doris 建议给 BE 预留物理内存的 80% 上限剩下的留给 page cache 和系统。5.6 宿主机端口被占用导致容器启动失败现象docker compose up报port is already allocated或者bind: address already in use。测试环境最容易出现这种问题因为大家习惯默认端口。比如 9030 可能被本机已有的 MySQL 占了8030 可能被别的 Web 服务占了。解决办法最直接的就是换端口映射比如ports: - 9031:9030然后所有客户端连接用 9031。注意如果这样改第 4 节里mysql -h127.0.0.1 -P9030也要改成-P9031。这个坑看起来很小但真发生的时候很容易让人怀疑 Doris 配置有问题排查一圈发现是端口冲突浪费不少时间。问题现象大概率原因处理方式FE 一直重启bind mount 权限错误chmod -R 777 目录BE Alivefalsepriority_networks 选错网卡指定priority_networks建表失败副本数大于 BE 数调整 replication_num重启后 BE 失联容器 IP 漂移DROP 后重新 ADD BACKENDBE 被 OOM kill内存未限制设置 mem_limit 和 BE_MEM_LIMIT端口启动冲突宿主机端口被占换映射端口6. 从部署到运维还有哪些值得做的事6.1 集群健康巡检三板斧集群部署完不是终点Doris 在运行过程中需要持续关注状态。我每次看集群健康基本就是三板斧。第一板斧是 Web UI。浏览器打开http://宿主机IP:8030登录后首页能看到 FE、BE 节点数量BE 的磁盘使用率、内存使用率、tablet 数量。这个界面比命令行直观适合快速看一眼有没有异常。第二板斧是 SQL 巡检。通过 FE 的 9030 端口执行SHOW FRONTENDS; SHOW BACKENDS;重点看Alive字段是否为true。如果某个 BE 长时间false就要去那个 BE 的日志里找原因。再看一下磁盘容量SHOW PROC /backends;里面有每个 BE 的DataUsedCapacity、DiskCapacity等信息能快速判断存储水位。第三板斧是日志巡检。FE 日志主要看/opt/apache-doris/fe/log/fe.log和fe.audit.logBE 日志主要看/opt/apache-doris/be/log/be.INFO和be.out。容器环境里如果挂载了日志目录直接在宿主机上就能查tail -n 200 ./fe-1/log/fe.log | grep -i error tail -n 200 ./be-1/log/be.INFO | grep -i error重点看有没有ERROR级别的堆栈以及OutOfMemory、Realtime write fail这类关键词。6.2 建完集群就该顺手设置的几个参数部署只是开始有些参数我建议在集群跑起来后尽快设置不然后面数据量大了会吃亏。第一个是priority_networks前面已经说过必须在集群刚建好时配置否则 BE 注册到 FE 的 IP 可能是错的后面纠正的成本很大。第二个是 BE 的mem_limit除了容器内存限制Doris 自身也有一套内存管理机制。可以在be.conf里设mem_limit 4g或者用环境变量BE_MEM_LIMIT控制。不要在配置和 compose 环境变量里同时设以实际生效的那个为准。第三个是 FE 的max_java_heap_size这个参数主要影响 FE JVM 堆大小。容器化部署时直接用JAVA_OPTS-Xmx2g -Xms2g来控制更直接。调大堆内存不是免费的堆越大GC 停顿越明显Doris FE 在小集群下 2G 够用数据量大了再按需调整。第四个和日常运维关系密切Doris 会把 BE 上的小文件不断合并成大文件这个过程叫 Compaction默认是自动处理的。如果你在测试中想手动触发某个表的合并可以这样操作ALTER TABLE tbl_demo COMPACT;这在验证数据可见性和清理版本时很有用比如频繁更新同一行导致表有大量历史版本手动合并一下能明显加快查询速度这也是很多 Doris 调优资料里常提到的“手动触发对表的合并”。6.3 后续扩容与工具链衔接Doris 扩容是它的一大优势不需要停机。加一个新的 BE 节点时只要部署一个 BE 容器启动后执行ALTER SYSTEM ADD BACKEND new-be-hostname:9050;Doris 后台会自动把部分 tablet 的副本迁移到新 BE 上不需要人工搬数据。扩容的 BE 越多集群的查询和写入吞吐能力越强存储空间也随之扩大。加 FE 节点也类似高可用场景下再起一个容器设置FEtrue然后在当前集群中执行ALTER SYSTEM ADD FOLLOWER new-fe-hostname:9010;新 FE 会从主 FE 同步元数据完成后即可承担查询协调任务。生产环境建议 3 个 FE 起步节点角色里有一个是 Master另外两个是 Follower。工具链衔接方面Doris 生态已经比较丰富。Flink SQL 写入 Doris 是现在很常见的实时数仓链路通过 Flink Doris Connector 就可以直接写Unique Key模型表写入时需要注意 sequence 列设置和merge_on_write相关参数。数据同步场景还可以用 Doris CCR Sync 做库表级别的准实时复制。6.4 备份与恢复的底线最后聊聊备份。很多人以为 Doris 有三副本就不需要备份了这是误区。三副本解决的是硬件故障问题解决不了误删表、误更新数据的问题。一旦执行了DROP TABLE所有 BE 上的副本都会在后台被清理想恢复只能靠备份。FE 元数据的备份非常重要它保存了所有表结构、分区、副本分布。最简单的方式就是定期把挂载的元数据目录打包tar zcvf fe_meta_$(date %F).tar.gz ./fe-1/doris-metaBE 的数据副本一般不建议直接备份文件因为 Doris 会自己维护副本一致性你手工拷贝的数据容易被当成不一致副本处理。真正的数据级备份应该用 Doris 的BACKUP命令导出到远端存储恢复时再用RESTORE命令。对于测试环境做好 FE 元数据备份再保持三副本稳定运行已经能覆盖绝大多数场景。我个人在实际操作中的体会是Doris 部署的难点从来不在“把容器拉起来”而在网络规划和元数据生命周期管理。网络层面把priority_networks和 hostname 钉死多数集群问题能提前规避一半元数据层面把 FE 的目录挂载和权限处理好重启、迁移、重建都不会慌。另外一个小建议所有个性化配置尽量沉淀成 compose 文件里的环境变量或挂载的 conf 文件不要嫌麻烦登录进容器手动改改完容器一删就全丢。把环境代码化才能做到推倒重来也就一条命令的事。希望这篇内容能帮你少踩几个坑。