在数据仓库和实时分析领域,Apache Doris 凭借其高性能、易用性和实时性,成为了许多开发者和企业的热门选择。然而,传统的物理机或虚拟机部署方式往往涉及繁琐的环境配置、依赖安装和集群管理,对新手和运维都构成了不小的挑战。本文将为你带来一套基于 Docker 的 Doris 部署“保姆级”教程,从核心概念到一键启动,从基础连接到生产级配置,手把手带你绕过所有常见坑点。无论你是想快速搭建一个测试环境,还是为生产部署寻找更高效的方案,这篇教程都能提供完整的代码示例和清晰的排错思路,确保你能成功部署并运行起自己的 Doris 服务。

1. 背景与核心概念:为什么选择 Docker 部署 Doris?

在深入部署步骤之前,我们有必要理解两个核心组件:Doris 和 Docker,以及它们结合带来的优势。

Apache Doris 是一个现代化的、高性能的、实时的分析型数据库(MPP)。它最初由百度开发并开源,旨在提供毫秒级的查询响应能力,支持高并发的点查询和复杂的 Ad-Hoc 查询。Doris 的架构主要包含两个角色:

  • Frontend (FE) :负责元数据管理、集群调度、接收和解析用户请求。一个 Doris 集群可以有多个 FE 组成高可用集群,其中一个是 Leader。
  • Backend (BE) :负责数据存储和计算。数据表被水平划分为多个 Tablet(数据分片),分布式地存储在多个 BE 节点上,查询时也由多个 BE 并行计算。

传统的部署方式需要你在每台机器上手动安装 Java 运行环境,配置系统参数,并逐个启动 FE 和 BE 进程。这个过程不仅耗时,而且环境差异极易导致部署失败。

Docker 是一个开源的应用容器引擎,它允许开发者将应用及其依赖打包到一个轻量级、可移植的容器中。使用 Docker 部署 Doris 带来了革命性的便利:

  1. 环境隔离与一致性 :Docker 镜像包含了运行 Doris 所需的所有依赖(如特定版本的 Java),彻底解决了“在我机器上能跑”的环境问题。无论是在 Ubuntu、CentOS 还是 macOS 上,只要运行同一个镜像,表现完全一致。
  2. 快速部署与扩展 :通过 docker run 命令,可以在几秒钟内启动一个 Doris 节点。扩缩容集群变得异常简单,只需要增加或减少容器实例即可。
  3. 资源隔离与高效利用 :可以方便地为每个容器(FE/BE)分配特定的 CPU 和内存资源,避免进程间相互影响,也更容易管理资源。
  4. 简化运维与升级 :版本升级或回滚,只需替换镜像标签并重启容器。整个集群的配置和状态可以通过 Docker Compose 或 Kubernetes 进行声明式管理。

因此,对于学习、测试、乃至中小型生产环境,使用 Docker 部署 Doris 都是一个极具性价比和效率的选择。接下来,我们将从零开始,完成整个部署过程。

2. 环境准备与版本说明

在开始之前,请确保你的操作环境满足以下基本要求。本文将在一个 Linux 环境中进行演示,但 Docker 的特性使得其在 Windows 和 macOS 上同样可行,只需注意路径等细微差别。

基础环境要求:

  • 操作系统 :Linux (Ubuntu 20.04/22.04, CentOS 7/8 等)、macOS 或 Windows 10/11 (需安装 WSL2)。
  • Docker 引擎 :版本 20.10.0 或更高。这是运行容器的核心。
  • Docker Compose :版本 v2.0.0 或更高。用于编排多容器应用(集群部署时强烈推荐)。
  • 可用资源 :建议为 Docker 分配至少 4GB 内存和 2核 CPU。运行一个完整的 Doris 集群(1 FE + 1 BE)至少需要 2GB 内存。

本文使用的软件版本:

  • Docker Engine : 24.0.6
  • Docker Compose : v2.20.2
  • Apache Doris : 官方镜像 apache/doris:2.0.4 (此版本是一个长期支持版本,稳定且功能丰富)
  • MySQL Client : 8.0 (用于连接 Doris,因为 Doris 兼容 MySQL 协议)

