docker-compose 部署单节点 kafka 4.0 测试环境

高版本kafka已经不再需要ZooKeeper当保姆才能启动了,现在部署一个单机单节点测试环境比原来方便不少。

不过最常用的bitnami/kafka不再提供免费镜像,导致我们只能用apache/kafka,新镜像的配置会稍微麻烦一些,所以记录一下。

部署内容:

  • 单节点kafka服务,版本4.0+
  • kafka UI,方便管理,版本用最新的
  • 开启简单的用户名密码验证

docker-compose文件:

yaml 复制代码
version: '3'

networks:
  kafka-net:

services:
  kafka:
    image: apache/kafka:latest
    container_name: kafka
    networks:
      - kafka-net
    ports:
      - "9092:9092"
    volumes:
      - ./kafka_data:/var/lib/kafka/data
      - ./kafka_server_jaas.conf:/etc/kafka/kafka_server_jaas.conf # 配置用户名密码
    environment:
      KAFKA_NODE_ID: 1
      KAFKA_PROCESS_ROLES: 'broker,controller'
      KAFKA_CONTROLLER_QUORUM_VOTERS: '1@localhost:9093'
      KAFKA_CONTROLLER_LISTENER_NAMES: 'CONTROLLER'
      
      # 定义监听器:EXTERNAL(9092) 走 SASL 认证,PLAINTEXT(29092) 给容器内用(这里也改为 SASL 确保安全)
      KAFKA_LISTENERS: 'SASL_PLAINTEXT://0.0.0.0:29092,EXTERNAL://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093'
      KAFKA_ADVERTISED_LISTENERS: 'SASL_PLAINTEXT://kafka:29092,EXTERNAL://localhost:9092'
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: 'CONTROLLER:PLAINTEXT,SASL_PLAINTEXT:SASL_PLAINTEXT,EXTERNAL:SASL_PLAINTEXT'
      KAFKA_INTER_BROKER_LISTENER_NAME: 'SASL_PLAINTEXT'
      
      # SASL/PLAIN 认证配置
      KAFKA_SASL_ENABLED_MECHANISMS: 'PLAIN'
      KAFKA_SASL_MECHANISM_INTER_BROKER_PROTOCOL: 'PLAIN'
      # 告诉 Kafka 读取我们的 JAAS 文件
      KAFKA_OPTS: "-Djava.security.auth.login.config=/etc/kafka/kafka_server_jaas.conf"

      # 数据持久化
      KAFKA_LOG_DIRS: '/var/lib/kafka/data'

  kafka-ui:
    image: provectuslabs/kafka-ui:latest
    container_name: kafka-ui
    depends_on:
      - kafka
    networks:
      - kafka-net
    ports:
      # 映射到8090,因为8080一般还得挂其他的服务做测试
      - "8090:8080"
    environment:
      KAFKA_CLUSTERS_0_NAME: local
      KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:29092
      # 配置 UI 使用用户名和密码连接 Kafka
      KAFKA_CLUSTERS_0_PROPERTIES_SECURITY_PROTOCOL: SASL_PLAINTEXT
      KAFKA_CLUSTERS_0_PROPERTIES_SASL_MECHANISM: PLAIN
      KAFKA_CLUSTERS_0_PROPERTIES_SASL_JAAS_CONFIG: 'org.apache.kafka.common.security.plain.PlainLoginModule required username="你配置的用户名" password="你配置的密码";'

配置文件里输入用户和密码:

conf 复制代码
KafkaServer {
    org.apache.kafka.common.security.plain.PlainLoginModule required
    username="节点在集群内通信时的用户名"
    password="节点在集群内通信时的密码"
    # 下面这些才是用户配置
    # 格式user_<用户名>="密码"
    user_apot="你配置的密码";
};

创建好文件和目录之后用docker-compose up -d就能启动服务了。访问localhost:8090可以看到kafka的web控制面板:

安装好之后可以用下面的命令查看版本:

console 复制代码
$ docker exec -it kafka /opt/kafka/bin/kafka-server-start.sh --version

[2025-12-29 11:08:34,595] INFO Registered kafka:type=kafka.Log4jController MBean (kafka.utils.Log4jControllerRegistration$)
4.0.0

