Back to Blog
8 min read
DevOps

Docker Compose Ports Explained: Host Ports, Container Ports, and Conflicts

Understand Docker Compose ports syntax, host-to-container mappings, localhost access, expose vs ports, and common port conflict errors in docker-compose.yml files.

By Spoold Editorial TeamReviewed for tool accuracy
Editorial Policy

Most Docker Compose port bugs are mapping bugs

Docker Compose port syntax looks small, but it controls how traffic reaches your service. The left side is the host port on your machine. The right side is the container port inside the service. Confusing those two is the quickest way to create a localhost bug or a port collision.

When to use this guide

Local development

Map a web app, API, database, queue, or admin panel to a predictable localhost port.

Compose reviews

Read a compose file and understand which services are exposed to the host.

Port conflicts

Find two services trying to bind the same host port before you run docker compose up.

Safer defaults

Decide when a service needs ports and when it should stay internal on the compose network.

How to read Compose ports

1

Start with host:container

In "3000:80", open localhost:3000 on the host. Docker forwards that traffic to port 80 inside the container.
2

Check protocol only when needed

"5353:5353/udp" maps UDP. Without a suffix, Docker uses TCP.
3

Use expose for internal visibility

expose documents internal ports for other services. It does not publish the port to localhost.
4

Inspect the full file visually

Paste the file into Docker Compose Viewer to see service ports, dependencies, volumes, and validation warnings together.

Docker Compose port examples

TaskInputResult
Basic web app"3000:3000"localhost:3000 reaches container port 3000.
Nginx container"8080:80"localhost:8080 reaches port 80 inside the container.
Bind to localhost only"127.0.0.1:5432:5432"The database is available only from the local machine.
Internal onlyexpose: ["6379"]Other compose services can talk to Redis, but the host cannot.

How to choose a Docker Compose port mapping

A port mapping is a small operational decision. It decides who can reach a service, whether two services collide, and whether local development matches production closely enough to catch real bugs.

Browser-facing app

Publish a stable host port, such as "3000:3000", so teammates and test scripts can use the same URL every time.

Database for local tools

Bind to 127.0.0.1 when possible, for example "127.0.0.1:5432:5432", to avoid exposing the database on your network.

Internal service

If only other containers need the service, skip ports and let compose networking handle service-to-service traffic by name.

Temporary debugging

It is fine to publish a port while debugging, but remove it after the service no longer needs host access.

Port debugging checklist

  • 1Read mappings as host port first, container port second.
  • 2Check for duplicate host ports across all services in the compose file.
  • 3Use 127.0.0.1 bindings for local-only databases, queues, and admin panels.
  • 4Remove published ports from services that only need internal compose-network access.

ports vs expose

Use ports when a human, browser, test runner, or external client on the host needs to connect. Use expose when only other services in the compose network need to know about the port.

Port rule

If you can reach a service through another container name, you often do not need to publish that service to localhost.

Related workflow

This guide is designed to pair with the tool linked below. Use the article to understand the workflow, then open the tool with a real sample so you can validate the result instead of copying a generic answer from a search result.

Common mistakes to avoid

  • Reading "8080:80" backwards and opening localhost:80.
  • Publishing databases and internal queues to every network interface during local development.
  • Using the same host port for two services.
  • Assuming expose makes a service available from the browser.

FAQ

Which side of Docker Compose ports is localhost?

The left side. In "8080:80", 8080 is the host port.

Why does Docker say port is already allocated?

Another process or compose service is already using the same host port. Change the left side of the mapping or stop the existing process.

Do services need ports to talk to each other?

No. Services on the same compose network can usually talk by service name and container port.

Try it in Docker Compose Viewer

Paste a real sample, run the workflow, and use the guide above as a checklist while you inspect the output.

Try It Now

Put this guide into practice with our free tools. No sign-up required.

Open Docker Compose Viewer
Docker Compose Ports Explained: Host Ports, Container Ports, and Conflicts | Blog | Spoold