Map a Docker port with -p HOST_PORT:CONTAINER_PORT, such as -p 127.0.0.1:8080:80 to publish container port 80 only on the host loopback interface.
The order is easy once the traffic path is clear: clients reach the host port, Docker forwards to the container port, and the process inside the container must actually be listening there.
Table of contents
- Read publish syntax from outside to inside
- Make the process listen inside the container
- Use Compose syntax explicitly
- Understand EXPOSE and automatic ports
- Treat published ports as network exposure
- How this fits the rest of the stack
- FAQ
Read publish syntax from outside to inside
docker run -p 8080:80 image publishes host TCP port 8080 and forwards it to container TCP port 80. The host and container ports may match, but they do not have to. Port mapping does not change the application’s internal listening port.
docker run --rm -p 127.0.0.1:8080:80 my-web-image
curl http://127.0.0.1:8080
Binding to 127.0.0.1 keeps the published port local to the host. Omitting the host IP commonly binds on all interfaces, which can expose the service beyond the developer’s intention.
Make the process listen inside the container
The application must listen on the container port and usually on 0.0.0.0, not only container loopback. A published port cannot reach a process bound exclusively to 127.0.0.1 inside the container.
docker exec my-container ss -lntp
docker port my-container
docker logs my-container
When a connection is refused, check container status, logs, listening address, internal port, published mapping, and host firewall in that order. Randomly swapping port numbers is not a networking strategy.
Use Compose syntax explicitly
Compose expresses the same mapping under ports. Quoting avoids YAML treating colon-separated values unexpectedly and makes protocol or host-IP additions clear.
services:
web:
image: my-web-image
ports:
- '127.0.0.1:8080:80'
- '127.0.0.1:5353:53/udp'
Services on the same Compose network usually connect through service names and container ports without publishing them to the host. Publish only what external clients need.
Understand EXPOSE and automatic ports
A Dockerfile EXPOSE 80 documents an intended container port; it does not publish that port. Publishing happens at runtime through -p, -P, Compose, or an orchestrator. -P assigns host ports automatically for exposed ports, which is useful in some tests but less predictable for stable local access.
Inspect assigned mappings with docker port or docker ps. Do not build security assumptions around EXPOSE because it is metadata, not a firewall rule.
Treat published ports as network exposure
Apply host firewall rules, authentication, TLS, and reverse-proxy policy as appropriate. Avoid publishing databases and administrative interfaces to every interface merely because local testing worked. Use private networks or loopback bindings by default.
In production platforms, the routing layer may map a public hostname to a container port without direct host publishing. Keep the application’s internal port explicit and let the platform own external TLS, health checks, and route lifecycle.
How this fits the rest of the stack
Before choosing container size and public traffic shape, model the service, database, storage, and bandwidth in the RunxBuild hosting calculator. Then deploy through the RunxBuild dashboard, where the live route can point to the container port without exposing every host interface.
Useful related references:
- Syncthing Docker: Persistent Volumes, Ports, Permissions, and Safe Remote Access
- Installation of Docker in Ubuntu: Step-by-Step for 22.04 and 24.04
- How to Install Docker on Ubuntu: 2026 Guide (22.04 and 24.04)
- Docker services on RunxBuild
FAQ
Which port comes first in Docker mapping?
The host port comes first and the container port second: HOST_PORT:CONTAINER_PORT.
What is the difference between EXPOSE and -p?
EXPOSE documents an intended container port. The -p flag actually publishes a host mapping at runtime.
Why is my mapped Docker port refusing connections?
Check that the container is running, the process listens on the expected container port and on a reachable address, the mapping is correct, and the host firewall allows traffic.
How do I map a UDP port?
Add the protocol, such as -p 5353:53/udp. TCP is the default when no protocol is specified.
How do I keep a Docker port local only?
Bind it to host loopback, for example -p 127.0.0.1:8080:80, and verify host firewall and Docker networking behavior.