Docker Networking: Hostname vs Container Name, Port Mapping, and Bridge Networks
Docker container networking has several layers: hostname (what the container thinks it's called), container name (how Docker identifies it), and network aliases (how other containers reach it). Port mapping exposes container ports to the host. Dynamic port mapping (host port 0) lets the OS assign available ports — required for ECS bridge mode with multiple tasks per host.
Hostname vs container name vs network alias
Three distinct identities in Docker networking:
| Identity | What it is | Set by |
|---|---|---|
| Container name | Docker's name for the container | --name flag or container_name: in Compose |
| Hostname | What the container sees as its own hostname | --hostname flag, defaults to container ID |
| Network alias | DNS name other containers use to reach this one | --network-alias or Compose aliases: |
In a Docker network, by default the container name is also registered as a DNS name. Other containers on the same network resolve it. The hostname only affects what the container sees internally (e.g., hostname command, HOSTNAME env var).
# docker-compose.yml
services:
api:
image: my-api
container_name: api-container # Docker's name
hostname: api-service # what the container thinks it's called
networks:
app-net:
aliases:
- api # other containers use "api" to reach this service
web:
image: my-web
environment:
API_URL: http://api:8080 # uses the network alias, not container name
networks:
- app-net
networks:
app-net:
driver: bridge
Hostname and container name are independent — using localhost inside a container never reaches another container
GotchaDocker NetworkingEach container has its own network namespace. When code inside a container connects to localhost, it connects to the container's own loopback interface — not the host machine and not other containers. Cross-container communication requires using the container name or network alias as the hostname.
Prerequisites
- Docker networks
- DNS resolution basics
Key Points
- localhost inside container A refers to container A's loopback — not the Docker host or container B.
- Container names are DNS-registered on user-defined networks, not on the default bridge network.
- The default bridge network uses --link for container discovery (legacy). User-defined networks have built-in DNS.
- hostname: sets what the container sees as its own name, not what others use to reach it.
Port mapping: static vs dynamic
Port mapping exposes a container port to the host. The host port can be:
services:
app:
image: my-app
ports:
- "8080:80" # static: host port 8080 → container port 80
- "0:80" # dynamic: OS assigns available host port → container port 80
- "80" # equivalent to "0:80" — shorthand for dynamic mapping
Static port mapping (8080:80): only one container can bind to host port 8080. Running two instances of the same service on the same host requires different host ports.
Dynamic port mapping (0:80): the OS assigns an available ephemeral port. Multiple containers can run the same service on the same host. Find the assigned port:
docker inspect container-id \
--format '{{range $p, $conf := .NetworkSettings.Ports}}{{$p}} -> {{(index $conf 0).HostPort}}{{"\n"}}{{end}}'
# or
docker port container-id 80
Dynamic port mapping in ECS bridge mode
ECS requires dynamic port mapping when running multiple tasks of the same service on a single EC2 instance. If you use a static host port (e.g., 8080:80), only one task can run per instance because host port 8080 is already taken.
resource "aws_ecs_task_definition" "app" {
family = "app"
network_mode = "bridge"
container_definitions = jsonencode([{
name = "app"
image = "my-app:latest"
portMappings = [{
containerPort = 80
hostPort = 0 # dynamic — ECS assigns an available host port
protocol = "tcp"
}]
}])
}
With hostPort = 0, ECS assigns a random host port (typically in the 32768-65535 range) when the task starts. The ALB target group uses instance IP + dynamic port — the ECS service registration handles updating the target group automatically.
📝User-defined networks vs default bridge
Docker's default bridge network (docker0) has limited DNS resolution — containers on it can only find each other by IP, not by name (unless you use the legacy --link flag).
User-defined bridge networks solve this:
# Create a user-defined network
docker network create app-network
# Containers on the same network find each other by name
docker run -d --name postgres --network app-network postgres:16
docker run -d --name api --network app-network \
-e DB_HOST=postgres \ # resolves by container name
my-api:latest
Docker's embedded DNS server resolves postgres to the postgres container's IP on the app-network network. This works without --link and without knowing container IPs.
Multiple networks: a container can join multiple user-defined networks. This creates network segmentation — the web container can reach the api container, the api container can reach the database, but web cannot reach the database directly.
services:
web:
networks: [frontend]
api:
networks: [frontend, backend]
db:
networks: [backend]
networks:
frontend:
backend:
You're running two ECS tasks from the same task definition on a single EC2 instance. The task definition uses bridge network mode with hostPort=8080, containerPort=80. The second task fails to start. Why?
easyThe first task starts successfully and its container is running. The EC2 instance has sufficient CPU and memory for both tasks.
AECS doesn't support running multiple tasks from the same task definition on the same instance
Incorrect.ECS supports multiple tasks from the same task definition on the same instance. The issue is port binding, not task definition reuse.BThe second task can't bind to host port 8080 because the first task already holds that port — set hostPort=0 for dynamic port assignment
Correct!In bridge mode, the container binds to the specified host port on the EC2 instance's network interface. Port 8080 can only be bound once per host. The first task takes port 8080; the second task's container fails to start because the port is already in use. Fix: set hostPort=0 in the task definition to use dynamic port mapping. ECS assigns different ephemeral host ports to each task, and the ALB integration handles port registration automatically.Cawsvpc mode is required for running multiple tasks on the same instance
Incorrect.awsvpc mode gives each task its own ENI, avoiding port conflicts. But bridge mode with dynamic port mapping also supports multiple tasks — it's not limited to awsvpc.DThe EC2 instance's security group doesn't allow inbound traffic on port 8080
Incorrect.Security groups control inbound traffic from outside, not container-to-host port binding. The failure is a port collision on the host, not a security group issue.
Hint:What happens when two processes try to bind to the same host port?