Create your own
Lesson illustration

Launch and Verify a Single-Node KRaft Kafka Broker

Hello. In the last lesson, you traced an event from a producer into a topic partition and out to independent consumer groups. Now you will run the broker that makes that path real.

This is the practical portion of the Kafka Foundations and a Local KRaft Lab module. By the end, you will have a single Kafka node running in Docker, understand why it is a KRaft deployment, and verify that a Kafka client can reach it. We will deliberately stop before creating topics and sending records—that is the focus of the next lesson.


KRaft in the local lab

Older Kafka deployments required a separate ZooKeeper service to manage cluster metadata and controller election. KRaft—Kafka Raft—is Kafka’s built-in mechanism for maintaining that metadata and coordinating controllers. A modern Kafka deployment can therefore run without ZooKeeper.

For a production cluster, the roles are commonly separated:

  • Brokers store topic partitions and serve producer and consumer requests.
  • Controllers manage cluster metadata, such as topic definitions and partition leadership.
  • Multiple nodes provide fault tolerance.

For this lab, one Kafka node performs both roles:

RoleWhat the local node does
BrokerAccepts client connections and will store topic partitions
ControllerMaintains the local cluster’s metadata
KRaft quorumContains one controller voter: itself

This is called combined mode. It is convenient for development, but it has no redundancy: if the container is unavailable, so is Kafka.

Watch this brief overview to place the lab in context. Focus on the distinction between KRaft itself and the older ZooKeeper-based architecture; you do not need to study multi-node layouts yet.

Kafka Without Zookeeper? Setting Up KRaft Mode!

“Kafka Without Zookeeper? Setting Up KRaft Mode!” by SWE with Vivek Bharatha introduces KRaft as Kafka’s built-in replacement for ZooKeeper in controller election and metadata management.

Watch the KRaft overview. Listen for the two jobs KRaft takes over: controller election and metadata administration.

The official apache/kafka Docker image provides a fast path for this kind of local KRaft broker. Read the setup portion below before running commands, particularly the distinction between starting a process and proving that a Kafka client can communicate with it.

Developing event-driven applications with Kafka and Docker | Docker Docs

Read Docker’s Kafka guide for the official-image launch command and its cluster-ID connectivity check. It also explains why port 9092 must be published when an application runs on your host rather than inside the Kafka container.

In Launching Kafka, read the Starting Kafka subsection from the launch steps. Focus on the docker run command and the kafka-cluster.sh cluster-id verification command; ignore the later Node.js application material. Then, in Connecting to Kafka from a non-containerized app, read the opening explanation in External clients, from the port mapping explanation. Stop before the instructions to download Kafka tools onto the host, since this lesson uses the tools already packaged in the container.


Start the broker

1. Confirm Docker is available

Ensure Docker Desktop or the Docker daemon is running, then run:

docker version

You should see both a Client and a Server section. If the Server section is missing, Docker itself is not running yet.

2. Launch Kafka

Run this command from any working directory:

docker run -d --name kafka -p 9092:9092 apache/kafka:latest

Here is what each part does:

FragmentMeaning
docker runCreates and starts a container from an image
-dRuns the container in the background
--name kafkaGives the container a stable, convenient name
-p 9092:9092Publishes container port 9092 on port 9092 of your host
apache/kafka:latestUses the official Apache Kafka image

Docker will download the image on the first run, which can take longer than subsequent starts. The command returns a long container ID if Docker successfully creates the container.

For a short-lived learning environment, the latest tag is acceptable and matches the curated quick-start material. In a team project or production setting, use a tested, explicitly pinned image version so that a rebuild does not silently change Kafka versions.

3. Check the container lifecycle

Now inspect the container:

docker ps --filter "name=kafka"

You want its status to say Up. A typical abbreviated result looks like:

CONTAINER ID   IMAGE                 STATUS         PORTS
...            apache/kafka:latest   Up ...         0.0.0.0:9092->9092/tcp

There are two distinct checks in that output:

  1. Up means Docker still has the Kafka process running.
  2. 0.0.0.0:9092->9092/tcp means Docker has published the broker’s client port to your host.

Neither check alone proves the broker is ready to answer Kafka protocol requests. Kafka needs a brief initialization period, especially immediately after the image download. The next command is the meaningful readiness check.


Verify Kafka, not merely Docker