安装 Docker 与 Docker Compose (如未安装): 如果你的系统尚未安装 Docker,可以参照以下命令进行安装(以 Ubuntu 22.04 为例):

# 1. 卸载旧版本
sudo apt-get remove docker docker-engine docker.io containerd runc

# 2. 安装依赖包
sudo apt-get update
sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

# 3. 添加 Docker 官方 GPG 密钥
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# 4. 设置稳定版仓库
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 5. 安装 Docker Engine
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

# 6. 验证安装
sudo docker run hello-world

# 7. (可选) 将当前用户加入 docker 组,避免每次使用 sudo
sudo usermod -aG docker $USER
# 执行此命令后,需要**注销并重新登录**或重启系统生效。

对于 Docker Compose,如果你安装的是 docker-compose-plugin (如上所述),那么命令是 docker compose 。如果你需要独立的 docker-compose ,可以单独安装。

3. 单机快速体验:启动一个 All-in-One 的 Doris

对于初次接触或快速功能验证,Apache Doris 社区提供了一个 All-in-One 的 Docker 镜像,它将 FE 和 BE 打包在同一个容器中,非常适合快速启动和测试。

操作步骤:

  1. 拉取 Doris 镜像 从 Docker Hub 拉取官方镜像。这里我们选择 2.0.4 版本。

    docker pull apache/doris:2.0.4
    
  2. 启动 All-in-One 容器 使用 docker run 命令启动容器。我们需要映射几个关键端口:

    • 8030 : FE 的 HTTP 端口(用于 Web UI 和某些 API)。
    • 9030 : FE 的 MySQL 协议端口(用于客户端如 MySQL CLI, JDBC 连接)。
    • 8040 : BE 的 HTTP 端口。 同时,我们给容器起一个有意义的名字,比如 doris-quickstart
    docker run -d \
      --name doris-quickstart \
      -p 8030:8030 \
      -p 9030:9030 \
      -p 8040:8040 \
      apache/doris:2.0.4
    

    参数解释:

    • -d : 后台运行容器。
    • --name : 指定容器名称。
    • -p host_port:container_port : 将容器内部端口映射到宿主机端口。
  3. 检查容器状态 使用 docker ps 命令查看容器是否正常运行。

    docker ps | grep doris-quickstart
    

    你应该能看到容器状态为 Up

  4. 连接 Doris 数据库 容器启动后,FE 需要一些时间(约30秒到1分钟)来完成初始化。之后,你就可以使用任何兼容 MySQL 协议的客户端进行连接。

    • 使用 MySQL 命令行客户端连接:
      # 假设你的 MySQL 客户端已安装
      mysql -h 127.0.0.1 -P 9030 -uroot
      
      默认情况下,All-in-One 镜像的 root 用户密码为空,直接回车即可。
    • 连接成功后,执行一个测试 SQL:
      SHOW FRONTENDS;
      
      你会看到 FE 节点的信息,状态应为 Alive
      SHOW BACKENDS;
      
      你会看到 BE 节点的信息,状态也应为 Alive
  5. 访问 Web UI 在浏览器中打开 http://<你的服务器IP>:8030 ,你将看到 Doris 的简易 Web 界面,可以查看系统状态和进行一些基本操作。

至此,一个单机版的 Doris 已经成功运行! 你可以在这个环境里创建数据库、表,导入数据并进行查询。这对于功能学习和小数据量测试已经完全足够。

4. 生产级部署:使用 Docker Compose 编排 Doris 集群

All-in-One 模式虽简单,但不适合生产环境。生产环境需要 FE 和 BE 分离部署,并且通常要求 FE 构成高可用集群(至少1个 Follower,1个 Observer),BE 可以横向扩展。使用 Docker Compose 可以轻松定义和管理这样一个多容器的集群。

4.1 规划集群结构与目录

我们规划一个最小化的生产可用集群:

  • FE 节点 :3个,角色分别为 1 Leader (master), 1 Follower (slave), 1 Observer。
  • BE 节点 :2个,用于数据存储和计算。

