Container Networking, Volume Storage & Persistence
Version: 2.0.0
Purpose: Canonical lesson structure for Platform Engineering & AI Infrastructure Curriculum.
Required Inputs: Module definition, lesson objectives, project standards.
Outputs: Standards-compliant lesson markdown.
Lesson Metadata
- Lesson ID:
MOD-DOCKER-04 - Module: Containers & Docker (
MOD-DOCKER) - Difficulty: Intermediate to Advanced
- Estimated Duration: 55 minutes
- Learning Track: 🟢 Core
- Version: 2.0.0
- Last Updated: 2026-06-28
Lesson Overview
This lesson explores the master plumbing architectures of container runtimes, decrypting how Docker bridges isolated network namespaces to the physical wire and persists ephemeral container data across host storage drivers. By mastering Container Networking modes (bridge, host, none), Storage Mount types (Volumes, Bind Mounts, tmpfs), and terminal inspection tools (docker network, docker volume), you will firmly establish the elite infrastructure plumbing capabilities supporting our module capability: “I can build secure container images, orchestrate multi-container applications, manage volume persistence, and debug running containers.”
Learning Objectives
- Deconstruct the three master Docker Network drivers:
bridge(default virtual switch),host(shared host networking stack), andnone(air-gapped isolation). - Explain how Docker utilizes Linux
iptablesand Network Address Translation (NAT) to route external traffic into container bridge networks. - Contrast the three master Docker Storage mount types: Named Volumes (managed by Docker daemon), Bind Mounts (direct host filesystem mapping), and
tmpfs(ephemeral RAM storage). - Configure persistent database storage and live source code reloading using
docker run -v(and the modern--mountflag). - Inspect low-level network bridges and volume physical storage paths using
docker network inspectanddocker volume inspect.
Prerequisites
- Completion of
MOD-DOCKER-01,MOD-DOCKER-02, andMOD-DOCKER-03. - Foundational terminal networking and file system navigation skills (
ip route,ls -la,iptables).
Why This Exists
In Lessons 01 through 03, we explored how to isolate container namespaces, build minimal images, and orchestrate microservices with Docker Compose. However, a running container process is completely useless if it cannot communicate with the outside world or persist its data across reboots.
Imagine you are a Platform Engineer deploying a production Postgres database container (postgres:15). You start the container using a standard docker run -d postgres command without configuring any volume mounts or custom networks.
The database starts up beautifully. Your application connects to it and writes 50 Gigabytes of critical customer financial transactions into the database over three weeks.
One afternoon, the host server experiences a minor power fluctuation and reboots. When the Docker daemon restarts, your Postgres container is gone. You start a brand-new Postgres container (docker run -d postgres). When you inspect the database tables, every single customer financial transaction has completely vanished!
Furthermore, when you attempt to connect to the database from an external server, the connection fails because you don’t understand how Docker bridges virtual container IPs (172.17.0.2) to the physical host network interface (eth0).
When junior engineers encounter data loss or networking black holes in Docker, they frequently panic, blaming container runtimes as unstable. By mastering Container Networking and Volume Persistence mechanics, Platform Engineers can guarantee absolute data durability, architect flawless network routing tables, and ensure zero lost data in production.
Core Concepts
1. The Three Master Docker Network Drivers
When you start a container, Docker attaches its isolated network namespace to a specific network driver:
bridge(Default Virtual Switch): Docker creates a virtual software bridge (docker0) on the host server acting as a virtual network switch. Containers receive isolated private IP addresses (172.17.0.2). Containers on the same bridge can communicate, but require port binding (-p 8080:80) to receive traffic from the outside world!host(No Network Namespace!): The container completely bypasses network namespace isolation! It shares the physical host server’s networking stack directly! If your container runs Nginx on port 80, it binds directly to physical port 80 on the host server! Provides absolute maximum networking performance, but destroys port isolation!none(Air-Gapped Isolation): The container receives a network namespace, but Docker only configures a loopback interface (lo). It gets zero external network interfaces! Perfect for highly secure, air-gapped cryptographic processing containers!
[ Bridge Network (docker0) ] [ Host Network (--net=host) ]
┌───────────────────────────────┐ ┌───────────────────────────────┐
│ Container IP: 172.17.0.2:80 │ │ Container Process (Nginx) │
├───────────────────────────────┤ ├───────────────────────────────┤
│ Virtual Bridge Switch (docker0│ │ (No Network Namespace!) │
├───────────────────────────────┤ ├───────────────────────────────┤
│ Host IP: 192.168.1.50:8080 │ │ Host IP: 192.168.1.50:80 │
└───────────────────────────────┘ └───────────────────────────────┘2. Linux iptables and NAT Routing
How does traffic travel from the physical network wire (eth0) into a bridge container (172.17.0.2)? Docker dynamically programs the host Linux kernel’s Traffic Cop (iptables)!
- When you declare
-p 8080:80, Docker tells The Traffic Cop to intercept the Incoming Visitor. It rewrites the destination address and forwards them across The Internal Router (docker0 bridge)!
3. The Ephemeral Container Filesystem
When a container starts, it writes all file modifications into The Temporary Scratchpad.
- The Ephemeral Trap: This scratchpad is permanently tied to the lifecycle of the container wrapper! If you delete the container, Docker physically deletes the scratchpad! Any database tables, log files, or user uploads stored inside that layer are deleted forever!
4. The Three Master Storage Mount Types
To persist data safely outside the temporary scratchpad, Platform Engineers utilize three master storage mount types:
- The Safe Vault (Named Volumes): The absolute industry standard for database persistence! Docker creates a dedicated storage folder inside its own managed root directory. Volumes are completely decoupled from container lifecycles, surviving container terminations flawlessly!
- The Direct Folder Link (Bind Mounts): You map a direct physical folder path from the host server directly into the container. Exceptional for local developer laptops where you want live source code modifications to instantly reload inside the container!
- The Memory Stick (tmpfs Mounts): Docker creates a temporary file system stored exclusively in your computer’s physical RAM. It never touches the physical hard drive! Excellent for storing highly sensitive, ephemeral API secret keys or temporary cache files!
5. The Modern --mount Syntax vs. Legacy -v
When attaching storage to a container, Docker supports two CLI flags:
-v my_volume:/app/data: The legacy shorthand syntax. Quick to type, but combines all options into a confusing, colon-separated string.--mount type=volume,source=my_volume,target=/app/data: The modern, highly explicit, canonical standard! Clearly separates mount types, sources, targets, and read-only flags (readonly). Platform Engineers strictly mandate--mountfor production automation scripts!
Architecture
This layered diagram clarifies the interactions between the host system and the running container. Starting at Layer 4, external networking traffic arrives at the host. Layer 3 manages traffic rules that seamlessly route the network packets to Layer 2, where the isolated container processes reside. Finally, when the container needs to save data persistently, it connects to Layer 1, utilizing robust storage mechanisms like Named Volumes or Bind Mounts directly on the host filesystem.
Real-World Example
Imagine you are a Lead Site Reliability Engineer managing a high-frequency trading platform. Your trading application microservice requires sub-millisecond networking latency to execute stock buy orders, and needs to persist terabytes of historical trading logs without running out of disk space.
A junior engineer deploys the microservice using the default bridge network driver and uses a standard Bind Mount pointing to a slow network file share.
When the trading markets open, the application encounters severe latency. Because traffic must pass through the virtual docker0 bridge switch and execute complex iptables NAT prerouting translations for every single stock order packet, networking latency spikes by 5 milliseconds, causing your company to lose out on critical stock trades! Furthermore, the bind mount crashes due to file permission mismatches (Permission denied).
Because you understand container plumbing perfectly, you forcefully refactor the deployment architecture. You transition the trading microservice to the host Network Driver (--network=host). By completely bypassing network namespace isolation, the microservice attaches directly to the physical host network card (eth0), completely eliminating iptables NAT overhead and dropping networking latency to sub-millisecond perfection!
Finally, you transition the storage architecture to a Named Volume (--mount type=volume...) managed directly by the Docker daemon on high-speed NVMe storage. Your trading platform executes orders instantly, logs terabytes of data flawlessly, and achieves pristine production stability!
Hands-on Demonstration
Let’s look at how an engineer inspects network bridges using docker network inspect, inspects named volume storage paths using docker volume inspect, and launches containers using the modern --mount syntax.
Input 1: Inspecting Network Bridges and Virtual Subnets
We use docker network inspect to view the pristine JSON metadata block defining our virtual bridge switch, IP subnet ranges, and attached container endpoints.
Code 1
# Inspect the low-level JSON metadata of the default bridge network.
# (We simulate inspecting the clean JSON output of docker network inspect bridge)
docker network inspect bridge 2>/dev/null | grep -A 15 "IPAM" || cat << 'EOF'
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"Containers": {
"8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d": {
"Name": "production-database",
"EndpointID": "ab12cd34ef567890ab12cd34ef567890",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
}
EOFExpected Output 1
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"Containers": {
"8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d": {
"Name": "production-database",
"EndpointID": "ab12cd34ef567890ab12cd34ef567890",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
}Explanation 1
Look at how beautifully structured Docker’s virtual switch is! Let’s deconstruct the core JSON keys:
"Subnet": "172.17.0.0/16": The isolated private IP subnet range managed by thedocker0bridge!"Gateway": "172.17.0.1": The virtual gateway IP address assigned to the host server’s virtual switch interface!"IPv4Address": "172.17.0.2/16": The isolated virtual IP address assigned to our runningproduction-databasecontainer endpoint!
Input 2: Inspecting Named Volumes and Physical Mount Paths
We use docker volume inspect to view the pristine JSON metadata block defining our named volume, verifying the exact physical host storage path (Mountpoint).
Code 2
# Inspect the low-level JSON metadata of a named storage volume.
# (We simulate inspecting the clean JSON output of docker volume inspect pgdata)
docker volume inspect pgdata 2>/dev/null || cat << 'EOF'
[
{
"CreatedAt": "2026-06-28T12:00:00Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/pgdata/_data",
"Name": "pgdata",
"Options": {},
"Scope": "local"
}
]
EOFExpected Output 2
[
{
"CreatedAt": "2026-06-28T12:00:00Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/pgdata/_data",
"Name": "pgdata",
"Options": {},
"Scope": "local"
}
]Explanation 2
Notice how perfectly secure Docker’s named volume storage is! Let’s deconstruct the core JSON key:
"Mountpoint": "/var/lib/docker/volumes/pgdata/_data": The exact physical folder path on the host server’s hard drive where Docker stores our database tables! Because this folder sits inside/var/lib/docker/, it is completely protected from accidental deletion by non-root system users!
Hands-on Lab
- Objective: Create custom bridge networks, create named volumes, launch containers using
--mountsyntax, verify data persistence across container deletions, and verify network isolation. - Estimated Time: 20 minutes
- Difficulty: Intermediate to Advanced
- Environment: Interactive Browser Terminal / Local Sandbox (with Docker installed)
Step-by-step Instructions
- Open your terminal sandbox and create a custom bridge network:
docker network create isolated-net. - Type
docker volume create persistent-storeto create a brand-new named storage volume. - Launch a container attached to your custom network and volume using the modern
--mountsyntax:
docker run -d --name db-writer --network=isolated-net --mount type=volume,source=persistent-store,target=/app/data alpine:latest /bin/sh -c "echo 'CRITICAL_DATABASE_TRANSACTION_99' > /app/data/ledger.txt && sleep 3600"- Type
docker exec -it db-writer cat /app/data/ledger.txtto verify the critical data was successfully written to the mount target! - Type
docker rm -f db-writerto forcefully stop and delete the container wrapper! (Junior engineers would panic, assuming the data is lost!). - Launch a brand-new container attached to the exact same named volume:
docker run --rm --mount type=volume,source=persistent-store,target=/app/data alpine:latest cat /app/data/ledger.txt- Verify that your brand-new container successfully outputs
CRITICAL_DATABASE_TRANSACTION_99, proving absolute volume persistence!
Verification
docker volume ls | grep "persistent-store"If your terminal successfully outputs local persistent-store, you have mastered volume persistence and storage decoupling!
Troubleshooting
- Issue:
docker runfails withinvalid mount config for type "volume": invalid mount target, must be an absolute path. - Solution: In the
--mountflag, you specified a relative path for thetarget(e.g.,target=app/data). Docker strictly mandates that container mount targets must be absolute paths starting with a forward slash (target=/app/data)!
Cleanup
# Safely remove the demonstration volume and custom network
docker volume rm persistent-store 2>/dev/null || true
docker network rm isolated-net 2>/dev/null || trueProduction Notes
In enterprise Kubernetes environments, understanding Named Volumes is critical to grasping Persistent Volume Claims (PVCs) and Container Storage Interface (CSI) drivers. While Docker named volumes store data on the local host server’s hard drive (/var/lib/docker/), in a 50-node Kubernetes cluster, if a Pod moves from Worker Node A to Worker Node B, it loses access to local disk storage! Platform Engineers solve this by deploying CSI drivers (e.g., AWS EBS / EFS CSI), which dynamically provision cloud block storage and mount it across physical worker nodes over the network!
Common Mistakes
- Using Bind Mounts for Database Persistence: Beginners frequently use
-v /home/user/pgdata:/var/lib/postgresql/datafor database storage. This creates catastrophic file permission errors (Permission denied) because the host user (UID 1000) and the container postgres user (UID 999) clash over folder ownership! Always use Named Volumes for database storage! - Running Port Bindings with
--network=host: Junior developers frequently executedocker run --network=host -p 8080:80 nginx. Docker will output a loud warning:Published ports are discarded when using host network mode. Becausehostmode completely bypasses network namespaces, port mapping (-p) is physically impossible!
Failure-Driven Learning
Imagine a junior engineer attempts to start a container using a bind mount pointing to a host directory that does not exist or lacks correct read/write execution permissions, causing the container to instantly crash on startup.
Simulated Failure
# Simulating a container startup failure due to a bind mount permission mismatch
# (We simulate the exact Docker CLI error when mounting an inaccessible host directory)
echo -e "docker: Error response from daemon: error while creating mount source path '/root/secret_app': mkdir /root/secret_app: permission denied.\n# ERRO[0000] error waiting for container: context canceled"Output
docker: Error response from daemon: error while creating mount source path '/root/secret_app': mkdir /root/secret_app: permission denied.
# ERRO[0000] error waiting for container: context canceledDiagnosis & Recovery
Why did this fail? Look at this clear system error: mkdir /root/secret_app: permission denied! When you declare a bind mount (-v /root/secret_app:/app), if the host directory does not exist, the Docker daemon attempts to automatically create it. However, if your terminal user lacks physical Linux filesystem permissions to access or write to that host directory (e.g., attempting to mount a folder inside /root as a non-root user), the Linux kernel blocks the operation and crashes the container startup! To recover, the engineer must modify the bind mount source to point to a clean, accessible user directory (-v /home/user/app:/app), and the container starts flawlessly!
Engineering Decisions
Storage Persistence: Named Volumes vs. Bind Mounts vs. Cloud Object Storage (S3)
When architecting an enterprise application, engineering leaders must choose where data is persisted.
- Named Volumes (
--mount type=volume): Managed by the Docker daemon in/var/lib/docker/. Fully protected from host permission clashes. Excellent for single-server database tables and application caches. - Bind Mounts (
--mount type=bind): Directly maps a host folder. Excellent for local developer laptops to enable live code reloading. However, highly insecure and fragile for production environments. - Cloud Object Storage (AWS S3 / Google Cloud Storage): The ultimate Platform Engineering standard! Applications completely bypass local container filesystem storage, writing user uploads and state directly to cloud object storage APIs over the network! Enables stateless container architectures that can auto-scale infinitely!
- The Platform Decision: Platform Engineers mandate Named Volumes for single-node development databases, while strictly enforcing Cloud Object Storage (S3) for all production application file persistence to guarantee stateless microservice auto-scaling.
Best Practices
- Master
docker volume prune: When your Docker engine accumulates dozens of abandoned storage volumes over months of development, executedocker volume prune. It safely inspects your engine database and permanently deletes all named volumes that are not currently attached to an active container! - Leverage
tmpfsfor Sensitive Keys: When running an AI inference container that requires a highly sensitive, short-lived API key, pass the key into atmpfsmount (--mount type=tmpfs,destination=/app/secrets). Becausetmpfsexists exclusively in system RAM, if the host server is compromised or powered off, the secret key vanishes instantly without leaving a trace on physical disk!
Troubleshooting Guide
Issue 1: “docker: Error response from daemon: network not found” vs. “docker volume in use”
- Cause: You attempt to launch containers on custom networks or delete storage volumes, but encounter missing resource errors or active dependency locks.
- Diagnosis & Solution:
network not found: You declared--network=backend-netin yourdocker runcommand, but the custom bridge network completely does not exist in the Docker engine! Docker cannot attach a container to a non-existent virtual switch. To fix, create the network first:docker network create backend-net!docker volume in use: You attempted to executedocker volume rm pgdata, but Docker forcefully rejected the deletion. This occurs because an existing container wrapper (even a stopped container!) is still actively linked to this volume! To fix, inspectdocker ps -a, remove the stopped container wrapper (docker rm [container]), and then executedocker volume rm!
Summary
bridgenetworks create virtual switches (docker0);hostnetworks share the physical host networking stack;noneprovides air-gapped isolation.- Linux
iptablesuses NAT prerouting rules to forward external host port traffic (-p 8080:80) into container network namespaces. - Named Volumes are managed by the Docker daemon in
/var/lib/docker/volumes/and survive container deletions flawlessly. - Bind Mounts map direct host folders (
/home/user/app), making them perfect for live source code reloading on developer laptops. tmpfsmounts store ephemeral data exclusively in host server physical RAM, never touching physical hard drives.
Cheat Sheet
# Create a custom virtual bridge network switch in the Docker engine
docker network create [network_name]
# Inspect the low-level JSON metadata and attached containers of a network
docker network inspect [network_name]
# Connect an actively running container to an existing custom network bridge
docker network connect [network_name] [container_name]
# Create a brand-new named storage volume managed by the Docker daemon
docker volume create [volume_name]
# Inspect the low-level JSON metadata and physical host Mountpoint of a volume
docker volume inspect [volume_name]
# Launch a container with a Named Volume using the modern explicit --mount syntax
docker run -d --name [name] --mount type=volume,source=[vol],target=[path] [image]
# Launch a container with a Bind Mount using the modern explicit --mount syntax
docker run -d --name [name] --mount type=bind,source=[host_path],target=[path] [image]
# Launch a container with a tmpfs RAM mount using the modern explicit --mount syntax
docker run -d --name [name] --mount type=tmpfs,destination=[path] [image]
# Forcefully cleanup and delete all unused custom networks and abandoned volumes
docker network prune -f && docker volume prune -fKnowledge Check
Multiple Choice Questions
- A developer starts a container using
docker run -d --name myapp --network=host -p 8080:80 nginx. When they inspectdocker ps, they notice the port mapping8080->80is completely missing, and Nginx is actively listening on physical port 80. Why did this happen?- A) Nginx crashed.
- B) The developer forgot to create a named volume.
- C) Because
--network=hostcommands the container to completely bypass network namespace isolation and share the host networking stack directly, port binding (-p 8080:80) is physically impossible and discarded by the daemon. - D) Docker requires
iptablesto be disabled.
Scenario Questions
You are deploying an AI inference container that generates temporary cache files. You want to ensure these cache files are stored exclusively in the host server’s physical RAM and never touch the physical hard drive. Based on what you learned in this lesson, what exact --mount type do you append to your docker run command?
Short Answer Questions
Explain the exact architectural difference between where Docker stores data for a Named Volume versus where it stores data for a Bind Mount on the host filesystem.
Interview Preparation
Beginner Questions
- What is a Docker named volume?
- What is the difference between
bridgeandhostnetwork drivers? - What does
docker volume prunedo?
Intermediate Questions
- Explain how Docker utilizes Linux
iptablesto route external traffic into a container bridge network. - Why is the modern
--mountsyntax architecturally superior to the legacy-vflag?
Advanced Questions
- Explain how Docker utilizes the Container Network Model (CNM) to manage Sandboxes, Endpoints, and Networks, and describe how the
veth(virtual ethernet) pair establishes a tunnel between the hostdocker0bridge and the container’s isolatedeth0interface.
Scenario-Based Discussions
- Discuss the architectural trade-offs of managing persistent database storage for a highly available enterprise microservice application using local Docker Named Volumes versus migrating the database entirely to a fully managed cloud database service (e.g., AWS RDS / Google Cloud SQL), specifically addressing backups, failover, and storage scaling.
View Answers
Beginner
- [Docker named volume]: A storage mechanism fully managed by the Docker daemon (typically stored in
/var/lib/docker/volumes/). It persists data securely outside the container’s ephemeral scratchpad and survives container deletions flawlessly. - [
bridgevshostnetworks]:bridgecreates an isolated virtual network namespace for the container and requires port bindings to communicate with the outside world.hostcompletely disables network isolation, attaching the container directly to the physical host’s networking stack for maximum performance, but risking port collisions. - [
docker volume prune]: It scans the Docker engine and permanently deletes all named volumes that are not currently attached to any existing container, freeing up disk space.
Intermediate
- [
iptablesrouting]: When a container uses abridgenetwork and publishes a port (-p 8080:80), Docker dynamically injects Network Address Translation (NAT) prerouting rules into the host’siptables. When external traffic hits host port 8080,iptablesintercepts it and forwards it across the virtualdocker0bridge directly to the container’s isolated internal IP on port 80. - [
--mountvs-v]: The-vflag merges multiple complex configurations (source, target, read-only status) into a single, confusing colon-separated string.--mountuses explicit key-value pairs (e.g.,type=volume,source=myvol,target=/data,readonly), making infrastructure-as-code scripts far more readable, strict, and predictable.
Advanced
- [CNM and
vethpairs]: The Container Network Model (CNM) defines three components: the Sandbox (the isolated network namespace), the Endpoint (the network interface inside the Sandbox), and the Network (the virtual switch/bridge). Docker connects the Sandbox to the Network using aveth(virtual ethernet) pair—a virtual wire. One end of the wire sits inside the container’s namespace aseth0, and the other end sits in the host’s root namespace attached to thedocker0bridge, allowing packet transmission between the isolated environments.
Scenario-Based Discussions
- [Local Named Volumes vs Cloud Managed DBs]: Using local Docker Named Volumes is cheap and excellent for single-server development. However, achieving high availability across multiple nodes is extremely difficult, as local volumes don’t easily failover or replicate. Migrating to a fully managed cloud database (AWS RDS) offloads the complex operational overhead of automated backups, multi-AZ replication, failover routing, and storage auto-scaling to the cloud provider, making it the superior architectural choice for critical enterprise production workloads.