Skip to main content

How Private & Public IPs & Ports Work

The IP addresses and ports that come out of Kurtosis can be confusing at times. This document will explain how Kurtosis handles public and private IPs and ports.

Private IPs

Each Docker or Kubernetes cluster has a private IP address range, from to Each container gets IP addresses from this range, and containers talk to other containers using these IP addresses. These IP addresses have nothing to do with the outside world's IP addresses, and are purely internal to the cluster.

These IP addresses are private to Docker/Kubernetes, so you will not be able to reach them from your host machine (i.e. outside the Docker/Kubernetes cluster). For example, a container with IP address will not be reachable by curl from your regular command line.

Private Ports

Containers can listen on ports. These ports do not conflict with other containers, nor do they conflict with ports on your host machine, outside the Docker/Kubernetes cluster. For example:

  • You might be running Container A running a server listening on port 3000, and Container B running a server listening on port 3000. Even though the containers are using the same port, they are treated separately inside of Docker/Kubernetes and do not conflict.
  • You might be running a server on your host machine on port 3000, and a container in Docker/Kubernetes listening on port 3000. This is also fine, because the Docker/Kubernetes ports are private to the cluster.

These container ports are private: you will not be able to access them from your host machine.

Public IPs & Ports

To simplify your work, Kurtosis allows you to connect to every private port of every container. This is accomplished by binding every private port to an ephemeral port on your host machine. These ephemeral ports are called the "public ports" of the container because they allow the container to be accessed outside the Docker/Kubernetes cluster. To view the private & public port bindings of each container in Kurtosis, run kurtosis enclave inspect and look for the bindings in the "Ports" column:

========================================== User Services ==========================================
GUID ID Ports Status
cl-beacon-1670597432 cl-beacon http: 4000/tcp -> RUNNING
metrics: 5054/tcp ->
tcp-discovery: 9000/tcp ->
udp-discovery: 9000/udp ->
cl-validator-1670597459 cl-validator http: 5042/tcp -> RUNNING
metrics: 5064/tcp ->
el-1670597405 el engine-rpc: 8551/tcp -> RUNNING
rpc: 8545/tcp ->
tcp-discovery: 30303/tcp ->
udp-discovery: 30303/udp ->
ws: 8546/tcp ->
forkmon-1670597469 forkmon http: 80/tcp -> RUNNING
grafana-1670597488 grafana http: 3000/tcp -> RUNNING

The IP address used to reach these containers is your localhost address, This is the "public IP address" of each container in the cluster.

The combination of public IP + port will allow you to connect to a container from your command line. For example, from the output above, curl on your command line would make a request to private port 4000 on the cl-client-0-beacon service.