Flink 2.2 Docker 部署Session / Application / SQL Client 一把梭(含 Compose、插件、连接器与踩坑点)

1. 先搞清楚:Docker 里跑 Flink,你到底在跑什么

Flink 的官方镜像本质上就是一个标准 Flink 发行版 + 入口脚本。你可以用它启动三种角色:

  • JobManager(Session 集群)
  • JobManager(Application 集群,standalone-job
  • TaskManager(给任意集群用)

核心差别只在于:你是先起集群再提交作业(Session),还是"集群=作业"(Application)。

2. 最快启动:手动 docker run 启一个 Session 集群

2.1 创建网络 + 指定 JobManager RPC 地址

JobManager 和 TaskManager 要互相发现,所以必须设置 jobmanager.rpc.address,并且建议放进同一个 Docker network。

bash 复制代码
FLINK_PROPERTIES="jobmanager.rpc.address: jobmanager"
docker network create flink-network

2.2 启 JobManager(带 Web UI)

bash 复制代码
docker run \
  --rm \
  --name=jobmanager \
  --network flink-network \
  --publish 8081:8081 \
  --env FLINK_PROPERTIES="${FLINK_PROPERTIES}" \
  flink:2.2.0-scala_2.12 jobmanager

2.3 启 TaskManager(可多个)

bash 复制代码
docker run \
  --rm \
  --name=taskmanager \
  --network flink-network \
  --env FLINK_PROPERTIES="${FLINK_PROPERTIES}" \
  flink:2.2.0-scala_2.12 taskmanager
bash 复制代码
./bin/flink run ./examples/streaming/TopSpeedWindowing.jar

访问 Web UI:http://localhost:8081

停止集群:直接 Ctrl+C 或 docker stop jobmanager taskmanager

3. 推荐方式:Docker Compose 一键起 Session / Application / SQL Client

Compose 的优势是:配置集中、扩缩容方便、可复制到其他机器。

3.1 Session Mode(最常用)

docker-compose.yml 示例:

yaml 复制代码
version: "2.2"
services:
  jobmanager:
    image: flink:2.2.0-scala_2.12
    ports:
      - "8081:8081"
    command: jobmanager
    environment:
      - |
        FLINK_PROPERTIES=
        jobmanager.rpc.address: jobmanager

  taskmanager:
    image: flink:2.2.0-scala_2.12
    depends_on:
      - jobmanager
    command: taskmanager
    scale: 1
    environment:
      - |
        FLINK_PROPERTIES=
        jobmanager.rpc.address: jobmanager
        taskmanager.numberOfTaskSlots: 2

启动:

bash 复制代码
docker compose up

扩容 TaskManager(两种写法二选一):

bash 复制代码
docker compose scale taskmanager=3
# 或者新版本:docker compose up --scale taskmanager=3

关闭:

bash 复制代码
docker compose down

3.2 SQL Client + Session 集群(本地写 SQL 最爽的组合)

yaml 复制代码
version: "2.2"
services:
  jobmanager:
    image: flink:2.2.0-scala_2.12
    ports:
      - "8081:8081"
    command: jobmanager
    environment:
      - |
        FLINK_PROPERTIES=
        jobmanager.rpc.address: jobmanager

  taskmanager:
    image: flink:2.2.0-scala_2.12
    depends_on:
      - jobmanager
    command: taskmanager
    scale: 1
    environment:
      - |
        FLINK_PROPERTIES=
        jobmanager.rpc.address: jobmanager
        taskmanager.numberOfTaskSlots: 2

  sql-client:
    image: flink:2.2.0-scala_2.12
    command: bin/sql-client.sh
    depends_on:
      - jobmanager
    environment:
      - |
        FLINK_PROPERTIES=
        jobmanager.rpc.address: jobmanager
        rest.address: jobmanager

启动集群后进入 SQL Client:

bash 复制代码
docker compose run sql-client

重要提醒:SQL Client 只是"提交端",真正跑算子的还是 JM/TM。你用到的连接器依赖必须在集群侧也可见(见第 5 节)。

3.3 Application Mode(一个应用一个集群,隔离更强)

Application Mode 的关键点:作业 JAR 必须在容器里可用(通常 /opt/flink/usrlib),或者通过 --jars 指定远端下载路径。

Compose 示例(挂载 usrlib):

yaml 复制代码
version: "2.2"
services:
  jobmanager:
    image: flink:2.2.0-scala_2.12
    ports:
      - "8081:8081"
    command: >
      standalone-job
      --job-classname com.job.ClassName
    volumes:
      - /host/path/to/job/artifacts:/opt/flink/usrlib
    environment:
      - |
        FLINK_PROPERTIES=
        jobmanager.rpc.address: jobmanager
        parallelism.default: 2

  taskmanager:
    image: flink:2.2.0-scala_2.12
    depends_on:
      - jobmanager
    command: taskmanager
    scale: 1
    volumes:
      - /host/path/to/job/artifacts:/opt/flink/usrlib
    environment:
      - |
        FLINK_PROPERTIES=
        jobmanager.rpc.address: jobmanager
        taskmanager.numberOfTaskSlots: 2
        parallelism.default: 2

如果你要从 savepoint 拉起(Application Mode 常见需求):

  • --fromSavepoint /path/to/savepoint
  • --allowNonRestoredState(可选)

注意:savepoint 路径必须在所有容器里都能访问(DFS 或挂载卷)。

4. 三种配置方式:动态参数、环境变量、挂载 conf

你可以用任意一种"覆盖"容器内的 flink-conf.yaml

4.1 动态参数(-D)覆盖

bash 复制代码
docker run flink:2.2.0-scala_2.12 taskmanager \
  -D jobmanager.rpc.address=jobmanager \
  -D taskmanager.numberOfTaskSlots=3 \
  -D blob.server.port=6124
bash 复制代码
FLINK_PROPERTIES="jobmanager.rpc.address: jobmanager
taskmanager.numberOfTaskSlots: 3
blob.server.port: 6124
"
docker run --env FLINK_PROPERTIES="${FLINK_PROPERTIES}" flink:2.2.0-scala_2.12 taskmanager

提示:jobmanager.rpc.address 必配,其它按需。

4.3 挂载自定义 conf(你要全量接管配置)

bash 复制代码
docker run \
  --mount type=bind,src=/host/path/to/custom/conf,target=/opt/flink/conf \
  flink:2.2.0-scala_2.12 jobmanager

注意:挂载目录里要包含必要的配置文件,并且 Flink 配置文件要可写(入口脚本有时会修改)。

5. 连接器与 SQL Client:最容易踩的坑(也是最关键的坑)

坑 1:连接器 JAR 只放在 SQL Client 里不行

SQL Client 只是提交 SQL,真正执行 SQL 的运行时在 JM/TM。你需要确保:

  • JobManager / TaskManager 的 /opt/flink/lib(或 plugin 路径)里也有相同连接器 JAR
  • SQL Client 容器里也有(否则解析/提交阶段可能缺类)

坑 2:ADD JAR 对宿主机路径不生效

在容器里,"本地文件系统"是 Docker overlay filesystem,不是你的宿主机路径。想让集群看到 JAR:

  • 方案 A:自定义镜像,把 JAR 放进 /opt/flink/lib
  • 方案 B:挂载卷,把 JAR 挂进 /opt/flink/lib/opt/flink/usrlib
  • 方案 C:Application Mode 用 --jars 从 S3/HTTP/DFS 拉

推荐:做一个带 Kafka 连接器的自定义镜像

示例 Dockerfile(官方示例思路):

dockerfile 复制代码
FROM flink:2.2.0-scala_2.12
ARG kafka_connector_version=4.0.0-2.0
RUN wget -P /opt/flink/lib https://repo.maven.apache.org/maven2/org/apache/flink/flink-sql-connector-kafka/${kafka_connector_version}/flink-sql-connector-kafka-${kafka_connector_version}.jar

然后在 compose 里 build 替换 image,让 jobmanager/taskmanager/sql-client 都用同一镜像。

6. 插件启用:S3、Hadoop FS 这些"不是放 lib 就完事"

Flink 的 filesystem 插件通常需要放到 /opt/flink/plugins/<plugin-name>/ 下,官方镜像提供了 ENABLE_BUILT_IN_PLUGINS 来启用自带插件 JAR(从 /opt/flink/opt 链接到 plugins)。

示例:

bash 复制代码
docker run \
  --env ENABLE_BUILT_IN_PLUGINS=flink-s3-fs-hadoop-2.2.0.jar \
  flink:2.2.0-scala_2.12 jobmanager

多个插件用 ; 分隔。

7. 容器里做"本地恢复":Working Directory + 挂载卷(强烈建议)

如果你用了 RocksDB state backend 或者希望 TaskManager 重启后更快恢复,建议把 working dir 做成"可持久化"挂载卷,否则容器一重启,本地 state 直接消失。

建议做法:

  • 挂载一个宿主机目录到容器,例如 /data/flink/working -> /data/flink/working
  • 配置 process.working-dir 指向这个路径
  • 开启 state.backend.local-recovery: true
  • 给 TaskManager 固定 taskmanager.resource-id(在容器环境尤其重要)

Compose 片段示例(思路):

yaml 复制代码
services:
  taskmanager:
    image: flink:2.2.0-scala_2.12
    volumes:
      - /data/flink/working:/data/flink/working
    environment:
      - |
        FLINK_PROPERTIES=
        jobmanager.rpc.address: jobmanager
        process.working-dir: /data/flink/working
        state.backend.local-recovery: true
        taskmanager.resource-id: tm-01

如果你会 scale 多个 TM,要让每个实例的 taskmanager.resource-id 唯一,否则会踩目录冲突坑。生产里更常见的做法是"每台机器固定一个 TM + 固定 resource-id",或用编排系统注入唯一 ID。

8. 内存分配器:jemalloc 与 glibc 的选择

官方镜像默认使用 jemalloc 来缓解内存碎片问题。如果你想切回 glibc:

bash 复制代码
docker run --env DISABLE_JEMALLOC=true flink:2.2.0-scala_2.12 taskmanager

如果你使用 glibc,建议限制 arena 数避免内存膨胀(尤其是 RocksDB + checkpoint/savepoint 时更明显):

bash 复制代码
docker run --env MALLOC_ARENA_MAX=1 flink:2.2.0-scala_2.12 taskmanager

9. 在 Docker 里跑 PyFlink:自定义镜像一步到位

示例 Dockerfile:

dockerfile 复制代码
FROM flink:2.2.0

RUN apt-get update -y && \
    apt-get install -y python3 python3-pip python3-dev && \
    rm -rf /var/lib/apt/lists/*
RUN ln -s /usr/bin/python3 /usr/bin/python

RUN pip3 install apache-flink==2.2.0

构建:

bash 复制代码
docker build -t pyflink:latest .

10. 镜像标签最佳实践:别用 latest,别偷懒

强烈建议显式使用包含 Flink+Scala 的 tag,比如:

  • flink:2.2.0-scala_2.12

原因很现实:Scala 版本与 Flink 版本不匹配时,类冲突会让你怀疑人生。

官方镜像有两个渠道:

  • Docker Hub 官方 flink(更推荐)
  • apache/flink(社区维护,适合应急)

11. 一套"最短闭环"的调试套路(特别适合你做压测/验证)

你前面提到 "Print 验证正确性 + BlackHole 压测性能",在 Docker Session 集群里尤其好用:

  • 开发阶段:source 用 datagen,sink 用 print 看输出是否符合预期
  • 压测阶段:sink 换 blackhole,你就能把瓶颈收敛到 join/agg/topn/UDF 本身(避免 sink 抢戏)
  • 观察方式:看 Web UI 的 backpressure、busy、checkpoint(如果有)、以及算子吞吐
相关推荐
市安3 小时前
docker命令知识点1
运维·docker·云原生·容器·eureka
xuekai200809013 小时前
GaussDB-SQL优化案例
数据库·sql·gaussdb
学习3人组4 小时前
Docker run 挂载本地两个目录到容器内的写法(核心规则+实操示例)
运维·docker·容器
礼拜天没时间.5 小时前
《Docker实战入门与部署指南:从核心概念到网络与数据管理》:初识Docker——概念与优势
linux·运维·网络·docker·容器·centos
潘晓可5 小时前
Booklore自建图书馆
docker
海星船长丶6 小时前
预编译与sql注入,正则回溯绕过,mysql常见绕过,报错注入7大常用函数
服务器·数据库·sql·mysql·网络安全
Mikhail_G6 小时前
Mysql数据库操作指南——数据库(零基础篇)
大数据·数据库·sql·mysql·数据分析
独泪了无痕6 小时前
SQL数据类型转换:CAST详解及实践
数据库·sql·oracle
optimistic_chen6 小时前
【Docker入门】Docker Image(Docker 镜像)
linux·运维·docker·容器·镜像