auto-update-daily-20260202

Infrastructure Workflow

Manage Docker/Podman networking, storage (volumes), and container registries.

Quick Start

Common infrastructure operations for container deployment:

# Network operations
docker network create myapp-net
docker network connect myapp-net container_name

# Volume operations
docker volume create myapp-data
docker run -v myapp-data:/data myapp

# Registry operations
docker login ghcr.io
docker tag myapp:latest ghcr.io/username/myapp:latest
docker push ghcr.io/username/myapp:latest

Quick commands reference:

# List infrastructure
docker network ls
docker volume ls
docker images

# Inspect infrastructure
docker network inspect myapp-net
docker volume inspect myapp-data

# Clean up
docker network prune
docker volume prune

Detect runtime before operations:

# Run DetectRuntime.sh to determine Docker/Podman
# All commands shown support both runtimes

Network Management

Create and manage container networks for connectivity and isolation.

Creating Networks

Bridge network (default, most common):

docker network create mynetwork
podman network create mynetwork

With subnet and gateway:

docker network create \
  --subnet=172.20.0.0/16 \
  --gateway=172.20.0.1 \
  mynetwork

podman network create \
  --subnet=172.20.0.0/16 \
  --gateway=172.20.0.1 \
  mynetwork

With IP range restriction:

docker network create \
  --subnet=172.20.0.0/16 \
  --ip-range=172.20.240.0/20 \
  --gateway=172.20.0.1 \
  mynetwork

With driver options:

docker network create \
  --driver bridge \
  --opt "com.docker.network.bridge.name=br-myapp" \
  --opt "com.docker.network.bridge.enable_ip_masquerade=true" \
  mynetwork

Network Drivers

Bridge (Default):

  • Best for: Single-host deployments, isolated container groups, development
  • Characteristics: Software bridge, NAT for external access, DNS between containers
  • Isolation: Isolated from host network

Host:

docker run --network host myapp
podman run --network host myapp
  • Best for: Maximum performance, direct port binding, legacy apps
  • Characteristics: No isolation, uses host network stack, no port mapping needed
  • Trade-off: Higher performance, lower security

Overlay (Docker Swarm):

docker network create --driver overlay myoverlay

# With encryption
docker network create --driver overlay --opt encrypted myoverlay
  • Best for: Multi-host deployments, Docker Swarm, microservices across hosts
  • Characteristics: Spans multiple Docker hosts, requires swarm mode
  • Features: Optional encrypted traffic

Macvlan:

docker network create \
  --driver macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  mymacvlan
  • Best for: Legacy applications, direct Layer 2 access, containers needing MAC address
  • Characteristics: Containers get own MAC, appear as physical devices

None (No networking):

docker run --network none myapp
podman run --network none myapp
  • Best for: Maximum isolation, custom networking, security-critical containers
  • Characteristics: No network interface, complete isolation

Connecting and Disconnecting

Connect running container:

docker network connect mynetwork container_name
podman network connect mynetwork container_name

Connect with specific IP:

docker network connect --ip 172.20.0.100 mynetwork container_name
podman network connect --ip 172.20.0.100 mynetwork container_name

Connect with alias:

docker network connect --alias db mynetwork container_name
podman network connect --alias db mynetwork container_name

Disconnect container:

docker network disconnect mynetwork container_name
podman network disconnect mynetwork container_name

Start container on network:

docker run --network mynetwork --name web nginx
podman run --network mynetwork --name web nginx

# With custom IP
docker run --network mynetwork --ip 172.20.0.100 --name web nginx

# With network alias
docker run --network mynetwork --network-alias webapp --name web nginx

Network Inspection

View network details:

docker network inspect mynetwork
podman network inspect mynetwork

Get specific fields:

# List connected containers
docker network inspect -f '{{range .Containers}}{{.Name}} {{end}}' mynetwork

# Get subnet
docker network inspect -f '{{range .IPAM.Config}}{{.Subnet}}{{end}}' mynetwork

# Get gateway
docker network inspect -f '{{range .IPAM.Config}}{{.Gateway}}{{end}}' mynetwork

JSON output with jq:

docker network inspect mynetwork | jq '.[0].IPAM.Config'
podman network inspect mynetwork | jq '.[0].subnets'

