> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Nomad Networking Ports and Bridges

> Explains Nomad port mapping, host versus container ports, bridge versus host network modes, using port labels and environment variables, and why to avoid static host ports for scalable services.

Two copies of the same application on the same machine, both wanting port 8080 — how can that work?

On Maya's old virtual machines, that would have been impossible. Tidepool avoided collisions by keeping a spreadsheet: someone recorded which service owned which host port — and nobody updated it reliably.

So why didn't the second container fail?

Because Maya never asked Nomad to bind the same *host* port. In her job file she created a named port with a `to` value of `8080` inside the `network` block. That `to` value is the port inside the task (the container), not the host port. She named the port but left the host port unspecified, allowing Nomad to choose it.

Separate the two concepts:

* The `to` value is the port inside the task — the port the application listens on (for Tidepool's API this is `8080` and is baked into the image).
* The host port is what the machine exposes. If you omit it, Nomad assigns a free host port from a default range (20000–30000).

Example: container port (task-facing)

```hcl theme={null}
network {
  port "HTTP" {
    to = 8080
  }
}
```

Because no static host port was declared, Nomad picked distinct host ports for each allocation. Inside each container the application still sees `8080`, but Nomad maps different host ports to those internal ports.

How the mapping works depends on the network mode in the group block — the two common modes are:

* host mode (the default): the task shares the machine's network stack. No port translation occurs; two allocations that both request the same host port will collide.
* bridge mode: the group gets an isolated network namespace with its own IP. Nomad maps a host port it chose into the container port specified by `to`.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/l4I9ipyyKXTd2i-D/images/Learn-By-Doing-HashiCorp-Nomad/Scaling-and-Connecting-Workloads/Nomad-Networking-Ports-and-Bridges/docker-host-vs-bridge-networking.jpg?fit=max&auto=format&n=l4I9ipyyKXTd2i-D&q=85&s=d34a3d41f0cfc2e46f9dbc2e318e1b67" alt="A slide illustrating host vs bridge Docker networking. It shows icons for host (globe), bridge (lock) and ports mapped (plug) with four Docker containers labeled box-1 to box-4 and the note &#x22;Bridge · its own namespace, ports mapped.&#x22;" width="1920" height="1080" data-path="images/Learn-By-Doing-HashiCorp-Nomad/Scaling-and-Connecting-Workloads/Nomad-Networking-Ports-and-Bridges/docker-host-vs-bridge-networking.jpg" />
</Frame>

Bridge mode is what enables host-to-container port mapping and is the recommended choice when you plan to run multiple instances of the same service.

Comparison at a glance:

| Network Mode | What it means | When to use |
| - | - | - |
| `host` | Task shares the host network; no translation between host and container ports | Single-instance services, low-latency host networking, or when you require the host's IP and ports directly |
| `bridge` | Task runs in its own network namespace; Nomad maps a host port to the container port | Services you scale to multiple copies where each allocation needs its own host port |

If Nomad chooses the host port, how does the application know which port it got? Nomad exposes environment variables for every port label you declare. For a label named `HTTP`, Nomad provides variables like:

* `NOMAD_PORT_http` — the host port number Nomad chose
* `NOMAD_IP_http` — the host's IP address (as seen from the allocation)
* `NOMAD_ADDR_http` — the host IP and port combined

Example environment variables Nomad injects into the task:

```text theme={null}
NOMAD_PORT_http=20001
NOMAD_IP_http=10.0.1.12
NOMAD_ADDR_http=10.0.1.12:20001
```

Use the same port label in your `service` block so Nomad registers the actual host port under the service name. Do not hard-code numeric host ports in the service stanza — let Nomad wire things together from the label.

```hcl theme={null}
task "api" {
  driver = "docker"

  config {
    image = "tidepool/api:latest"
    # container ports are mapped by Nomad when network mode is bridge
  }

  resources {
    network {
      port "HTTP" {}
    }
  }

  service {
    name = "tidepool-api"
    port = "HTTP"    # refer to the same label, not a numeric port
  }
}
```

<Callout icon="lightbulb" color="#1CB2FE">
  Always reference the port by its label (for example `HTTP`) in `service` and task code. This keeps the container-facing port and the Nomad-assigned host port synchronized without hard-coded numbers.
</Callout>

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/l4I9ipyyKXTd2i-D/images/Learn-By-Doing-HashiCorp-Nomad/Scaling-and-Connecting-Workloads/Nomad-Networking-Ports-and-Bridges/one-label-written-once-docker-boxes.jpg?fit=max&auto=format&n=l4I9ipyyKXTd2i-D&q=85&s=f09438982abf4426f25bfd635a2f09ff" alt="A presentation slide titled &#x22;One Label, Written Once&#x22; showing icons for a network label and an env var alongside the phrase &#x22;Never from a config file.&#x22; Below are Docker whale icons and server illustrations labeled box-1 through box-4." width="1920" height="1080" data-path="images/Learn-By-Doing-HashiCorp-Nomad/Scaling-and-Connecting-Workloads/Nomad-Networking-Ports-and-Bridges/one-label-written-once-docker-boxes.jpg" />
</Frame>

Nothing else in your infrastructure needs to record static ports. That lets instances move between machines and scale up or down without manual edits.

If you need service-to-service identity (mutual TLS, encrypted traffic, etc.), that's typically handled by a service mesh. Nomad integrates with service meshes using a `connect` block that injects a sidecar proxy next to each task and routes traffic through it — a larger topic beyond the scope of this article.

One common pitfall is pinning every service to a fixed host port. Using a static host port can make firewall rules simpler, but it breaks scaling: when you increase from two to four copies, new allocations may be unable to start because the fixed ports are already in use. That returns you to the spreadsheet problem.

<Callout icon="warning" color="#FF6B6B">
  Avoid static host ports unless an external constraint requires them (for example, a legacy load balancer or a partner integration that demands fixed ports). In most cases, allow Nomad to assign host ports and read the assigned port from the environment.
</Callout>

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/l4I9ipyyKXTd2i-D/images/Learn-By-Doing-HashiCorp-Nomad/Scaling-and-Connecting-Workloads/Nomad-Networking-Ports-and-Bridges/static-port-trap-pending-allocations.jpg?fit=max&auto=format&n=l4I9ipyyKXTd2i-D&q=85&s=568cc77f82adfdc4e9b927b3c2e427fe" alt="A presentation slide titled &#x22;The Static Port Trap&#x22; showing icons (traffic light, bar chart, hourglass) with captions about pinned services, counts and pending allocations, and four Docker/server boxes labeled box-1 through box-4. The right side highlights the text &#x22;Pending allocations, and the spreadsheet returns.&#x22;" width="1920" height="1080" data-path="images/Learn-By-Doing-HashiCorp-Nomad/Scaling-and-Connecting-Workloads/Nomad-Networking-Ports-and-Bridges/static-port-trap-pending-allocations.jpg" />
</Frame>

Summary

* Use `to` to declare the container port your application listens on.
* Prefer bridge mode for multi-instance services so Nomad can map host ports.
* Read `NOMAD_PORT_<label>` (and related env vars) from inside the task to discover the host port.
* Only use static host ports when absolutely necessary.

Links and references

* [Nomad Networking Documentation](https://www.nomadproject.io/docs/administration/networking)
* [Nomad Port Labels and Services](https://www.nomadproject.io/docs/job-specification/service)
* [Service Mesh with Nomad Connect](https://www.nomadproject.io/docs/connect)

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/learn-by-doing-hashicorp-nomad/module/d6f53825-444d-461b-adca-bce23263dba7/lesson/5c2c1264-1d78-4cf0-9280-41286541fd24" />

  <Card title="Practice Lab" icon="flask-conical" cta="Learn more" href="https://learn.kodekloud.com/user/courses/learn-by-doing-hashicorp-nomad/module/d6f53825-444d-461b-adca-bce23263dba7/lesson/68729c88-b26d-46be-b668-e8d66585ef5c" />
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.