Skip to content
intermediate Phase 3 · Docker Volumes & Storage

Bind Mounts

Mount host directories into containers for development workflows.

45m
0 problems
Topic Progress 0%

Bind Mount Basics

Bind Mount Basics

A bind mount maps a specific file or directory from the host into a container. Unlike named volumes (managed by Docker), bind mounts reference an exact path on the host.

Basic Syntax

# Mount current directory into container
docker run -it -v $(pwd):/app alpine sh

# Using --mount syntax (recommended)
docker run -it --mount type=bind,source=$(pwd),target=/app alpine sh

# Mount specific file
docker run -v $(pwd)/config.json:/app/config.json:ro myapp

# Mount with specific ownership
docker run -v $(pwd):/app:Z myapp  # SELinux relabel

Bind Mount vs Named Volume

Feature Bind Mount Named Volume
Source Specific host path Docker-managed
Performance Depends on OS Always fast (Linux)
Sharing Easy (same path) Requires volume create
Backup Copy host directory Docker volume commands
Use case Development Data persistence

Development Workflow

Bind mounts are essential for live development:

# Node.js development
docker run -d \
  -v $(pwd):/app \
  -w /app \
  -p 3000:3000 \
  node:20 \
  npm run dev

# Python development
docker run -it \
  -v $(pwd):/app \
  -w /app \
  python:3.12 \
  python main.py

# Go development
docker run -it \
  -v $(pwd):/go/src/app \
  -w /go/src/app \
  golang:1.21 \
  go run main.go

Read-Only Bind Mounts

# Prevent container from modifying host files
docker run -d \
  --mount type=bind,source=$(pwd)/config,target=/etc/app,readonly \
  myapp

Common Use Cases

  • Development: Live code reload without rebuilding
  • Configuration: Mount config files into containers
  • Logs: Write logs to host filesystem
  • Build artifacts: Share build output between containers

Permissions and Ownership

Permissions and Ownership

UID/GID Mapping

Containers run with a UID/GID that may not match the host user. This can cause permission issues:

# Container runs as root (UID 0), host files owned by UID 1000
docker run -v $(pwd)/data:/data alpine ls -la /data
# Files may appear owned by root inside container

# Run container as specific user
docker run -v $(pwd)/data:/data \
  --user $(id -u):$(id -g) \
  alpine ls -la /data

Fixing Permissions

# Option 1: Run as host user
docker run -v $(pwd):/app \
  --user $(id -u):$(id -g) \
  node:20 npm install

# Option 2: Change ownership on host
sudo chown -R $(id -u):$(id -g) ./node_modules

# Option 3: Use named volume for node_modules
# (avoids permission issues entirely)
docker run -v $(pwd):/app -v node_modules:/app/node_modules \
  node:20 npm install

SELinux Labels

On SELinux systems (RHEL, Fedora), bind mounts may fail with permission denied:

# Use :z to relabel for shared containers
docker run -v $(pwd):/app:z myapp

# Use :Z for private relabel (single container)
docker run -v $(pwd):/app:Z myapp

# Use :O for overlay mount (read-only with copy-up)
docker run -v $(pwd):/app:O myapp

macOS File Performance

Docker Desktop on macOS mounts through a VM layer, causing slow I/O:

# Slow: Every file access goes through VM
v /Users/me/project:/app

# Faster: Use named volume for heavy I/O
v app-nodemodules:/app/node_modules

Optimize for macOS:

  • Use named volumes for node_modules and build caches
  • Exclude large directories in Docker Desktop settings
  • Consider :cached or :delegated mount consistency options

Docker Compose Bind Mounts

services:
  web:
    image: node:20
    volumes:
      - .:/app                    # Current directory
      - ./config:/app/config:ro   # Read-only config
      - /absolute/path:/data      # Absolute path
    working_dir: /app
    command: npm run dev

  nginx:
    image: nginx:1.25
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./static:/usr/share/nginx/html:ro

Security Considerations

# DANGEROUS: Mounts Docker socket (full host access)
docker run -v /var/run/docker.sock:/var/run/docker.sock docker

# DANGEROUS: Mounts host root
docker run -v /:/host alpine chroot /host

# SAFE: Mount specific config only
docker run -v $(pwd)/config.json:/app/config.json:ro myapp