List all containers on network:

docker network inspect mynetwork -f '{{range .Containers}}{{.Name}} {{.IPv4Address}}{{"\n"}}{{end}}'

DNS Resolution

Automatic DNS (user-defined networks):

# Create network
docker network create myapp

# Start containers
docker run -d --network myapp --name web nginx
docker run -d --network myapp --name db postgres

# Containers can resolve each other by name
docker exec web ping db
docker exec web curl http://db:5432

Custom DNS

Set DNS servers:

docker run --dns 8.8.8.8 --dns 8.8.4.4 myapp
podman run --dns 8.8.8.8 myapp

Set DNS search domain:

docker run --dns-search example.com myapp
podman run --dns-search example.com myapp

Add multiple aliases:

docker network connect --alias db --alias database mynetwork container_name

Network Isolation

Networks provide isolation between container groups:

# Frontend network
docker network create frontend

# Backend network (internal only)
docker network create --internal backend

# Web server on both networks
docker run -d --network frontend --name web nginx
docker network connect backend web

# Database only on backend (isolated from external)
docker run -d --network backend --name db postgres

Port Mapping Strategies

Basic port mapping:

docker run -p 8080:80 nginx  # host:container
podman run -p 8080:80 nginx

Bind to specific interface:

docker run -p 127.0.0.1:8080:80 nginx
podman run -p 127.0.0.1:8080:80 nginx

Map port range:

docker run -p 8080-8090:8080-8090 myapp
podman run -p 8080-8090:8080-8090 myapp

UDP ports:

docker run -p 53:53/udp dns-server
podman run -p 53:53/udp dns-server

Publish all exposed ports:

docker run -P nginx  # Maps to random host ports
podman run -P nginx

Check port mappings:

docker port container_name
podman port container_name

Managing Networks

List networks:

docker network ls
podman network ls

# Filter by driver
docker network ls --filter driver=bridge

# Filter by name
docker network ls --filter name=myapp

Remove network:

docker network rm mynetwork
podman network rm mynetwork

Remove all unused networks:

docker network prune
podman network prune

Podman-Specific Networking

CNI plugins (Podman uses CNI):

# CNI config location
/etc/cni/net.d/

# List available plugins
ls /usr/libexec/cni/

Rootless networking:

# Rootless uses slirp4netns by default
podman network inspect podman

# Create rootless network
podman network create mynetwork

Pod networking (containers in pod share network):

# Create pod
podman pod create --name mypod -p 8080:80

# Add containers (share network via localhost)
podman run -d --pod mypod --name web nginx
podman run -d --pod mypod --name app myapp

Volume Management

Create and manage persistent storage for container data.

Volume Types

Named Volumes (Recommended):

  • Managed by Docker/Podman
  • Easy to backup and migrate
  • Work across platforms
  • Best for most use cases

Bind Mounts:

  • Direct host path mapping
  • Useful for development
  • Direct file access from host
  • Platform-specific paths

tmpfs Mounts (Linux only):

  • Stored in host memory
  • Not persisted to disk
  • Fast but temporary
  • Good for sensitive data

Creating Volumes

Simple named volume:

docker volume create myvolume
podman volume create myvolume

With driver options (NFS example):

docker volume create \
  --driver local \
  --opt type=nfs \
  --opt o=addr=192.168.1.1,rw \
  --opt device=:/path/to/dir \
  nfs-volume

With labels:

docker volume create \
  --label project=myapp \
  --label environment=production \
  myvolume

podman volume create \
  --label project=myapp \
  myvolume

Volume Drivers

Local driver (default):

docker volume create --driver local myvolume

Local with bind mount options:

docker volume create \
  --driver local \
  --opt type=none \
  --opt device=/path/to/host/dir \
  --opt o=bind \
  myvolume

NFS driver:

docker volume create \
  --driver local \
  --opt type=nfs \
  --opt o=addr=192.168.1.100,rw,nfsvers=4 \
  --opt device=:/exported/path \
  nfs-volume

Bind Mounts vs Volumes

Named volume (preferred):

docker run -v myvolume:/data myapp
docker run --mount source=myvolume,target=/data myapp

