用 Docker 玩转 Kafka 4.0镜像选型、快速起步、配置持久化与常见坑
一、镜像选型:JVM vs GraalVM 原生
-
基于 JVM 的官方镜像(推荐):自 3.7.0 起在 Docker Hub 提供,适合本地开发与生产部署。
# 固定 4.0.0 版本 docker pull apache/kafka:4.0.0 # 拉取最新 docker pull apache/kafka:latest
-
基于 GraalVM 的“原生”镜像(实验性):自 3.8.0 起提供,仅用于本地开发/测试,不建议生产。
docker pull apache/kafka-native:4.0.0 docker pull apache/kafka-native:latest
怎么选?
- 追求稳定、生态最广:JVM 镜像。
- 想体验原生可执行体的启动更快/内存占用更小:本地试试 GraalVM 原生镜像(切记非生产)。
二、最小可用:一条命令跑起来
2.1 JVM 镜像(默认配置 + 端口 9092)
docker run -p 9092:9092 apache/kafka:4.0.0
2.2 GraalVM 原生镜像(实验性)
docker run -p 9092:9092 apache/kafka-native:4.0.0
提示:Kafka 4.0 仅支持 KRaft(无 ZooKeeper)。官方镜像自带默认配置,适合“开箱即用”的本地演示。
三、进入容器执行 Kafka 命令(创建主题 / 生产 / 消费)
下面以容器名
k1
为例(在docker run
后加--name k1
)。
# 给容器起名并启动
docker run --name k1 -p 9092:9092 -d apache/kafka:4.0.0# 进入容器交互
docker exec -it k1 bash
在容器内执行(路径以镜像为准,通常在 bin/
下):
# 创建主题
bin/kafka-topics.sh --create \--topic quickstart-events \--bootstrap-server localhost:9092# 查看主题
bin/kafka-topics.sh --describe \--topic quickstart-events \--bootstrap-server localhost:9092# 生产者
bin/kafka-console-producer.sh \--topic quickstart-events \--bootstrap-server localhost:9092
# 输入几行消息后回车提交# 消费者(从头读)
bin/kafka-console-consumer.sh \--topic quickstart-events \--from-beginning \--bootstrap-server localhost:9092
四、持久化与自定义配置(推荐做法)
默认容器内的数据是临时的。要让数据与配置长久保存,建议挂载卷或绑定宿主机目录。
4.1 服务器配置(KRaft 单机演示示例)
在宿主机准备 server.properties
(示例):
# 身份与角色(KRaft)
node.id=1
process.roles=broker,controller# 监听与通道
listeners=PLAINTEXT://:9092,CONTROLLER://:9093
inter.broker.listener.name=PLAINTEXT
controller.listener.names=CONTROLLER# 控制器法定多数(单机演示)
controller.quorum.voters=1@localhost:9093# 数据目录(与挂载保持一致)
log.dirs=/var/lib/kafka-logs
首次使用需要初始化集群并格式化日志目录(生成 Cluster ID)——可在容器内执行(见 4.3)。
4.2 使用卷挂载启动容器
# 准备持久化目录
mkdir -p $(pwd)/kdata# 以卷/绑定方式启动,挂载配置与数据目录
docker run --name k1 -d \-p 9092:9092 -p 9093:9093 \-v $(pwd)/server.properties:/opt/kafka/config/server.properties \-v $(pwd)/kdata:/var/lib/kafka-logs \apache/kafka:4.0.0
server.properties
挂载路径以镜像内 Kafka 的默认配置路径为准;上面示例用常见路径/opt/kafka/config/
(不同镜像可能略有差异,如不一致请进入容器确认目录结构)。
4.3 在容器内完成 KRaft 初始化(只需一次)
docker exec -it k1 bash# 生成 Cluster ID
KAFKA_CLUSTER_ID="$(bin/kafka-storage.sh random-uuid)"# 格式化日志目录(与 server.properties 一致)
bin/kafka-storage.sh format --standalone \-t $KAFKA_CLUSTER_ID \-c config/server.properties# 启动(若镜像未自动根据配置启动)
bin/kafka-server-start.sh config/server.properties
五、网络与连通性:advertised.listeners
思维模型
最常见的问题来自网络地址暴露不正确。要点如下:
- 容器内地址 ≠ 宿主机地址:外部客户端如何访问 Kafka?需要 Kafka 对外“自报家门”的地址,即
advertised.listeners
。 - 本机开发:从宿主机访问,通常把
advertised.listeners
设为宿主机可达的 IP/域名 +:9092
。 - 容器互访:在同一 Docker 网络桥接下,可用容器名作为主机名。
示例(追加到 server.properties
):
# 对外暴露地址(按需修改为宿主机 IP 或域名)
advertised.listeners=PLAINTEXT://192.168.1.100:9092
macOS/Windows 可根据实际情况使用
host.docker.internal
;Linux 建议使用宿主机实际 IP 或反向代理。
六、Docker Compose(单机开发模板)
docker-compose.yml(最小 KRaft 单机)
services:kafka:image: apache/kafka:4.0.0container_name: k1ports:- "9092:9092"- "9093:9093"volumes:- ./server.properties:/opt/kafka/config/server.properties- ./kdata:/var/lib/kafka-logscommand: >bash -lc "if [ ! -f /var/lib/kafka-logs/.formatted ]; thenKAFKA_CLUSTER_ID=$(bin/kafka-storage.sh random-uuid) &&bin/kafka-storage.sh format --standalone -t $KAFKA_CLUSTER_ID -c config/server.properties &&touch /var/lib/kafka-logs/.formatted;fi &&bin/kafka-server-start.sh config/server.properties"
说明:上面用一个“打点文件”
.formatted
确保只格式化一次。
想做多 Broker或独立控制器拓扑,需要为每个实例配置唯一的
node.id
,并在controller.quorum.voters
中声明所有控制器投票者(3/5 台、奇数);此处不展开,建议先在单机模板上验证所有业务流转。
七、GraalVM 原生镜像:适用与注意事项
- 适用:本地 Demo / CI 里跑更快的临时 Kafka。
- 不适用:生产环境(官方标注为实验性)。
- 迁移方式:命令用法一致;若涉及体量与性能评估,建议在 JVM 镜像上完成。
八、常见问题与排查
-
外部客户端连不上
- 多半是
advertised.listeners
配置错误;确保对外暴露的是外部可达的地址。 - 端口冲突:检查
9092/9093
是否被占用。
- 多半是
-
重启后数据丢失
- 未做卷挂载或挂载目录与
log.dirs
不一致 → 确认 4.2 的挂载设置。
- 未做卷挂载或挂载目录与
-
无法启动或初始化失败
- KRaft 需要先
kafka-storage.sh format
;重复格式化会被拒绝。 controller.quorum.voters
配置不合法(单机演示仅 1 个投票者即可)。
- KRaft 需要先
-
容器里能通,宿主机/其它容器不通
- Docker 网络隔离导致;为“外部连通”设置
advertised.listeners
,为“容器间互通”使用 Docker 自定义网络并用容器名访问。
- Docker 网络隔离导致;为“外部连通”设置
-
GraalVM 原生镜像跑在生产
- 官方明确仅用于本地开发/测试;请切回 JVM 镜像。
九、操作小抄(Cheat Sheet)
# 拉取镜像(JVM)
docker pull apache/kafka:4.0.0
docker pull apache/kafka:latest# 拉取镜像(GraalVM 原生,实验性)
docker pull apache/kafka-native:4.0.0
docker pull apache/kafka-native:latest# 直接起一个 Kafka(本地试用)
docker run --name k1 -p 9092:9092 -d apache/kafka:4.0.0# 进入容器执行命令
docker exec -it k1 bash# 创建主题
bin/kafka-topics.sh --create --topic t1 --bootstrap-server localhost:9092# 生产/消费
bin/kafka-console-producer.sh --topic t1 --bootstrap-server localhost:9092
bin/kafka-console-consumer.sh --topic t1 --from-beginning --bootstrap-server localhost:9092