Docker Basics
Docker Hub and Registries
Docker Hub (hub.docker.com) hosts pre-built container images. When you run:
docker run python:3.11-slim
Docker pulls the image from Docker Hub if not present locally. The format is:
[REGISTRY/]USERNAME/IMAGE[:TAG]
- No registry specified → defaults to Docker Hub
- No username → official images (
python,ubuntu,nginx) - No tag → defaults to
latest
Common registries:
docker.io- Docker Hub (default)ghcr.io- GitHub Container Registrygcr.io- Google Container Registrylocalhost:5000- Local registry
Building Images
A Dockerfile defines the build process:
FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD ["python", "app.py"]
Build with:
# Basic build docker build -t myapp . # With specific tag docker build -t myapp:v1.0 . # With build arguments docker build --build-arg VERSION=1.0 -t myapp . # From specific Dockerfile docker build -f Dockerfile.dev -t myapp:dev .
The -t flag tags the image. Without it, you get an unnamed image with only an ID.
Running Containers
Basic run patterns:
# Run interactively with terminal docker run -it ubuntu bash # Run in background (detached) docker run -d nginx # Remove container after exit docker run --rm python:3.11 python -c "print('Hello')" # Name the container docker run --name webserver -d nginx
Container lifecycle:
docker runcreates and starts a new container- Container runs until main process exits
- Container remains in stopped state unless
--rmused
Port Mapping
Expose container ports to host:
# Map port 80 in container to 8080 on host docker run -p 8080:80 nginx # Map to specific interface docker run -p 127.0.0.1:8080:80 nginx # Map random host port docker run -P nginx # Maps all exposed ports # Multiple ports docker run -p 8080:80 -p 8443:443 nginx
Format: -p [HOST_IP:]HOST_PORT:CONTAINER_PORT
Volume Mounts
Share data between host and container:
# Bind mount (absolute path required) docker run -v /path/on/host:/path/in/container nginx # Bind mount with pwd docker run -v $(pwd)/data:/app/data python:3.11 # Read-only mount docker run -v $(pwd)/config:/etc/config:ro nginx # Named volume (Docker-managed) docker volume create mydata docker run -v mydata:/data postgres # Anonymous volume docker run -v /data postgres # Creates unnamed volume
Bind mounts vs Volumes:
- Bind mounts: Direct host filesystem access, use absolute paths
- Named volumes: Docker-managed, portable, better for databases
- Anonymous volumes: Temporary, deleted with container
Environment Variables
Pass configuration to containers:
# Single variable docker run -e DATABASE_URL=postgres://localhost/db postgres # Multiple variables docker run -e USER=admin -e PASSWORD=secret nginx # From file docker run --env-file .env python:3.11 # From host environment docker run -e HOME myapp # Passes $HOME from host
Environment file format:
# .env file
DATABASE_URL=postgres://localhost/db
API_KEY=abc123
DEBUG=true
Container Management
Control running containers:
# List running containers docker ps # List all containers docker ps -a # Stop container (SIGTERM, then SIGKILL after 10s) docker stop container_name # Kill immediately (SIGKILL) docker kill container_name # Restart container docker restart container_name # Remove stopped container docker rm container_name # Remove running container docker rm -f container_name
Executing Commands
Run commands in existing containers:
# Execute command in running container docker exec container_name ls -la # Interactive shell in running container docker exec -it container_name bash # As different user docker exec -u www-data container_name whoami # With environment variable docker exec -e DEBUG=true container_name python script.py
exec vs run:
runcreates NEW containerexecruns in EXISTING container
Names vs IDs vs Labels
Three ways to identify containers:
# By name (user-defined) docker run --name myapp nginx docker stop myapp # By ID (auto-generated) docker ps -q # Show only IDs docker stop a1b2c3d4 # By label (metadata) docker run --label env=prod --label team=backend nginx docker ps --filter label=env=prod
Names must be unique. IDs are unique hashes. Labels are key-value metadata for organization.
Command Reference
Quick lookup for common Docker commands:
docker build
Build image from Dockerfile:
docker build [OPTIONS] PATH Options: -t, --tag Name and tag (name:tag) -f, --file Dockerfile path --build-arg Set build-time variables --no-cache Build without cache --target Build specific stage Examples: docker build -t myapp:latest . docker build -f Dockerfile.dev -t myapp:dev . docker build --build-arg VERSION=1.0 -t myapp:v1 .
docker run
Create and start container:
docker run [OPTIONS] IMAGE [COMMAND] Options: -d, --detach Run in background -it Interactive with TTY --rm Remove after exit --name Container name -p, --publish Port mapping (host:container) -v, --volume Volume mount -e, --env Environment variable --network Connect to network -u, --user Username or UID Examples: docker run -d --name web -p 8080:80 nginx docker run -it --rm ubuntu bash docker run -v $(pwd):/app -e DEBUG=true myapp
docker ps
List containers:
docker ps [OPTIONS] Options: -a, --all Show all (including stopped) -q, --quiet Only display IDs -f, --filter Filter output --format Format output Examples: docker ps # Running containers docker ps -a # All containers docker ps -q # Only IDs docker ps --filter status=exited # Stopped containers docker ps --format "table {{.Names}}\t{{.Status}}"
docker exec
Execute in running container:
docker exec [OPTIONS] CONTAINER COMMAND Options: -i, --interactive Keep STDIN open -t, --tty Allocate pseudo-TTY -e, --env Set environment variable -u, --user Username or UID -w, --workdir Working directory Examples: docker exec myapp ls -la docker exec -it myapp bash docker exec -u root myapp apt update docker exec -e VAR=value myapp env
docker stop/kill
Stop containers:
docker stop [OPTIONS] CONTAINER # Graceful (SIGTERM) docker kill [OPTIONS] CONTAINER # Force (SIGKILL) Options: -t, --time Seconds to wait before killing (stop only) Examples: docker stop myapp # 10 second grace period docker stop -t 30 myapp # 30 second grace period docker kill myapp # Immediate termination docker stop $(docker ps -q) # Stop all running
docker rm/rmi
Remove containers and images:
docker rm [OPTIONS] CONTAINER # Remove container docker rmi [OPTIONS] IMAGE # Remove image Options: -f, --force Force removal -v, --volumes Remove associated volumes Examples: docker rm myapp # Remove stopped container docker rm -f myapp # Force remove running docker rm $(docker ps -aq) # Remove all containers docker rmi myimage:tag # Remove image docker rmi $(docker images -q) # Remove all images
docker logs
View container logs:
docker logs [OPTIONS] CONTAINER Options: -f, --follow Follow log output -t, --timestamps Show timestamps --tail Number of lines from end --since Show logs since timestamp Examples: docker logs myapp docker logs -f myapp # Follow live docker logs --tail 50 myapp # Last 50 lines docker logs --since 10m myapp # Last 10 minutes
docker cp
Copy files between container and host:
docker cp [OPTIONS] SRC DEST Examples: docker cp myapp:/app/config.json ./config.json # Container to host docker cp ./data.csv myapp:/app/data.csv # Host to container docker cp myapp:/logs ./backup/ # Copy directory
docker inspect
View detailed container/image info:
docker inspect [OPTIONS] NAME|ID Examples: docker inspect myapp # Full JSON output docker inspect -f '{{.State.Status}}' myapp # Specific field docker inspect -f '{{.NetworkSettings.IPAddress}}' myapp docker inspect -f '{{json .Mounts}}' myapp | jq # With jq
docker volume
Manage volumes:
docker volume [COMMAND] Commands: create Create a volume ls List volumes rm Remove volumes inspect Display volume details prune Remove all unused volumes Examples: docker volume create mydata docker volume ls docker volume rm mydata docker volume prune -f # Remove unused