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:18Format: -p HOST_PORT:CONTAINER_PORT
Docker Networks
Default Networks
docker network ls| Network | Purpose |
|---|---|
bridge | Default — containers can communicate via IP |
host | Container shares host's network (no isolation) |
none | No 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:5432Container 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-networkThe 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.
Docker Volumes (Recommended)
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 volumesBind 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 containerVolumes vs Bind Mounts
| Feature | Volumes | Bind Mounts |
|---|---|---|
| Managed by | Docker | You |
| Location | /var/lib/docker/volumes/ | Anywhere on host |
| Portability | High | Low (path-dependent) |
| Security | Better (Docker-managed) | Less (direct access) |
| Use case | Production data | Development |
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 1Practical 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:8080Summary
-p HOST:CONTAINERmaps 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.