在宿主机上创建一个工作目录,例如 ~/doris-cluster ,并在其中创建必要的子目录和配置文件。

mkdir -p ~/doris-cluster/{fe-master,fe-slave,fe-observer,be1,be2,logs}
cd ~/doris-cluster

4.2 编写 Docker Compose 配置文件

创建 docker-compose.yml 文件,这是定义整个集群的核心。

version: '3.8'

services:
  # ------------------- Frontend Services -------------------
  fe-master:
    image: apache/doris:2.0.4-fe
    container_name: doris-fe-master
    hostname: fe-master # 容器主机名,用于集群内部通信
    environment:
      - FE_SERVERS=fe-master:9010,fe-slave:9010,fe-observer:9010
      - FE_ID=1 # FE 的唯一 ID,集群内不能重复
    volumes:
      - ./fe-master/doris-meta:/opt/apache-doris/fe/doris-meta # 元数据持久化
      - ./fe-master/conf:/opt/apache-doris/fe/conf # 自定义配置
      - ./logs/fe-master:/opt/apache-doris/fe/log # 日志持久化
    ports:
      - "8030:8030" # Web UI & API
      - "9020:9020" # FE Thrift Server
      - "9030:9030" # MySQL Protocol
    networks:
      - doris-net
    command: 
      - /bin/bash
      - -c
      - |
        # 等待容器内网络就绪,然后启动 FE
        sleep 5;
        /opt/apache-doris/fe/bin/start_fe.sh --helper fe-master:9010 --daemon
        tail -f /opt/apache-doris/fe/log/fe.out

  fe-slave:
    image: apache/doris:2.0.4-fe
    container_name: doris-fe-slave
    hostname: fe-slave
    environment:
      - FE_SERVERS=fe-master:9010,fe-slave:9010,fe-observer:9010
      - FE_ID=2
    volumes:
      - ./fe-slave/doris-meta:/opt/apache-doris/fe/doris-meta
      - ./fe-slave/conf:/opt/apache-doris/fe/conf
      - ./logs/fe-slave:/opt/apache-doris/fe/log
    ports:
      - "8031:8030"
      - "9031:9030"
    networks:
      - doris-net
    depends_on:
      - fe-master
    command: 
      - /bin/bash
      - -c
      - |
        sleep 10; # 等待 master 先启动
        /opt/apache-doris/fe/bin/start_fe.sh --helper fe-master:9010 --daemon
        tail -f /opt/apache-doris/fe/log/fe.out

  fe-observer:
    image: apache/doris:2.0.4-fe
    container_name: doris-fe-observer
    hostname: fe-observer
    environment:
      - FE_SERVERS=fe-master:9010,fe-slave:9010,fe-observer:9010
      - FE_ID=3
    volumes:
      - ./fe-observer/doris-meta:/opt/apache-doris/fe/doris-meta
      - ./fe-observer/conf:/opt/apache-doris/fe/conf
      - ./logs/fe-observer:/opt/apache-doris/fe/log
    ports:
      - "8032:8030"
      - "9032:9030"
    networks:
      - doris-net
    depends_on:
      - fe-master
      - fe-slave
    command: 
      - /bin/bash
      - -c
      - |
        sleep 15;
        /opt/apache-doris/fe/bin/start_fe.sh --observer --helper fe-master:9010 --daemon
        tail -f /opt/apache-doris/fe/log/fe.out

  # ------------------- Backend Services -------------------
  be1:
    image: apache/doris:2.0.4-be
    container_name: doris-be1
    hostname: be1
    environment:
      - FE_SERVERS=fe-master:9010,fe-slave:9010,fe-observer:9010
      - BE_ADDR=be1:9050
    volumes:
      - ./be1/storage:/opt/apache-doris/be/storage # 数据存储持久化
      - ./be1/conf:/opt/apache-doris/be/conf
      - ./logs/be1:/opt/apache-doris/be/log
    networks:
      - doris-net
    depends_on:
      - fe-master
      - fe-slave
    command: 
      - /bin/bash
      - -c
      - |
        sleep 20;
        /opt/apache-doris/be/bin/start_be.sh --daemon
        tail -f /opt/apache-doris/be/log/be.out

  be2:
    image: apache/doris:2.0.4-be
    container_name: doris-be2
    hostname: be2
    environment:
      - FE_SERVERS=fe-master:9010,fe-slave:9010,fe-observer:9010
      - BE_ADDR=be2:9050
    volumes:
      - ./be2/storage:/opt/apache-doris/be/storage
      - ./be2/conf:/opt/apache-doris/be/conf
      - ./logs/be2:/opt/apache-doris/be/log
    networks:
      - doris-net
    depends_on:
      - fe-master
      - fe-slave
    command: 
      - /bin/bash
      - -c
      - |
        sleep 25;
        /opt/apache-doris/be/bin/start_be.sh --daemon
        tail -f /opt/apache-doris/be/log/be.out

