skip to content

Container-to-Container Patterns

Wiring multi-container setups by hand: creating networks, attaching one container to several, sharing another container's network namespace for a debug sidecar, and reaching a service on the host. Scenario questions here test practical connectivity reasoning.

part ofDockeroverview, primer and where to startread it →
on this pageshow

questions

4

Walk through how you would put two containers on the same Docker network, attach a third container to that network after it is already running, and later detach it. What does membership in a Docker network give a container, and what keeps it isolated from containers on a different network?

level: juniorimportance: must knowfreq 68%

answer

  1. veth pair + bridge + IP from subnet
  2. create / connect (live) / disconnect / inspect
  3. same network = all ports open, no -p needed
  4. DOCKER-ISOLATION-STAGE-1/2 drops cross-bridge
  5. default bridge = flat, no DNS, --link legacy

basics

~20 s

Run docker network create appnet, then start containers with --network appnet. A running container is attached later with docker network connect appnet NAME and removed with docker network disconnect. Membership gives an interface and IP on that bridge, so members reach each other on any port. Docker's isolation iptables rules block traffic between different bridges.

solid answer

~50 s

I create a user-defined bridge, `docker network create appnet`, and start both containers with `--network appnet`. Joining gives each container a virtual interface and an IP on that bridge subnet, so it can reach any other member on **any port** directly. Publishing ports with `-p` is only for host-to-container traffic and is not needed between containers. A running container can be attached live: `docker network connect appnet worker` adds a second interface with no restart; `docker network disconnect appnet worker` removes it, breaking connections that rode that interface. `docker network inspect appnet` lists members and their addresses. Isolation is the other half: each user-defined bridge is its own segment with its own subnet, and Docker installs DOCKER-ISOLATION-STAGE-1/2 iptables rules that drop forwarded traffic between bridges. A container on appnet cannot reach one on otherapp even by raw IP. That is why the network is the natural unit of segmentation on a single host.

code

bash · 9 lines
bash
docker network create appnet
docker run -d --name api --network appnet myapi:1.0
docker run -d --name db  --network appnet postgres:16

# attach an already-running container
docker network connect appnet worker
docker network disconnect appnet worker

docker network inspect appnet --format '{{json .Containers}}'

go deeper

for a junior

Know the three commands (create, run --network, connect/disconnect) and that same-network containers talk on any port without -p.

for a middle

Explain the veth-plus-bridge mechanics, that connect works on a running container, and that isolation is enforced by iptables rules rather than by convention.

for a senior

Discuss subnet planning and collisions with corporate ranges, the disruption of disconnecting a live container, and using networks as the segmentation boundary instead of publishing ports.

for a principal

Frame networks as the policy unit: which tiers share a segment, how that maps onto Compose or an orchestrator later, and what the single-host bridge model cannot express.