podman run -v myvolume:/data myapp

Bind mount:

docker run -v /host/path:/container/path myapp
docker run --mount type=bind,source=/host/path,target=/container/path myapp

podman run -v /host/path:/container/path myapp

When to use volumes:

  • Database data
  • Application state
  • Uploaded files
  • Configuration that persists

When to use bind mounts:

  • Development (live code reload)
  • Configuration files from host
  • Log file access
  • Sharing files with host

Mounting Volumes in Containers

Mount named volume:

docker run -v myvolume:/data myapp
podman run -v myvolume:/data myapp

Mount read-only:

docker run -v myvolume:/data:ro myapp
docker run --mount source=myvolume,target=/data,readonly myapp

podman run -v myvolume:/data:ro myapp

Mount with volume options:

docker run --mount type=volume,source=myvolume,target=/data,volume-opt=o=size=100m myapp

Bind mount with propagation:

# Shared propagation
docker run -v /host/path:/container/path:shared myapp

# Private propagation (default)
docker run -v /host/path:/container/path:private myapp

# Slave propagation
docker run -v /host/path:/container/path:slave myapp

tmpfs mount:

docker run --tmpfs /app/cache myapp
docker run --mount type=tmpfs,target=/app/cache myapp

podman run --tmpfs /app/cache myapp

tmpfs with size limit:

docker run --tmpfs /app/cache:size=100m myapp
docker run --mount type=tmpfs,target=/app/cache,tmpfs-size=100m myapp

When to use tmpfs:

  • Temporary files
  • Cache
  • Sensitive data (not persisted)
  • Session storage

Volume Inspection

View volume details:

docker volume inspect myvolume
podman volume inspect myvolume

Get specific fields:

# Get mountpoint
docker volume inspect -f '{{.Mountpoint}}' myvolume
podman volume inspect -f '{{.Mountpoint}}' myvolume

# Get driver
docker volume inspect -f '{{.Driver}}' myvolume

# Get labels
docker volume inspect -f '{{.Labels}}' myvolume

JSON output with jq:

docker volume inspect myvolume | jq '.[0].Mountpoint'
podman volume inspect myvolume | jq '.[] | .Mountpoint'

Find containers using volume:

docker ps -a --filter volume=myvolume
podman ps -a --filter volume=myvolume

List volumes used by container:

docker inspect -f '{{range .Mounts}}{{.Name}} {{.Destination}}{{"\n"}}{{end}}' container_name
podman inspect -f '{{range .Mounts}}{{.Name}} {{.Destination}}{{"\n"}}{{end}}' container_name

Backup and Restore

Backup volume to tar archive:

docker run --rm \
  -v myvolume:/data \
  -v $(pwd):/backup \
  alpine \
  tar czf /backup/myvolume-backup.tar.gz -C /data .

podman run --rm \
  -v myvolume:/data \
  -v $(pwd):/backup \
  alpine \
  tar czf /backup/myvolume-backup.tar.gz -C /data .

Backup with timestamp:

TIMESTAMP=$(date +%Y%m%d_%H%M%S)
docker run --rm \
  -v myvolume:/data \
  -v $(pwd):/backup \
  alpine \
  tar czf /backup/myvolume-${TIMESTAMP}.tar.gz -C /data .

Restore from tar archive:

# Create volume if needed
docker volume create myvolume

# Restore data
docker run --rm \
  -v myvolume:/data \
  -v $(pwd):/backup \
  alpine \
  tar xzf /backup/myvolume-backup.tar.gz -C /data

podman run --rm \
  -v myvolume:/data \
  -v $(pwd):/backup \
  alpine \
  tar xzf /backup/myvolume-backup.tar.gz -C /data

Copy between volumes:

docker run --rm \
  -v source-volume:/source:ro \
  -v dest-volume:/dest \
  alpine \
  cp -av /source/. /dest/

Export volume to host:

docker run --rm \
  -v myvolume:/data \
  -v $(pwd)/export:/export \
  alpine \
  cp -av /data/. /export/

Volume Plugins

Third-party drivers available:

  • REX-Ray (cloud storage)
  • Convoy
  • Flocker
  • GlusterFS
  • NetApp