networks:
  doris-net:
    driver: bridge
    name: doris-cluster-network

配置文件关键点解析:

  1. 镜像分离 :使用了 apache/doris:2.0.4-fe apache/doris:2.0.4-be 两个独立镜像,而非 All-in-One 镜像,更符合生产部署逻辑。
  2. 环境变量
    • FE_SERVERS :所有 FE 节点的地址列表,用于集群发现。
    • FE_ID :每个 FE 的唯一标识,必须不同。
    • BE_ADDR :BE 自身的地址,用于向 FE 注册。
  3. 数据持久化 :通过 volumes 将容器内的元数据 ( doris-meta )、数据 ( storage ) 和日志 ( log ) 目录挂载到宿主机。 这是最重要的部分 ,确保了容器重启或删除后数据不丢失。
  4. 端口映射 :为每个服务映射了不同的宿主机端口,避免冲突。例如,FE Master 的 MySQL 端口是 9030,FE Slave 的是 9031。
  5. 启动顺序与依赖 :使用 depends_on sleep 命令确保 FE Master 先启动,其他节点再依次加入。生产环境中可能需要更健壮的健康检查机制。
  6. 网络 :所有服务加入同一个自定义网络 doris-net ,使得容器间可以通过容器名 ( hostname ) 直接通信。

4.3 准备自定义配置文件(可选但推荐)

Doris 的默认配置可能不适合所有场景。我们可以通过挂载卷的方式覆盖默认配置。例如,调整 FE 的 Java 堆内存。

~/doris-cluster/fe-master/conf/ 目录下创建 fe.conf 文件:

# fe-master/conf/fe.conf
# 设置 JVM 堆内存大小,根据机器资源调整
JAVA_OPTS = -Xmx4096m -Xms4096m -XX:+UseG1GC

# 其他自定义参数,例如日志级别
# sys_log_level = INFO

同理,可以为 BE 创建配置文件 be.conf 在对应目录:

# be1/conf/be.conf
# 设置 BE 的 JVM 堆内存
JAVA_OPTS = -Xmx8192m -Xms8192m -XX:+UseG1GC

# 设置存储路径,此路径对应容器内路径,已在 volumes 中挂载
# storage_root_path = /opt/apache-doris/be/storage

4.4 启动 Doris 集群

docker-compose.yml 文件所在目录执行以下命令:

# 拉取所需的 FE 和 BE 镜像
docker compose pull

# 启动所有服务(在后台运行)
docker compose up -d

# 查看所有容器状态
docker compose ps

如果一切正常,你会看到所有容器的状态都是 Up 。启动过程可能需要几分钟,因为 FE 和 BE 需要进行初始化。

