Lifecycle of a network
docker network create app-net # bridge driver is the default
docker network create --subnet 172.30.0.0/16 \
--gateway 172.30.0.1 data-net # choose the IP range
docker run -d --name api --network app-net nginx:1.27
docker network connect data-net api # attach a second network
docker network disconnect data-net api # detach it; api keeps running
docker network rm data-net # remove once no container uses it
flowchart LR API["api"] --- AN["app-net 172.18.0.0/16"] API --- DN["data-net 172.30.0.0/16"] WEB["web"] --- AN DB["db"] --- DN
--networkattaches the container when it is created; repeat it to attach several networks.docker network connect NETWORK CONTAINER: the network first, then the container. A container on several networks (multi-homed) has one interface and IP per network.docker network disconnectremoves the interface at once; the container is not stopped.docker network rmfails withhas active endpointswhile containers are attached: disconnect or remove them first.-fonly ignores a missing network; it cannot force removal.
docker create vs docker run
docker create --name my-nginx --network app-net -p 8080:80 nginx:1.27 only creates the container (state Created) without starting it, so docker ps does not show it. Run docker start my-nginx. docker run = create + start.
| Command | Meaning |
|---|---|
docker network create app-net |
Create a user-defined bridge |
docker run --network app-net … |
Attach when creating a container |
docker network connect app-net web |
Attach a running container |
docker network disconnect app-net web |
Detach a container from a network |
docker network rm app-net |
Remove an empty network |
Name resolution on a user-defined bridge
Docker runs an embedded DNS server at 127.0.0.11 inside each container on a user-defined network. It answers container names and network aliases with the right IP, and forwards other names to the host's resolvers. Add an alias so several names reach one container, or so several containers share one name for simple round-robin:
docker run -d --name db1 --network app-net --network-alias db postgres:16
docker exec api getent hosts db
Useful options
| Option | Effect |
|---|---|
--ip 172.30.0.50 |
Fixed IP for a container (only on networks you created with a subnet) |
--internal |
Network with no route outside the host, for back-end tiers |
--opt com.docker.network.bridge.name=br-app |
A readable bridge name on the host |
--label team=web |
Metadata for filtering with docker network ls -f label=team=web |
An internal network is a simple way to make sure a database container can be reached by the app but never initiate connections to the internet.
Compose does this for you
docker compose up creates a network called <project>_default and attaches every service to it, so services reach each other by service name. You can declare extra networks in the Compose file to split front-end and back-end tiers.
Debugging connectivity
Minimal images often lack ping, curl, or dig. Instead of installing tools in the app image, start a debugging container that shares its network namespace:
docker run --rm -it --network container:api nicolaka/netshoot
Inside it you can run curl, dig, tcpdump, and ss exactly as the app container sees the network.
Housekeeping
docker network prune removes networks no container uses. docker network inspect app-net --format '{{range .Containers}}{{.Name}} {{.IPv4Address}}{{println}}{{end}}' lists each attached container with its address.