tmpfs Mounts

In-memory storage for temporary data:

docker run --tmpfs /app/cache myapp

# With size and mode options
docker run --tmpfs /app/cache:rw,size=100m,mode=1777 myapp

Managing Volumes

List volumes:

docker volume ls
podman volume ls

# Filter by name
docker volume ls --filter name=myapp

# Filter by driver
docker volume ls --filter driver=local

# Show dangling volumes
docker volume ls --filter dangling=true

Access volume data directly:

# Find volume location (Docker requires root)
docker volume inspect -f '{{.Mountpoint}}' myvolume
# Usually: /var/lib/docker/volumes/myvolume/_data

# Podman (rootless)
podman volume inspect -f '{{.Mountpoint}}' myvolume
# Usually: ~/.local/share/containers/storage/volumes/myvolume/_data

Browse volume with helper container:

docker run -it --rm \
  -v myvolume:/data \
  alpine \
  sh

Remove volume:

docker volume rm myvolume
podman volume rm myvolume

Remove all unused volumes:

docker volume prune
podman volume prune

# Filter and remove
docker volume prune --filter "label=project=old"

Podman-Specific Volumes

Rootless volume location:

~/.local/share/containers/storage/volumes/

Import/Export (Podman):

# Export volume
podman volume export myvolume > myvolume.tar

# Import volume
podman volume import myvolume < myvolume.tar

Registry Management

Push, pull, and manage container images across registries.

Registry Types

  • Docker Hub (docker.io)
  • GitHub Container Registry (ghcr.io)
  • GitLab Container Registry (registry.gitlab.com)
  • Private/self-hosted registries
  • Cloud provider registries (AWS ECR, Google GCR, Azure ACR)

Authentication

Docker Hub:

docker login
docker login -u username -p password

podman login docker.io
podman login -u username -p password docker.io

GitHub Container Registry:

echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
echo $GITHUB_TOKEN | podman login ghcr.io -u USERNAME --password-stdin

# Interactive
docker login ghcr.io
podman login ghcr.io

GitLab Container Registry:

docker login registry.gitlab.com -u USERNAME -p $CI_JOB_TOKEN
podman login registry.gitlab.com -u USERNAME -p $CI_JOB_TOKEN

Private registry:

docker login myregistry.example.com
podman login myregistry.example.com

AWS ECR:

aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS --password-stdin 123456789.dkr.ecr.us-east-1.amazonaws.com

aws ecr get-login-password --region us-east-1 | \
  podman login --username AWS --password-stdin 123456789.dkr.ecr.us-east-1.amazonaws.com

Google Container Registry:

gcloud auth configure-docker

# Or manually
cat keyfile.json | docker login -u _json_key --password-stdin gcr.io

Azure Container Registry:

az acr login --name myregistry

# Or with service principal
docker login myregistry.azurecr.io -u $SP_ID -p $SP_PASSWORD

Logout:

docker logout
docker logout ghcr.io

podman logout docker.io
podman logout ghcr.io

Pushing Images

Tag for registry:

docker tag myapp:latest myregistry/myapp:latest
docker tag myapp:latest myregistry/myapp:v1.0.0

podman tag myapp:latest myregistry/myapp:latest

Tag for Docker Hub:

docker tag myapp:latest username/myapp:latest
podman tag myapp:latest docker.io/username/myapp:latest

Tag for GHCR:

docker tag myapp:latest ghcr.io/username/myapp:latest
podman tag myapp:latest ghcr.io/username/myapp:latest

Push image:

docker push myregistry/myapp:latest
podman push myregistry/myapp:latest

Push all tags:

docker push --all-tags myregistry/myapp
podman push --all-tags myregistry/myapp

Pulling Images

Pull latest tag:

docker pull myregistry/myapp:latest
podman pull myregistry/myapp:latest

Pull specific tag:

docker pull myregistry/myapp:v1.0.0
podman pull myregistry/myapp:v1.0.0

Pull by digest:

docker pull myregistry/myapp@sha256:abc123...
podman pull myregistry/myapp@sha256:abc123...

Pull all tags:

docker pull --all-tags myregistry/myapp
podman pull --all-tags myregistry/myapp