4.5 初始化与验证集群

  1. 连接 FE Master 并添加其他 FE 节点 虽然我们在 docker-compose.yml 中通过 --helper 参数指定了主 FE,但首次启动时,其他 FE 节点需要被“添加”到集群中。

    # 连接到 FE Master
    mysql -h 127.0.0.1 -P 9030 -uroot
    

    在 MySQL 客户端中执行:

    -- 查看当前 FE 节点,应该只有 fe-master
    SHOW FRONTENDS;
    
    -- 添加 FE Follower (fe-slave)
    ALTER SYSTEM ADD FOLLOWER "fe-slave:9010";
    
    -- 添加 FE Observer (fe-observer)
    ALTER SYSTEM ADD OBSERVER "fe-observer:9010";
    
    -- 再次查看,应该能看到三个 FE,其中 fe-master 是 Leader
    SHOW FRONTENDS;
    

    确保所有 FE 的 Alive 列为 true

  2. 添加 BE 节点

    -- 添加第一个 BE 节点
    ALTER SYSTEM ADD BACKEND "be1:9050";
    -- 添加第二个 BE 节点
    ALTER SYSTEM ADD BACKEND "be2:9050";
    
    -- 查看 BE 状态
    SHOW BACKENDS;
    

    等待几分钟,直到所有 BE 的 Alive 列变为 true ,并且 SystemDecommissioned 列为 false

  3. 进行简单测试

    -- 创建一个测试数据库
    CREATE DATABASE test_db;
    USE test_db;
    
    -- 创建一张测试表
    CREATE TABLE test_table (
        id INT,
        name VARCHAR(50),
        dt DATE
    )
    DISTRIBUTED BY HASH(id) BUCKETS 10
    PROPERTIES("replication_num" = "2"); -- 副本数为2,会在两个BE上存储
    
    -- 插入测试数据
    INSERT INTO test_table VALUES 
    (1, 'Alice', '2023-10-01'),
    (2, 'Bob', '2023-10-02');
    
    -- 查询数据
    SELECT * FROM test_table;
    

    如果查询成功返回数据,恭喜你,一个高可用的 Doris 生产集群已经部署完成!

5. 常见问题与排查思路

在部署和运行过程中,你可能会遇到一些问题。以下是常见问题的排查指南。

问题现象 可能原因 排查步骤与解决方案
容器启动后立即退出 1. 端口冲突。
2. 挂载的宿主机目录权限不足。
3. 镜像拉取不完整或损坏。
1. docker compose logs <service_name> 查看具体错误日志。
2. docker ps -a 查看已退出容器的状态码。
3. 检查 docker-compose.yml 中端口是否被占用 ( netstat -tlnp | grep <port> )。
4. 确保宿主机挂载目录存在且 Docker 进程有读写权限 ( ls -la 查看)。
5. 尝试删除镜像并重新拉取 ( docker rmi , docker compose pull )。
FE/BE 节点 Alive 状态为 false 1. 节点进程未成功启动。
2. 网络不通,无法进行心跳汇报。
3. 时钟不同步。
1. 进入对应容器查看进程: docker exec -it <container_name> bash 然后 ps aux | grep doris
2. 查看对应节点的日志文件: cat /opt/apache-doris/fe/log/fe.warn.log be.warn.log
3. 检查容器间网络:在容器内 ping 其他容器的 hostname。
4. 确保所有容器时间同步,Docker 容器默认使用宿主机时间。
SHOW BACKENDS 显示 LastStartTime 错误 BE 节点启动失败或注册失败。 1. 检查 BE 日志,常见错误是 storage_root_path 配置错误或权限问题。
2. 确认 ALTER SYSTEM ADD BACKEND 语句中的 IP 和端口是否正确(应是容器名和 9050 )。
3. 尝试删除并重新添加 BE: ALTER SYSTEM DROP BACKEND “be1:9050”; 然后重新添加。
客户端无法连接 9030 端口 1. 防火墙或安全组规则阻止。
2. FE 进程未监听端口。
3. 连接地址错误。
1. 在宿主机上检查端口监听: ss -tlnp | grep 9030
2. 进入 FE 容器检查 FE 进程是否运行,并检查 fe.conf query_port 配置。
3. 确认连接命令中的主机 IP 是否正确。如果是远程连接,需确保 FE 容器映射到了宿主机的正确 IP ( 0.0.0.0 )。
数据插入或查询非常慢 1. BE 节点资源(CPU/内存)不足。
2. 数据分布不均或副本数设置不合理。
3. 未正确建立索引。
1. 使用 docker stats 查看容器资源使用情况。
2. 检查表的分桶键和分区键设计是否合理。
3. 对于查询条件列,考虑创建 Rollup 索引或 Bloom Filter 索引。
4. 通过 SHOW PROC ‘/backends’; 查看 BE 节点负载。
磁盘空间不足 数据量增长过快,或日志文件未清理。 1. 清理过期数据:使用 DROP TABLE 或分区删除 ALTER TABLE … DROP PARTITION …
2. 设置数据生命周期 (TTL)。
3. 定期清理 FE/BE 的旧日志文件(挂载到宿主机的日志目录)。
4. 为 BE 的 storage_root_path 挂载更大容量的磁盘。