可以看到已经配置好了kafka 4.0环境。

apache/kafka的镜像里内置了各种操作kafka的脚本,不过这些脚本没被添加进$PATH,执行的时候需要指定路径:

bash 复制代码
# 先配置登录验证信息
docker exec -it kafka bash -c "cat <<EOF > /tmp/client.conf
security.protocol=SASL_PLAINTEXT
sasl.mechanism=PLAIN
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \
  username='客户端登录用户名,就是我们之前用user_xxx配置的那些' \
  password='客户端登录密码';
EOF"

# 调用脚本创建一个topic,需要指定脚本路径
docker exec -it kafka /opt/kafka/bin/kafka-topics.sh --command-config /tmp/client.conf \
  --bootstrap-server localhost:9092 \
  --create \
  --topic test.data \
  --partitions 1 \
  --replication-factor 1 \
  --config cleanup.policy=delete \
  --config retention.ms=86400000

所有脚本都存放在/opt/kafka/bin路径下,调用前还需要提供登录凭证信息,这些需要注意。打开localhost:8090上的web UI,就能找到我们刚刚创建的topic了:

过期处理策略和过期时间也已经被正确设置:

总体而言执行脚本还是有些繁琐,我更愿意通过代码或者web界面来做这些操作。

最后我们写一个go的测试代码,向我们的测试用单节点kafka里写入一些数据:

golang 复制代码
package main

import (
	"context"
	"math/rand/v2"
	"strconv"
	"time"

	"github.com/segmentio/kafka-go"
	"github.com/segmentio/kafka-go/sasl/plain"
)

const (
	topic         = "lean.data1"
	kafkaEndpoint = "localhost:9092"
)

func main() {
	mechanism := plain.Mechanism{
		Username: "客户端登录用户名",
		Password: "客户端登录密码",
	}

	dialer := &kafka.Dialer{
		Timeout:       10 * time.Second,
		DualStack:     true,
		SASLMechanism: mechanism,
	}

	w := kafka.NewWriter(kafka.WriterConfig{
		Brokers: []string{kafkaEndpoint},
		Dialer:  dialer, // 必须传入带 SASL 的 dialer
		Async:   false,
	})
	defer w.Close()

	msg := kafka.Message{
		Topic: topic,
		Key:   []byte("test"),
		Value: []byte(strconv.Itoa(rand.Int())), // 随便写入一些随机数据
	}

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	err := w.WriteMessages(ctx, msg)
	if err != nil {
		panic(err)
	}
}

可以看到我们的随机数已经正常写入topic了。

注意:这个配置只使用了最基本的验证,且是单节点,不适合在测试和学习之外的任何用途使用,为了安全我也建议在测试完成之后就立刻用docker-compose down关闭服务。

相关推荐
枕书1 小时前
实战记录:如何使用 Docker 一键部署长亭 PandaWiki 智能知识库
运维·docker·容器
IT19955 小时前
Docker笔记-对docker-compose.yml基本认识
笔记·docker·容器
JCGKS5 小时前
海量文档单词计数算法方案分析
golang·数据结构与算法·海量数据·搜索引起·倒排查找
supersolon7 小时前
WSL2(Linux)升级docker
linux·运维·docker·wsl·升级
一殊酒7 小时前
【Docker】常用命令大全及解析
docker·容器·eureka
福大大架构师每日一题7 小时前
ollama v0.18.2 发布!OpenClaw 安装优化、Claude 加速、MLX 量化全面升级
golang·ollama
Uncertainty!!8 小时前
将docker镜像上传到github镜像存储仓库(GitHub 容器仓库(GHCR)使用流程)
docker·容器·github
我是谁??8 小时前
Rocky9+ Docker + 容器内Linux桌面环境 + Web远程
运维·docker·容器
姓王名礼9 小时前
这是一个完整的全栈交付包,包含Vue3 前端交互界面(集成数字人视频流、ECharts 图表、语音对话)和Docker Compose 一键部署脚本。
前端·docker·echarts
eggwyw9 小时前
Redis 设置密码(配置文件、docker容器、命令行3种场景)
数据库·redis·docker