Pull for specific platform:

docker pull --platform linux/arm64 myregistry/myapp:latest
podman pull --arch arm64 myregistry/myapp:latest

Tagging Strategies

Semantic versioning:

docker tag myapp:latest ghcr.io/username/myapp:v1.2.3
docker tag myapp:latest ghcr.io/username/myapp:v1.2
docker tag myapp:latest ghcr.io/username/myapp:v1
docker tag myapp:latest ghcr.io/username/myapp:latest

Git commit SHA:

docker tag myapp:latest ghcr.io/username/myapp:abc123

Build date:

docker tag myapp:latest ghcr.io/username/myapp:2024-01-15

Naming convention:

registry.example.com/project/app:version
ghcr.io/username/myapp:v1.0.0
docker.io/library/nginx:1.25-alpine

Private Registries

Run local registry:

docker run -d -p 5000:5000 --name registry registry:2

# With persistence
docker run -d -p 5000:5000 \
  --name registry \
  -v registry-data:/var/lib/registry \
  registry:2

# With authentication
docker run -d -p 5000:5000 \
  --name registry \
  -v registry-data:/var/lib/registry \
  -v $(pwd)/auth:/auth \
  -e REGISTRY_AUTH=htpasswd \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  -e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \
  registry:2

Use local registry:

docker tag myapp:latest localhost:5000/myapp:latest
docker push localhost:5000/myapp:latest

Configure insecure registry (Docker):

# /etc/docker/daemon.json
{
  "insecure-registries": ["myregistry.local:5000"]
}

Configure insecure registry (Podman):

podman login --tls-verify=false myregistry.example.com

Harbor/GitLab/GitHub Registries

Harbor (enterprise registry):

# Login
docker login harbor.example.com

# Push to project
docker tag myapp:latest harbor.example.com/myproject/myapp:latest
docker push harbor.example.com/myproject/myapp:latest

GitLab Container Registry:

# Login
docker login registry.gitlab.com

# Push to project
docker tag myapp:latest registry.gitlab.com/username/project/myapp:latest
docker push registry.gitlab.com/username/project/myapp:latest

GitHub Container Registry:

# Login with token
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin

# Push to user/org
docker tag myapp:latest ghcr.io/username/myapp:latest
docker push ghcr.io/username/myapp:latest

Multi-Registry Workflows

Copy between registries using skopeo:

# Copy from Docker Hub to GHCR
skopeo copy \
  docker://docker.io/username/myapp:latest \
  docker://ghcr.io/username/myapp:latest

# Copy with authentication
skopeo copy \
  --src-creds username:password \
  --dest-creds username:token \
  docker://registry1.com/myapp:latest \
  docker://registry2.com/myapp:latest

Copy all tags with skopeo:

skopeo sync \
  --src docker --dest docker \
  username/myapp \
  ghcr.io/username/

Copy using Docker/Podman:

docker pull registry1.com/myapp:latest
docker tag registry1.com/myapp:latest registry2.com/myapp:latest
docker push registry2.com/myapp:latest

Search images:

docker search nginx
docker search --filter "is-official=true" nginx
docker search --filter "stars=100" nginx

podman search nginx
podman search --filter=stars=100 nginx

List tags:

# Using skopeo
skopeo list-tags docker://docker.io/nginx
skopeo list-tags docker://ghcr.io/username/myapp

# Using podman
podman search --list-tags docker.io/nginx

Inspect remote images without pulling:

# With skopeo
skopeo inspect docker://myregistry/myapp:latest
skopeo inspect docker://ghcr.io/username/myapp:latest

# Show specific field
skopeo inspect docker://myapp:latest | jq '.Layers'

# Inspect manifest
docker manifest inspect myregistry/myapp:latest
podman manifest inspect myregistry/myapp:latest

# Raw manifest
skopeo inspect --raw docker://myregistry/myapp:latest

Registry Mirrors

Configure Docker daemon mirrors:

# /etc/docker/daemon.json
{
  "registry-mirrors": ["https://mirror.example.com"],
  "max-concurrent-downloads": 3,
  "max-concurrent-uploads": 5
}

Configure Podman mirrors:

