User-defined bridge networks provide automatic DNS resolution and better isolation than attaching every container to the default bridge. This lab connects an Nginx frontend to a small HTTP backend without publishing the backend port.
1. Create an application network
docker network create --driver bridge app-net
docker network ls
docker network inspect app-net
2. Start a private backend
docker run -d --name backend --network app-net
python:3.13-alpine
sh -c 'mkdir -p /srv && echo backend-ok > /srv/index.html && python -m http.server 8000 -d /srv'
Port 8000 is exposed only inside the container network. Confirm service-name DNS from a disposable client:
docker run --rm --network app-net curlimages/curl:8.14.1
-fsS http://backend:8000
3. Add a frontend reverse proxy
mkdir -p "$HOME/docker-network-demo"
cat > "$HOME/docker-network-demo/default.conf" <<'EOF'
server {
listen 80;
location / {
proxy_pass http://backend:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
EOF
docker run -d --name frontend --network app-net
-p 127.0.0.1:8080:80
--mount type=bind,source="$HOME/docker-network-demo/default.conf",target=/etc/nginx/conf.d/default.conf,readonly
nginx:1.28-alpine
curl http://127.0.0.1:8080
4. Inspect addresses and port mappings
docker network inspect app-net
docker inspect backend --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'
docker port frontend
sudo ss -lntp | grep ':8080'
Containers should communicate by DNS name, not by an IP that can change after recreation. Binding the published port to 127.0.0.1 prevents direct external access.
5. Connect and disconnect networks
docker network create admin-net
docker network connect admin-net backend
docker inspect backend --format '{{json .NetworkSettings.Networks}}'
docker network disconnect admin-net backend
6. Troubleshoot connectivity
docker logs backend
docker logs frontend
docker exec frontend getent hosts backend
docker exec frontend wget -qO- http://backend:8000
docker inspect app-net --format '{{json .Containers}}'
Check in order: both containers are running, both share a network, DNS resolves the service name, the application listens on the expected container port, then the host publishes only the intended frontend port.
7. Clean up
docker rm -f frontend backend
docker network rm app-net admin-net
rm -rf "$HOME/docker-network-demo"
Security notes
- Publishing
0.0.0.0:PORTexposes a port on every host interface. - Do not publish database ports unless external clients truly need them.
- Docker-managed iptables rules interact with host firewall policy; test the effective path.
- Use separate frontend and backend networks for multi-tier stacks.
References: Docker documentation and the Server World topic index.