Production clusters run in isolated mode, with three or five dedicated controllers, so that a busy broker cannot starve the quorum (combined mode is for development). The six-node cluster mounts properties files and a start script (Formatting Storage and Configuration Files) rather than setting dozens of variables, and a YAML anchor keeps it short.
# quorum.yaml: three KRaft controllers (nodes 1-3) and three brokers (nodes 4-6)
name: l3-kq
x-node: &node
image: apache/kafka:4.3.1
entrypoint: ["bash", "/mnt/quorum/start.sh"]
volumes: ["./quorum:/mnt/quorum:ro"] # properties files and start.sh
environment: &env
CLUSTER_ID: Wb96LW2BRGSHe9VjFRvWOA
INITIAL_CONTROLLERS: "1@l3-c1:9093:5CUtmwF4QDiCN7NVutEiyQ,\
2@l3-c2:9093:4W0Cc1gvRbK40QSwRSZurg,3@l3-c3:9093:sTd2qAh9RWq8WbRS7RDbcw"
KAFKA_HEAP_OPTS: "-Xms256m -Xmx256m"
services:
c1: {<<: *node, container_name: l3-c1, environment: {<<: *env, ROLE: controller, NODE_ID: 1}}
c2: {<<: *node, container_name: l3-c2, environment: {<<: *env, ROLE: controller, NODE_ID: 2}}
c3: {<<: *node, container_name: l3-c3, environment: {<<: *env, ROLE: controller, NODE_ID: 3}}
b4: {<<: *node, container_name: l3-b4, environment: {<<: *env, ROLE: broker, NODE_ID: 4},
ports: ["33194:9094"]}
b5: {<<: *node, container_name: l3-b5, environment: {<<: *env, ROLE: broker, NODE_ID: 5},
ports: ["33195:9094"]}
b6: {<<: *node, container_name: l3-b6, environment: {<<: *env, ROLE: broker, NODE_ID: 6},
ports: ["33196:9094"]}
networks: {default: {name: l3-booknest}}Started with docker compose -f compose/quorum.yaml up -d, the six JVMs (256 MB heaps) used about 1.3 GiB: under 300 MiB per broker, 130-155 MiB per controller. Data lives in the image's anonymous volumes until down -v.