## The model A Docker bridge network is a Linux bridge device on the host plus an address pool. When a container joins, Docker creates a veth pair: one end becomes the container's `eth0` inside its own network namespace, the other is plugged into the bridge. The container gets an IP from the network's subnet and a default route pointing at the bridge address. Everything else follows from that. ## Creating and attaching `docker network create appnet` makes a bridge network with an auto-chosen subnet (override with `--subnet`/`--gateway`). `docker run --network appnet ...` starts a container already attached. `docker network connect appnet worker` attaches an **already running** container by hot-plugging a new interface into its namespace, and `docker network disconnect appnet worker` removes it. `docker network ls` lists networks, `docker network inspect appnet` shows the subnet and the attached containers, `docker network prune` deletes unused ones. A network cannot be removed while containers are attached. A container may belong to several networks at once, in which case it has one interface and IP per network. That is the basis of the multi-homed/segmentation pattern. ## What membership buys Within one network, every container can reach every other container on every port the process is listening on. There is no per-port gate: `-p` publishing exists to expose a container to clients on the host or beyond, not to permit container-to-container traffic. Newcomers commonly publish ports purely so their app can talk to its database; that is unnecessary and widens the attack surface. Membership also gets the container a name entry in Docker's embedded resolver, so peers can be addressed by container name rather than by IP. ## What isolation means Two user-defined bridges are separate L2 domains with separate subnets, so there is no direct path between them. Docker also programs iptables chains named DOCKER-ISOLATION-STAGE-1 and STAGE-2 that DROP forwarded packets whose input and output bridges differ. So even if a container guesses another network's subnet and adds a route, the host will not forward the packet. Isolation is host-level and does not depend on the application. The legacy default bridge (`docker0`, the network literally named `bridge`) is different in one important way: containers there share one flat network and get no name resolution, so people historically used the deprecated `--link` flag. Modern advice is to always create your own network. ## Compose and lifecycle Docker Compose creates one project network by default and attaches every service to it, which is why Compose services can talk to each other with no configuration. Extra networks can be declared under the top-level `networks:` key and referenced per service. Operationally, remember that networks are host-scoped for the bridge driver (multi-host requires overlay/swarm), that subnets can collide with corporate ranges — fix with `--subnet` or daemon `default-address-pools` — and that disconnecting a network from a live container is disruptive to open sockets. Attaching is safe; detaching is not.

  • Do containers on the same user-defined bridge need published ports to talk to each other?
    No. Publishing with -p only creates a host-side NAT mapping for traffic arriving at the host. Containers on a shared network route to each other directly over the bridge and can reach every listening port. Publishing a database port just to let the app connect is a common and unnecessary exposure.
  • Can you change a running container's networks without restarting it?
    Yes for attaching: docker network connect hot-plugs a new interface and IP into the running container's namespace. docker network disconnect likewise removes one, but any sockets bound to or routed through that interface break. What you cannot change live is the network mode itself, such as switching a container from bridge to host.

A network is a patch panel: plugging a container in gives it a port and an address on that switch; two different switches with no uplink cannot see each other.

saying these in an interview costs you the question

  • Thinking -p is required for container-to-container traffic
  • Believing containers on different Docker networks can reach each other by IP
  • Reaching for the deprecated --link instead of a user-defined network
  • Assuming a bridge network spans multiple hosts (that needs overlay)
  • Claiming a container can only ever be on one network

context

open as a page

A process inside a container needs to reach a service running directly on the Docker host, for example a database listening on the host's port 5432. Explain the special DNS name host.docker.internal: what it resolves to, where it works out of the box, and what you do on a platform where it does not exist.

level: middleimportance: should knowfreq 50%

basics

~20 s

host.docker.internal is a name Docker injects that resolves to the host from inside a container. It exists automatically on Docker Desktop (macOS/Windows). On plain Linux you must add it yourself with --add-host=host.docker.internal:host-gateway, and the host service must listen on an address the container can reach, not only 127.0.0.1.

open as a page

What does starting a container with Docker's --network container:<name> flag do? Explain exactly what is shared and what is not shared between the two containers, and give a case where you would use it.

level: seniorimportance: should knowfreq 42%

basics

~20 s

The new container joins the existing container's network namespace instead of getting its own. They share interfaces, IP, ports and loopback, so they reach each other on 127.0.0.1 and cannot both bind the same port. Filesystem, processes and users stay separate. It is the sidecar pattern, useful for debug and proxy containers.

open as a page

You are designing the Docker network layout for a multi-tier application on a single host: a public-facing reverse proxy, an internal API, and a database. How do you arrange networks so the database is reachable only by the API, what does attaching one container to two networks buy you, and how does Docker's --internal network option fit in?

level: principalimportance: should knowfreq 36%

basics

~20 s

Use one network per trust boundary: edge (proxy + API) and data (API + database). The API is multi-homed on both; the proxy never joins data, so it cannot reach the database at all. Publish ports only on the proxy. Mark the data network --internal to remove its external route. Networks, not published ports, are the boundary.

open as a page