# /etc/containers/registries.conf
[registries.search]
registries = ['docker.io', 'ghcr.io']

[registries.insecure]
registries = ['myregistry.local:5000']

[[registry]]
location = "docker.io"
[[registry.mirror]]
location = "mirror.example.com"

Credential Management

Docker credentials stored in:

~/.docker/config.json

Use credential helper:

# Configure in ~/.docker/config.json
{
  "credsStore": "secretservice"
}
# For Linux: docker-credential-secretservice
# For macOS: docker-credential-osxkeychain
# For Windows: docker-credential-wincred

Podman credentials stored in:

# Rootless
$XDG_RUNTIME_DIR/containers/auth.json

# Rootful
/run/containers/0/auth.json

View stored credentials:

cat ${XDG_RUNTIME_DIR}/containers/auth.json | jq

Best Practices

Network Best Practices

Security:

  • Use user-defined networks, not default bridge
  • Isolate sensitive services on separate networks
  • Use internal networks for backend services
  • Limit external exposure with firewall rules

Organization:

  • Name networks descriptively: frontend, backend, data
  • One network per application tier
  • Document network topology
  • Use labels for organization and filtering

Performance:

  • Use host networking for high-throughput apps (with caution)
  • Keep containers on same network for inter-container communication
  • Use overlay networks sparingly (has overhead)

Volume Best Practices

Storage selection:

  • Use named volumes for production data persistence
  • Use bind mounts for development and configuration
  • Use tmpfs for temporary, sensitive, or frequently accessed data

Naming:

  • Use descriptive names: postgres-data, app-uploads
  • Include app name: myapp-database, myapp-cache
  • Use labels for organization
  • Maintain consistent naming convention

Security:

  • Use read-only mounts when possible
  • Limit bind mount scope to minimum necessary
  • Don’t mount sensitive host directories
  • Set appropriate permissions
  • Consider using secrets for sensitive data

Performance:

  • Named volumes are faster than bind mounts on macOS/Windows
  • Use tmpfs for frequently accessed temporary data
  • Place volumes on fast storage
  • Consider volume drivers for distributed storage

Data management:

  • Regular backups of important volumes
  • Test restore procedures
  • Monitor volume usage and clean up unused volumes
  • Document volume dependencies

Registry Best Practices

Tagging strategy:

  • Use semantic versioning: v1.2.3
  • Tag with git commit SHA: abc123
  • Tag with build date: 2024-01-15
  • Always tag latest for current production
  • Tag stable releases: stable

Security:

  • Use credential helpers, not plain text passwords
  • Rotate access tokens regularly
  • Use least privilege access
  • Scan images before pushing
  • Sign images with Docker Content Trust or Cosign

Optimization:

  • Use multi-stage builds to reduce image size
  • Push during off-peak hours for large images
  • Use registry mirrors for faster pulls
  • Enable layer compression

Multi-registry:

  • Mirror critical images across registries
  • Use skopeo for efficient registry operations
  • Document registry dependencies
  • Test failover scenarios

Troubleshooting

Network Issues

Containers can’t communicate:

  • Check: Ensure containers are on the same network
  • Check: Verify DNS resolution with docker exec container ping other_container
  • Check: Inspect network connections with docker network inspect
  • Check: Firewall rules: sudo iptables -L DOCKER

Port already in use:

  • Check: lsof -i :8080
  • Solution: Use different host port
  • Solution: Stop conflicting service

Can’t remove network:

  • Cause: Containers still connected
  • Solution: Disconnect or remove containers first
  • Solution: docker network disconnect -f mynetwork container_name

Check container network:

# Get container IP
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name
podman inspect -f '{{.NetworkSettings.IPAddress}}' container_name

# Test connectivity from container
docker exec web ping db
docker exec web nc -zv db 5432
docker exec web nslookup db
docker exec web ip route

Check bridge and firewall:

# List bridges
ip link show type bridge

# Show bridge details
bridge link show

# Check iptables rules
sudo iptables -L DOCKER
sudo iptables -L DOCKER-USER
sudo iptables -t nat -L DOCKER

Volume Issues