通用排查命令:

  • docker compose logs -f <service_name> :实时查看某个服务的日志输出。
  • docker exec -it <container_name> bash :进入容器内部进行调试。
  • mysql -h 127.0.0.1 -P 9030 -uroot -e “SHOW PROC ‘/frontends’;” :不进入交互模式,直接执行 SQL 查看状态。

6. 最佳实践与工程建议

将 Docker 化 Doris 用于生产环境,除了基本的部署,还需要考虑稳定性、可维护性和性能。

  1. 资源限制与监控

    • docker-compose.yml 中为每个服务设置资源限制,防止某个容器耗尽宿主机资源。
      services:
        fe-master:
          # ...
          deploy:
            resources:
              limits:
                cpus: '2'
                memory: 4G
              reservations:
                memory: 2G
      
    • 集成监控系统(如 Prometheus + Grafana)。Doris 提供了丰富的 Metrics 接口(FE: 8030/metrics , BE: 8040/metrics ),可以方便地监控集群健康度、查询性能、资源使用等。
  2. 数据持久化与备份

    • 务必 doris-meta (FE元数据) 和 storage (BE数据) 目录通过 volumes 持久化到可靠的存储(如 SSD 云盘、网络存储)。
    • 定期备份 FE 的元数据。可以编写脚本,定期将 doris-meta 目录打包并上传到对象存储。
    • 对于重要数据,考虑使用 Doris 的备份恢复功能 ( BACKUP / RESTORE 语句) 到其他存储系统。
  3. 高可用与故障恢复

    • FE 集群至少部署 1 Leader + 1 Follower,可以容忍一个节点故障。Observer 节点可以承担读负载。
    • BE 的副本数 ( replication_num ) 建议设置为 3(如果 BE 节点数>=3),提供数据高可用。
    • 规划好容器的重启策略:在 docker-compose.yml 中配置 restart: unless-stopped restart: always ,使容器在异常退出时自动重启。
  4. 配置优化

    • JVM 参数 :根据机器内存调整 JAVA_OPTS 。FE 通常 4-8GB,BE 需要更多,通常 8-16GB 或更高,并留出足够内存给操作系统和其他进程。
    • BE 配置 :调整 be.conf 中的 storage_root_path 到高性能磁盘路径;根据 CPU 核数调整 brpc_io_threads brpc_worker_threads
    • FE 配置 :调整 fe.conf 中的 qe_max_connection (最大连接数)和 tablet_create_timeout_second (建表超时)。
  5. 安全考虑

    • 修改默认的 root 用户密码: SET PASSWORD FOR ‘root’ = PASSWORD(‘your_strong_password’);
    • 避免将 FE 的 9030 8030 端口直接暴露在公网。应通过跳板机、VPN 或应用内网访问。
    • 定期更新 Doris 镜像版本,以获取安全补丁和新功能。
  6. 使用更高级的编排工具

    • 对于大规模的、动态的集群,可以考虑使用 Kubernetes (K8s) 替代 Docker Compose。社区提供了 Doris 的 Helm Chart 或 Operator,可以更方便地管理集群生命周期、自动扩缩容和故障转移。

通过以上步骤,你不仅能够成功部署 Doris,更能构建一个稳定、高效、易于维护的实时分析数据库环境。Docker 化部署大大降低了运维复杂度,让你能更专注于业务逻辑和数据价值的挖掘。

更多推荐