Docker Compose, Registry, and Networking: Multi-Container Setups
The Docker Compose, Docker Registry, and Docker Networking exercises cover multi-container orchestration, image registries, and network drivers. These exercises appear across 4 courses. This article covers common failures and how to fix them.
Table of Contents
- Docker Compose: Containers Exiting with Code 0
- Docker Compose File Location Matters
- Docker Registry: Tagging Before Push
- Docker Registry: Insecure Registry Error
- Docker Hub Login and Push
- Network Drivers: Bridge, Macvlan, None
- Removing a Network with Active Containers
- Common Questions
Docker Compose: Containers Exiting with Code 0
No Main Process Means Instant Exit
After docker compose up -d, containers may immediately show Exited (0):
$ docker compose ps -a
NAME STATUS
myubuntu Exited (0) 5 seconds ago
myalpine Exited (0) 5 seconds ago
This happens because the base images (ubuntu, alpine) have no default foreground process.
Fix: Add a process to keep the container running. Options include:
services:
ubuntu:
image: ubuntu:24.04
stdin_open: true
# or
command: sleep infinity
The stdin_open: true flag (equivalent to -i) keeps stdin open, preventing the container from exiting.
Docker Compose File Location Matters <a name="compose-location>
Compose Looks for docker-compose.yml in Current Directory
cd ~/ && docker compose up -d
If you run docker compose up from the wrong directory, it won't find the compose file. The exercise typically asks you to create the file at /opt/docker-compose.yml:
docker compose -f /opt/docker-compose.yml up -d
Fix: Always specify -f /path/to/docker-compose.yml or cd to the directory containing the file.
Compose YAML Structure
name: pdso-training
services:
webserver:
image: nginx
container_name: webserver
ports:
- 8080:80
volumes:
- data:/usr/share/nginx/html
volumes:
data:
Common mistake: Incorrect indentation under ports and volumes lists. YAML is strict about indentation.
Docker Registry: Tagging Before Push
Image Must Be Tagged with Registry URL
You can't push an image to a registry without first tagging it with the registry address:
# Start local registry:
docker run -d -p 5000:5000 --restart=always --name registry registry:2
# Tag the image with registry URL prefix:
docker tag django.nv:1.0 localhost:5000/django.nv:1.0
# Now push:
docker push localhost:5000/django.nv:1.0
Common mistake: Trying to push django.nv:1.0 directly without the localhost:5000/ prefix. Docker doesn't know which registry to push to.
Verify the Push
curl localhost:5000/v2/_catalog
# Output: {"repositories":["django.nv"]}
Docker Registry: Insecure Registry Error <a name="registry-insecure>
Local Registry Uses HTTP, Not HTTPS
A local registry on localhost:5000 uses plain HTTP. Docker by default refuses to push to non-TLS registries:
http: server gave HTTP response to HTTPS client
Fix: For lab environments, configure Docker to trust the insecure registry by adding to /etc/docker/daemon.json:
{
"insecure-registries": ["localhost:5000"]
}
Then restart Docker: systemctl restart docker. In the lab environment, this is typically pre-configured.
Docker Hub Login and Push <a name="dockerhub-push>
Login to Docker Hub
docker login
# or
docker login -u your-docker-username -p your-docker-password
The exercise verifies login by checking for /root/.docker/config.json.
Push to Docker Hub Requires Username Prefix
Docker Hub images must be prefixed with your username:
docker tag django.nv:1.0 yourdockerusername/django.nv:1.0
docker push yourdockerusername/django.nv:1.0
Common mistake: Trying to push django.nv:1.0 without the username prefix. Docker Hub rejects pushes to images you don't own.
Network Drivers: Bridge, Macvlan, None
Network Driver Comparison
| Driver | Use Case | External Access |
|---|---|---|
| bridge (default) | Isolated container networking with NAT | Port mapping required |
| macvlan | Containers get their own MAC addresses, appear as physical devices | Direct IP on network |
| none | Complete network isolation | None |
none Network = No Connectivity
docker run -d --name ubuntu --network=none -it ubuntu:24.04
docker exec ubuntu apt update
Temporary failure resolving 'archive.ubuntu.com'
This is expected behavior — the container has no network stack.
Bridge Network with Custom Subnet
docker network create app --subnet "172.16.0.0/16"
Verify:
docker inspect app | jq '.[].IPAM.Config'
Removing a Network with Active Containers
Can't Remove a Network with Connected Containers
docker network rm app
Error response from daemon: error while removing network: network app id xxx has active endpoints
Fix: Disconnect or remove the container first:
docker network disconnect app myubuntu
# or
docker stop myubuntu && docker network rm app
Key concept: Removing a network doesn't automatically disconnect or stop attached containers.
Connecting a Container to a Network After Creation
docker network connect app myubuntu
Verify:
docker inspect myubuntu | jq '.[].NetworkSettings.Networks.app'
Common Questions
| Question | Answer |
|---|---|
| My compose containers exit immediately. | Add stdin_open: true or command: sleep infinity to keep them running. |
docker push to localhost:5000 fails with HTTPS error. |
Configure Docker's insecure-registries or check that the lab environment has it pre-configured. |
| How do I verify an image was pushed to my local registry? | Run curl localhost:5000/v2/_catalog. |
| What happens to containers when I remove their network? | Nothing. Containers keep running. Remove or disconnect them first. |
| My container can't reach the internet. | Check which network it's attached to. --network=none means no connectivity. |
| How do I create a network with a specific subnet? | docker network create <name> --subnet "172.16.0.0/16". |
Wrap-Up
Docker Compose, Registry, and Networking exercises cover multi-container orchestration:
- Compose containers need a foreground process — use
stdin_open: trueorcommand: sleep infinity. - Always tag images with the registry URL before pushing (
localhost:5000/image:tag). - Docker Hub requires your username prefix on image names.
- Bridge is the default network driver; none means zero connectivity; macvlan gives containers physical-network-level addresses.
- You can't remove a network while containers are connected to it.
The DevSecOps Box is stateless — all networks, containers, and images are lost on page refresh.