Run Kafka’s cluster inspection script inside the running container:

docker exec -it kafka /opt/kafka/bin/kafka-cluster.sh cluster-id --bootstrap-server localhost:9092

Expected result:

Cluster ID: <an opaque cluster identifier>

Your identifier will be different. The important fact is that you receive a cluster ID rather than a connection error.

This one command establishes several things:

  • the kafka container is running;
  • Kafka has completed startup;
  • the broker is listening at its client endpoint on port 9092;
  • a Kafka client can bootstrap against the broker;
  • the broker can return cluster metadata.

A bootstrap server is the initial Kafka address a client contacts. It is not necessarily the only broker a client will use in a larger cluster. Kafka returns metadata telling clients which brokers lead the relevant partitions. In this one-broker lab, localhost:9092 is both the bootstrap address and the only broker endpoint you need.

If the first attempt reports a connection failure, wait several seconds and run the same command again. Do not treat a merely running Docker container as proof that Kafka initialization is complete.

For an additional, host-side confirmation of the port mapping, run:

docker port kafka 9092

It should report a host address and port, normally port 9092. This confirms Docker’s forwarding rule. The cluster-ID command remains the stronger test because it checks Kafka communication rather than only Docker networking.


Why localhost needs careful interpretation

The word localhost always means the machine where the client process runs.

  • In the docker exec command, the client runs inside the Kafka container, so localhost:9092 means the broker listener inside that container.
  • In the Java and Spring Boot applications you will run later from your host machine, localhost:9092 means your own host. Docker forwards that request through the published port to Kafka.

The Kafka Docker networking paths diagram makes the distinction visible.

The diagram shows a Kafka container inside Docker Desktop’s VM: port `9092` is published to the host for a non-containerized application, while a separate internal endpoint can be advertised for clients running in another Docker container.

The diagram highlights a Kafka-specific networking issue: a client first contacts a bootstrap address, but then Kafka tells it which address to use for ongoing communication. That returned address is governed by Kafka’s advertised listeners configuration.

For this course’s simple environment, keep the situation narrow:

  • run the broker in Docker;
  • publish port 9092;
  • run Java and Spring Boot applications directly on your host;
  • connect those applications to localhost:9092.

When both Kafka and clients run in separate containers, listener configuration becomes more involved. In that situation, Kafka generally needs an address resolvable on the Docker network, rather than an address such as the client container’s own localhost. We will not add that complexity to this single-node lab.


A small operational routine

Keep this broker available for the next lessons. These commands control its lifecycle:

docker stop kafka

Stops Kafka while preserving the container.

docker start kafka

Starts the existing container again.

docker logs kafka --tail 100

Shows the most recent broker startup or error messages.

docker rm -f kafka

Stops and removes the container. Use this only when you deliberately want to discard this local environment. Without a named volume, records stored only in the container filesystem are removed with the container.

Common first-run failures

SymptomLikely causeFirst action
Cannot connect to the Docker daemonDocker Desktop or Docker daemon is not runningStart Docker, then rerun the command
Port binding error mentioning 9092Another process or container already uses port 9092Find the conflicting service, stop it, or choose a different host port
Container status is ExitedKafka startup encountered a configuration or environment issueRun docker logs kafka --tail 100
Connection refused from kafka-cluster.shBroker is still initializing, or it exited shortly after startupCheck docker ps -a, wait briefly if it is still Up, then inspect logs
No such container: kafkaThe container name differs, or it was removedRun docker ps -a and use the actual name

Avoid trying random Kafka configuration variables at this stage. The point of using the official quick-start image is to establish one known-good baseline before you begin changing topic, producer, consumer, or listener settings.


Takeaways

You now have a local Kafka environment with these properties:

  • It runs as one Docker container named kafka.
  • It uses modern KRaft operation, with no separate ZooKeeper container.
  • Its single node combines the broker and controller roles, which is appropriate for learning but not fault tolerant.
  • Docker publishes Kafka’s client port through -p 9092:9092.
  • docker ps checks the container lifecycle, while kafka-cluster.sh cluster-id verifies that a Kafka client can actually reach a ready broker.

Next, you will use Kafka’s command-line tools to create and inspect a topic, then produce and consume a few test records.

Can't find a good explanation? Sign up and we'll make it for you

Sign up