Networking & Data Persistence

30 minLesson 3 of 5

Learning Objectives

  • Forward ports between host and containers
  • Create and manage Docker networks
  • Enable container-to-container communication
  • Persist data with Docker volumes and bind mounts

Port Forwarding

Containers have their own network stack. To access services from outside, map host ports to container ports:

# Map host port 8080 to container port 80
docker container run -d --name web -p 8080:80 nginx
 
# Now accessible at http://localhost:8080
curl http://localhost:8080
 
# Map multiple ports
docker container run -d --name app \
  -p 3000:3000 \
  -p 9229:9229 \
  node:18

Format: -p HOST_PORT:CONTAINER_PORT

Docker Networks

Default Networks

docker network ls
NetworkPurpose
bridgeDefault — containers can communicate via IP
hostContainer shares host's network (no isolation)
noneNo networking

Creating Custom Networks

Custom networks enable DNS-based container communication (by name):

# Create a network
docker network create app-network
 
# Run containers on the same network
docker container run -d --name api \
  --network app-network \
  my-api-image
 
docker container run -d --name db \
  --network app-network \
  -e POSTGRES_PASSWORD=secret \
  postgres:15
 
# 'api' can reach 'db' by name:
# Connection string: postgresql://postgres:secret@db:5432

Container Communication

# Containers on the SAME network can communicate by name
docker container exec api ping db  # Works!
 
# Containers on DIFFERENT networks cannot communicate
docker container exec other-container ping db  # Fails!

Network Inspection

docker network inspect app-network

The Host Network

Removes network isolation — container uses host's ports directly:

docker container run -d --network host nginx
# Nginx is now on host's port 80 directly (no -p needed)

Data Persistence

By default, data inside containers is ephemeral — lost when the container is removed.

Volumes are managed by Docker and persist independently of containers:

# Create a volume
docker volume create my-data
 
# Mount it to a container
docker container run -d --name db \
  --mount type=volume,src=my-data,dst=/var/lib/postgresql/data \
  postgres:15
 
# Data persists even after container removal
docker container rm -f db
 
# Reattach to a new container
docker container run -d --name db2 \
  --mount type=volume,src=my-data,dst=/var/lib/postgresql/data \
  postgres:15
# All data is still there!

Volume Commands

docker volume ls              # List volumes
docker volume inspect my-data # View details
docker volume rm my-data      # Delete volume
docker volume prune           # Remove unused volumes

Bind Mounts (Development)

Map a host directory directly into the container — great for development:

# Mount current directory into container
docker container run -d --name dev \
  -v $(pwd):/app \
  -p 3000:3000 \
  node:18
 
# Changes on host immediately visible in container

Volumes vs Bind Mounts

FeatureVolumesBind Mounts
Managed byDockerYou
Location/var/lib/docker/volumes/Anywhere on host
PortabilityHighLow (path-dependent)
SecurityBetter (Docker-managed)Less (direct access)
Use caseProduction dataDevelopment

Sharing Volumes Between Containers

# Create shared volume
docker volume create shared-data
 
# Container 1 writes
docker container run --rm \
  --mount type=volume,src=shared-data,dst=/data \
  ubuntu bash -c "echo 'Hello from container 1' > /data/message.txt"
 
# Container 2 reads
docker container run --rm \
  --mount type=volume,src=shared-data,dst=/data \
  ubuntu cat /data/message.txt
# Output: Hello from container 1

Practical Example: WordPress + MySQL

# Create network and volumes
docker network create wp-network
docker volume create wp-db
docker volume create wp-content
 
# Start MySQL
docker container run -d --name wp-db \
  --network wp-network \
  --mount type=volume,src=wp-db,dst=/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=rootpass \
  -e MYSQL_DATABASE=wordpress \
  -e MYSQL_USER=wpuser \
  -e MYSQL_PASSWORD=wppass \
  mysql:8.0
 
# Start WordPress
docker container run -d --name wp-app \
  --network wp-network \
  --mount type=volume,src=wp-content,dst=/var/www/html \
  -p 8080:80 \
  -e WORDPRESS_DB_HOST=wp-db \
  -e WORDPRESS_DB_USER=wpuser \
  -e WORDPRESS_DB_PASSWORD=wppass \
  -e WORDPRESS_DB_NAME=wordpress \
  wordpress:latest
 
# Access at http://localhost:8080

Summary

  • -p HOST:CONTAINER maps ports for external access
  • Custom networks enable DNS-based container communication
  • Containers on the same network can reach each other by name
  • Volumes persist data beyond container lifecycle (production)
  • Bind mounts map host directories into containers (development)
  • Volumes can be shared between multiple containers

Next Steps

Next, we'll build custom Docker images with Dockerfiles and push them to registries.