Permission denied in container:

  • Cause: User ID mismatch between host and container
  • Solution: Run container as specific user
    docker run --user $(id -u):$(id -g) -v myvolume:/data myapp
    
  • Solution: Fix permissions in container
    docker run --rm -v myvolume:/data alpine chown -R 1000:1000 /data
    

Volume data disappeared:

  • Cause: Used anonymous volume or accidentally removed volume
  • Solution: Always use named volumes for persistent data
  • Prevention: Regular backups

Cannot remove volume:

  • Cause: Container still using it
  • Check: docker ps -a --filter volume=myvolume
  • Solution: Remove container first or use docker volume rm -f

Bind mount not updating (macOS/Windows):

  • Cause: File sync delay in Docker Desktop
  • Solution: Use named volumes or configure file sharing

Volume full:

  • Check size:
    docker run --rm -v myvolume:/data alpine du -sh /data
    
  • Solution: Remove unnecessary files or increase volume size

Registry Issues

Authentication failed:

  • Check: Verify credentials
  • Check: Ensure token hasn’t expired
  • Check: Verify proper permissions on registry
  • Solution: Re-login with fresh credentials

Push denied:

  • Check: Repository permissions
  • Check: Namespace/organization access
  • Solution: Create repository first (some registries require this)

Image not found:

  • Check: Image name and tag spelling
  • Check: Registry URL is correct
  • Check: Image was pushed successfully

TLS certificate error:

  • Solution (dev only): Add registry to insecure registries
  • Solution (production): Install proper CA certificates
  • Temporary: Use --tls-verify=false for testing only

Rate limit exceeded (Docker Hub):

  • Solution: Login to increase limit (200 pulls/6 hours free)
  • Solution: Use registry mirror
  • Solution: Upgrade to paid plan

Infrastructure Integration Examples

Multi-Tier Application

# Create networks
docker network create frontend
docker network create backend

# Create volumes
docker volume create db-data
docker volume create app-uploads

# Start database with volume
docker run -d \
  --name postgres \
  --network backend \
  -v db-data:/var/lib/postgresql/data \
  -e POSTGRES_PASSWORD=secret \
  postgres:15

# Start application server
docker run -d \
  --name app \
  --network backend \
  --network frontend \
  -v app-uploads:/uploads \
  myapp:latest

# Start web server
docker run -d \
  --name nginx \
  --network frontend \
  -p 80:80 \
  nginx:latest

# Database is isolated on backend network
# Web server only accesses app via frontend network

Development with Live Reload

# Create network
docker network create dev-network

# Create volume for dependencies
docker volume create node-modules

# Start with bind mount for code
docker run -d \
  --name dev-server \
  --network dev-network \
  -v $(pwd)/src:/app/src \
  -v node-modules:/app/node_modules \
  -p 3000:3000 \
  node:18 npm run dev

Registry Workflow with Infrastructure

# Build application
docker build -t myapp:latest .

# Create production volume
docker volume create prod-data

# Test locally with network
docker network create test-net
docker run -d --name test --network test-net -v prod-data:/data myapp:latest

# Tag for registry
docker tag myapp:latest ghcr.io/username/myapp:v1.0.0
docker tag myapp:latest ghcr.io/username/myapp:latest

# Login and push
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
docker push ghcr.io/username/myapp:v1.0.0
docker push ghcr.io/username/myapp:latest

# Deploy on production server
docker pull ghcr.io/username/myapp:latest
docker network create prod-net
docker volume create prod-data
docker run -d \
  --name prod \
  --network prod-net \
  -v prod-data:/data \
  -p 80:8080 \
  ghcr.io/username/myapp:latest

Backup Infrastructure Before Update

# Backup volume
docker run --rm \
  -v app-data:/data \
  -v $(pwd)/backups:/backup \
  alpine \
  tar czf /backup/app-data-$(date +%Y%m%d).tar.gz -C /data .

# Export network configuration
docker network inspect prod-net > network-config.json

# Tag current production image
docker tag myapp:latest myapp:backup-$(date +%Y%m%d)

# Push backup to registry
docker tag myapp:backup-$(date +%Y%m%d) ghcr.io/username/myapp:backup-$(date +%Y%m%d)
docker push ghcr.io/username/myapp:backup-$(date +%Y%m%d)