ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Windows 上用 Docker Desktop + WSL2 部署 Apache Doris 的完整实践

Windows 上用 Docker Desktop + WSL2 部署 Apache Doris 的完整实践 事情是这样我在 Windows 笔记本上要做一批数据验证正好想评估 Doris 作为分析型数据库到底合不合适。数据量不大但我想完整走一遍建表、导入、聚合查询的流程。一开始我直接下载 Doris 的 Linux 二进制包想在本机跑折腾半天 BE 起不来各种脚本和路径问题接踵而至。后来换了思路用 Docker Desktop 在 WSL2 后端里跑 Linux 容器一套 compose 文件把 FE、BE 拉起来十分钟不到就进可用的状态。这篇文章把我从零到跑通的完整过程写出来包括 Docker Desktop 在 Windows 上起不来的排查思路、Doris 的 FE/BE 容器怎么编排、建表导入怎么验证以及单机跑 Doris 最容易踩的端口和内存坑。如果你也想在 Windows 上快速体验 Doris或者只是想搭个本地验证环境这篇可以直接照着抄。1. 想清楚再动手为什么是Doris Docker Windows这套组合1.1 我到底要解决什么问题Doris准确说 Apache Doris是一个 MPP 架构的分析型数据库。它把节点分成 FEFrontend和 BEBackend两类角色FE 负责 SQL 解析、元数据管理、查询规划和协调BE 负责数据存储和实际计算。对外走的是 MySQL 协议这意味着你可以用现成的 MySQL 客户端连上去团队里会 MySQL 的人基本能无缝上手。存储层面是列式存储典型面向 OLAP 场景比如十几亿行日志的聚合分析、多表 JOIN、明细查询。我当时的场景很明确本地验证 Doris 的明细模型和聚合模型确认分桶策略、Stream Load 导入方式再跑几条常见的 GROUP BY 查询确认表现符合预期后再部署到服务器。这个需求不需要很大的数据量但必须有一个真实的、可操作的 Doris 环境而不是只看文档猜结论。1.2 为什么不在 Windows 上直接跑 Doris 二进制包这是我最开始的方案试过之后才决定放弃。Doris 官方发布的是 Linux 二进制包Windows 上没有现成的启动脚本。FE 是 Java 进程理论上还能跑但 BE 依赖大量 Linux 环境能力比如 mmap、文件描述符限制、shell 脚本执行环境在 Windows 上要么脚本直接报错要么路径里带盘符和反斜杠把配置解析搞崩。我碰到的问题是启动脚本无法执行、日志路径异常、进程崩溃后没有明确报错排起来非常消耗时间。更关键的是Doris 的部署文档、社区讨论、配置默认值全部是围绕 Linux 写的。与其在 Windows 上给 Doris 打补丁不如给它一个完整的 Linux 运行环境。Docker 容器正好干这个事镜像里自带运行环境、目录结构、启动脚本Windows 这边只负责跑容器不需要理解 Doris 内部对系统调用的依赖。1.3 Docker 方案带来的额外好处除了绕开环境兼容问题Docker 方案在日常使用上也更舒服。第一可复现。Docker Compose 文件就是部署文档换一台机器把 compose 文件和 data/log 目录搬过去docker compose up -d就能起同样的环境。第二可销毁。验证完了想清理docker compose down全部删掉不污染 Windows 系统环境也不会在注册表里留一堆东西。第三端口和资源可以随时调整比如 9030 端口被占用改一下映射关系就行不影响容器内部结构。另外我要说一句选型上的考虑。也有人问我为什么不上 ClickHouse毕竟单机场景 ClickHouse 也很能打。我承认 ClickHouse 单节点性能很强但我要验证的方案后续要复用 Doris 的聚合模型、Replace 模型这类功能而且团队里 MySQL 协议接受度更高。既然目标是 Doris本地就用 Doris 验证避免“本地用 A线上用 B”这种验证失真。2. 在 Windows 上把 Docker Desktop 跑通是第一道坎虚拟化与 WSL22.1 安装前先确认三件事很多人卡在 Docker Desktop 启动失败其实不是软件问题是前置条件没满足。Docker Desktop 在 Windows 上默认走 WSL2 后端要求 Windows 10 64 位以上Win11 更稳。装之前先确认三件事。第一BIOS 里的虚拟化必须打开。Intel 平台是 VT-xAMD 平台是 AMD-V。怎么确认打开任务管理器切到“性能”页看“虚拟化”这一项是不是“已启用”。如果显示未启用就得重启进 BIOS在 CPU 配置里找到 Intel Virtualization Technology 或 SVM Mode打开保存退出。第二Windows 功能里要启用“虚拟机平台”和“适用于 Linux 的 Windows 子系统”。最简单的方式是管理员权限运行 PowerShell执行下面两条命令然后重启系统dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart第三WSL2 内核要装好。老系统可能默认 WSL1需要手动升级。管理员 PowerShell 里跑wsl --update wsl --set-default-version 2装完之后用wsl --status可以看当前默认版本确认是 2 再装 Docker Desktop。注意 Windows 10 Home 版没有 Hyper-V但完全不影响WSL2 不依赖 Hyper-V 的图形界面组件Docker Desktop 在 Home 版上照常跑。2.2 Docker Desktop 启动失败的处理路线Docker Desktop 最典型的报错就是这句Docker Desktop failed to start because virtualization support wasnt detected中文环境可能显示“未检测到虚拟化支持”。这个报错信息很误导它不是说你的 CPU 不支持虚拟化而是说 Docker Desktop 没有检测到可用的虚拟化环境。按我排障的顺序来先回任务管理器确认虚拟化是否真的开启。如果显示“已启用”跳第 2 步如果显示“未启用”去 BIOS 开。确认 Windows 功能里“虚拟机平台”和“适用于 Linux 的 Windows 子系统”都勾上了。只装 Docker Desktop 但没开这两个功能是最常见的情况。运行wsl --status看子系统状态。如果有报错提示 WSL 内核太旧跑wsl --update。如果以上都正常打开 Docker Desktop 的 Settings - General确认勾选了Use the WSL 2 based engine然后重启 Docker Desktop。最后一步如果还是起不来退出 Docker Desktop管理员 PowerShell 执行wsl --shutdown把所有 WSL 实例彻底停掉再重新启动 Docker Desktop。我在这步踩过一次坑Windows 功能里子系统已经开了但 WSL 内核版本太老Docker Desktop 卡在启动界面半天日志里反复出现 WSL 初始化失败的记录。执行wsl --update重启后就好了。2.3 WSL2 的资源上限必须主动设置这一步很多人忽略但单机跑 Doris 必须处理。WSL2 默认内存占用策略是取 Windows 物理内存的 50%过去是 80%Doris 的 FE 和 BE 都是吃内存大户如果不限制WSL2 可能把整机的内存吃掉大半Windows 自己开始卡。WSL2 的资源限制通过用户目录下的.wslconfig文件配置。在C:\Users\你的用户名\.wslconfig里写入[wsl2] memory8GB processors4 swap2GB这里的 memory 是 WSL2 虚拟机能用的最大内存不是固定占用的内存。我建议根据你机器实际内存来设16GB 内存设 8GB8GB 内存设 5GB 左右留足够空间给 Windows 自己。改完配置后在 PowerShell 执行wsl --shutdown再重新启动 Docker Desktop配置才会生效。另外提醒一句Doris 的镜像不算小FE、BE 两个镜像加起来可能要下载几个 GB。如果拉镜像速度很慢在 Docker Desktop 的 Settings - Docker Engine 里加一段 registry-mirrors 配置用国内公共镜像加速地址比如{ registry-mirrors: [ https://docker.m.daocloud.io ] }注意这些公共加速地址随时可能变化以能拉下来为准。镜像加速我只在纯本机拉取公共镜像这个场景下讨论不涉及任何其他用途。3. Docker Compose 部署 DorisFE 和 BE 的配置细节与启动流程3.1 镜像选型和目录规划Doris 官方在 Docker Hub 上的仓库是apache/doris镜像 tag 一般按版本切成-fe和-be两个后缀比如我用的apache/doris:2.1.4-fe和apache/doris:2.1.4-be。不同版本的 tag 命名可能略有差异以 Docker Hub 仓库实际展示为准。如果 apache 官方仓库拉取慢或找不到可以试一下selectdb/apache-dorisSelectDB 维护的镜像也提供 FE/BE 双镜像部署参数基本一致。动手前先把目录结构规划好我本地建了这么一套doris-deploy/ ├─ docker-compose.yml ├─ fe/ │ ├─ data/ │ └─ log/ └─ be/ ├─ data/ └─ log/FE 元数据、BE 数据文件都在挂载目录里容器删了数据还在。有一个特别要注意的点我没有挂载 conf 目录。Doris 官方很多示例会建议把 FE、BE 的 conf 目录也挂出来方便改配置。但在 Windows 上这么做风险很大Windows NTFS 文件系统与容器内 Linux 用户权限映射经常出问题容器内 doris 用户写日志时遇到 Permission deniedBE 直接起不来。所以我用最省事的方案只挂 data 和 log配置改动用容器内操作完成后面第 5 节详细讲。3.2 compose 文件实际写法直接在doris-deploy目录下创建docker-compose.ymlservices: fe: image: apache/doris:2.1.4-fe container_name: doris-fe hostname: doris-fe environment: FE_MASTER: true ports: - 8030:8030 - 9010:9010 - 9030:9030 volumes: - ./fe/data:/opt/apache-doris/fe/data - ./fe/log:/opt/apache-doris/fe/log networks: - doris-net be: image: apache/doris:2.1.4-be container_name: doris-be hostname: doris-be environment: FE_MASTER: true ports: - 8040:8040 - 9050:9050 - 9060:9060 - 9070:9070 volumes: - ./be/data:/opt/apache-doris/be/data - ./be/log:/opt/apache-doris/be/log depends_on: - fe networks: - doris-net networks: doris-net: driver: bridge这里有几个关键点要解释清楚。FE 暴露了三个端口8030 是 Web UI 和 Stream Load 的 HTTP 端口9030 是 MySQL 协议端口客户端连这个9010 是 FE 之间选举和元数据同步用的 RPC 端口。BE 暴露的端口稍微多些9050 是 BE 向 FE 上报心跳的端口8040 是 BE 的 HTTP 服务端口9060 是 BE 的 Thrift RPC 端口9070 是 BE 的 BRPC 端口。单机部署时这些端口都映射出来方便排查问题。网络层面我用了自定义 bridge 网络doris-net而不是默认网络。自定义网络的好处是 Docker 内置 DNS 解析FE 容器里可以直接通过服务名be解析到 BE 容器的 IP。如果用默认网络容器间只能靠 IP 通信容器重建后 IP 会变后面注册 BE 的地址会失效维护起来很恼火。depends_on只能保证 BE 容器在 FE 容器之后创建不能保证 FE 元数据已经初始化完。所以启动后不要急着加 BE先确认 FE 真起来了再说。3.3 启动、注册 BE、检查状态先启动服务docker compose up -d然后观察 FE 日志等 FE 完成初始化docker logs -f doris-fe看到 FE 进程正常监听端口的记录后打开浏览器访问http://127.0.0.1:8030能出现 Doris 的 Web 登录页就说明 FE 已经活了。接下来用 MySQL 客户端连 FEmysql -h 127.0.0.1 -P 9030 -uroot如果你电脑上没装 MySQL 客户端也不用急FE 镜像自带了 mysql 客户端直接进容器执行docker exec -it doris-fe bash -c mysql -uroot -P9030默认 root 密码为空直接回车就能进去。执行下面这条命令注册 BE 节点ALTER SYSTEM ADD BACKEND doris-be:9050;这里必须用doris-be:9050而不是localhost:9050或127.0.0.1:9050。原因很简单执行这条 SQL 的是 FE 容器FE 容器里的localhost指向它自己它去localhost:9050找 BE 当然找不到BE 就会一直显示 offline。用doris-be:9050FE 通过 docker 网络解析到真实的 BE 容器地址心跳才能建立起来。注册完后执行SHOW BACKENDS;看结果里的Aliveness字段是否为 trueStatus是否正常。如果 Aliveness 是 false多半就是地址写错了用ALTER SYSTEM DROP BACKEND 错误地址:9050删掉再重新加。这一步过了Doris 集群就算真正跑起来了。4. 建库导入查数顺带把几 MB 数据要不要分桶说透4.1 MySQL 协议连上 FE建一张测试表Doris 对外是 MySQL 协议所以建库建表的习惯和 MySQL 很像。连上 FE 之后我建了一个测试库和一张日志表CREATE DATABASE demo; USE demo; CREATE TABLE event_log ( day DATE, user_id INT, event VARCHAR(32), cnt INT ) DUPLICATE KEY(day, user_id) DISTRIBUTED BY HASH(user_id) BUCKETS 1 PROPERTIES (replication_num 1);DUPLICATE KEY表示明细模型适合日志类数据相同 key 可以多行存在不丢数据。DISTRIBUTED BY HASH(user_id) BUCKETS 1是数据分布策略按 user_id 的哈希值分散到 1 个桶里。replication_num设为 1因为当前只有一个 BE副本数大于 1 也没有别的节点可以放。4.2 只有几 MB 数据到底要不要分桶这是实际使用 Doris 时很多人纠结的问题包括我自己。先说结论如果数据只有几 MB甚至几十 MB分桶数直接设 1 就行不需要为了“看起来标准”去分 16 个或 32 个桶。为什么Doris 里一个 bucket 对应一个 tablettablet 是数据管理和调度的最小单位。几 MB 的数据如果分成 32 个桶每个桶里只有几百 KB结果就是元数据膨胀、导入时产生大量小文件、查询时 Doris 要分别调度 32 个 tablet 再合并结果纯属给自己加负担。数据量小到一定程度一个桶反而最快最干净。但也要考虑一件事后期扩容。Doris 新增 BE 节点后负载均衡会把已有的 tablet 在多个 BE 之间搬迁。如果你的表只有 1 个桶哪怕以后扩到 3 个 BE这张表的数据也只会落在 1 个 BE 上多节点并行能力完全用不上。所以如果预判数据量以后会涨到 GB 级初始 bucket 数建议至少设成未来 BE 数量的倍数比如预计 3 台 BE就设 6 或 9 个桶。如果你只是本地验证今天用完明天可能就删了BUCKETS 1 就是最优解。顺便提一句Doris 导入时对单表 tablet 数量有默认上限限制如果某张表非要建 1000 个桶可能报max_tablet_num_per_table超限。小数据场景完全不需要碰这个参数真碰到了先想想是不是桶建多了。4.3 导入数据和查询验证建完表先插几条数据做冒烟测试INSERT INTO event_log VALUES (2025-01-01, 1, click, 3), (2025-01-01, 2, view, 1), (2025-01-02, 1, click, 2), (2025-01-02, 3, view, 5);然后跑一条聚合查询SELECT day, COUNT(*) AS pv, SUM(cnt) AS total_cnt FROM event_log GROUP BY day ORDER BY day;能正常返回分组结果说明 FE、BE 和存储链路都是通的。如果只想验证功能到这一步就够了。不过 Doris 的日常导入很少用 INSERT更常用 Stream Load这里也演示一下。准备一个event_log.csv文件内容就是带表头的逗号分隔数据然后执行curl.exe -X PUT -u root: \ -H Expect: 100-continue \ -H ColumnSeparator: , \ -T event_log.csv \ http://127.0.0.1:8030/api/demo/event_log/_stream_load这里的127.0.0.1:8030是 FE 的 HTTP 端口/api/demo/event_log/_stream_load路径里的 demo 是库名event_log 是表名。-u root:表示用户名 root、密码为空。返回的 JSON 里看Status字段是否为Success如果是Publish Timeout通常数据已经写入成功只是事务确认超时可以查表确认如果是Label Already Exists说明这个导入 label 之前用过了需要换 label 或者清掉旧的。导入完成后再用 4.1 的 SELECT 查一遍确认聚合结果和预期一致。整个验证流程到这里就闭环了。5. Windows 本机运行的坑端口冲突、内存限制与容器重启5.1 端口被占用的定位和解决Doris 用的端口很多最常见的是 9030 和 8030 被占用。Windows 上 MySQL 如果之前装过9030 被 MySQL 占掉的情况非常多8030 也可能被其他 Web 服务占用。我的排查习惯是两步走。先用 netstat 看端口对应进程netstat -ano | findstr 9030回显里最后一列是 PID。再用 tasklist 查这个 PID 是哪个程序tasklist /FI PID eq 12345如果确认是多余进程可以在任务管理器里结束它或者命令行taskkill /F /PID 12345。如果你不想动现有进程更安全的方法是改 compose 文件里的端口映射把宿主机端口换掉容器内部端口不变。比如ports: - 9031:9030这样外部访问就用-h 127.0.0.1 -P 9031。改完执行docker compose up -d重建对应容器Doris 内部元数据不受影响。这个思路同样适用于 8030 被占用的情况。5.2 FE/BE 内存设置不调会 OOM这是 Windows 单机跑 Doris 最隐蔽的一个坑。Doris 默认参数是按服务器设计的在 Windows WSL2 环境里内存是共享的FE 是 Java 进程默认堆可能给到 8GBBE 的mem_limit默认按物理内存的 80% 算如果 WSL2 没限制Docker Desktop 就会疯狂吃内存然后 Windows 开始卡随后容器被 OOM Kill。我的处理思路是把 FE 和 BE 的内存都压到适合小内存机器。进入 BE 容器docker exec -it doris-be bash sed -i s/^mem_limit.*/mem_limit 4GB/ conf/be.conf然后进入 FE 容器调整 Java 堆docker exec -it doris-fe bash sed -i s/^JAVA_OPTS.*/JAVA_OPTS-Xmx2048m -Xms2048m/ conf/fe.conf如果 sed 命令在容器里不好用也可以用docker cp把配置文件拷出来编辑再拷回去。改完分别重启容器docker restart doris-fe docker restart doris-be注意一个细节因为我们没有挂载 conf 目录改的配置是写在容器可写层的只要容器不删除配置就一直在。一旦docker compose down再up容器会重建这些改动就丢了。一个简单的备份方法是把改好的两个 conf 文件用docker cp拉到宿主机保存下次重建后再传回去。还有一个思路如果镜像本身支持环境变量传配置可以优先用环境变量。但不同版本支持情况不一致我为了统一直接用改 conf 文件的方式效果最确定。5.3 重启电脑后 Doris 如何自动恢复本地验证环境的另一个问题是 Windows 经常要重启每次手动起容器很烦。我做了两个设置之后就省事了。第一步Docker Desktop 的 Settings 里勾选Start Docker Desktop when you sign in让 Windows 登录后 Docker Desktop 自动启动。第二步给 compose 文件里的服务加上自动重启策略services: fe: restart: unless-stopped be: restart: unless-stopped之后 Windows 重启Docker Desktop 起来WSL2 里的容器会按重启策略自动拉起。由于 FE 的元数据存储在挂载目录里BE 也可以重新向 FE 注册集群基本能恢复到之前的状态。如果重启后发现SHOW BACKENDS里 BE 短暂 offline等几十秒再查一次或者手动docker restart doris-be触发重连这是正常的启动时序问题不是集群坏了。最后分享一个使用习惯日常验证完数据不需要容器在后台跑的时候用docker compose stop停掉而不是docker compose down。stop 只停止容器再docker compose start就能继续用数据目录和容器配置都保留down 会把容器删掉下次 up 是全新创建。对于本地频繁开关机的验证环境stop 显然更合适。这套组合我用了挺长一段时间整体稳定唯一的建议就是先保证 WSL2 稳定再谈 Doris 的配置优化。
返回列表