Docker Basics

Essential Docker system commands and concepts for beginners

Resource Limits

You can control how much CPU and memory a container can use to prevent one container from using all system resources.

Example:

services:
    redis:
        image: redis:alpine
        deploy:
            resources:
                limits:
                    cpus: '0.50'
                    memory: 150M
                reservations:
                    cpus: '0.25'
                    memory: 20M

Limits

The maximum resources a container can use.

In this example, the container can use up to 0.5 CPU cores and 150MB of memory.

Reservations

The minimum resources guaranteed to a container.

In this example, the container is guaranteed at least 0.25 CPU cores and 20MB of memory.

Environment Variables

Environment variables are used to configure applications without changing code. They're like settings that can change between environments.

Setting in docker-compose.yml

services:
    web:
        image: nginx:alpine
        environment:
            - DEBUG=1
            - FOO=BAR

Using .env file

Create a file named .env in your project directory:

POSTGRES_VERSION=14.3

Then reference it in your docker-compose.yml:

services:
    db:
        image: "postgres:${POSTGRES_VERSION}"

Overriding at runtime

You can override environment variables when starting containers:

docker compose up -d -e DEBUG=0

Networking

Docker creates a default network that allows containers to communicate with each other.

Example:

services:
    web:
        image: nginx:alpine
        ports:
            - "8080:80"
    db:
        image: postgres
        ports:
            - "5432"

External Access

The web service is accessible from outside on port 8080.

You can access it via: http://localhost:8080

Internal Communication

Containers can communicate using their service names.

The web container can reach the database at: db:5432

Dependencies

In Docker Compose, you can specify that one service depends on another. This ensures services start in the correct order.

Example:

services:
    app:
        image: myapp
        depends_on:
            - db
    db:
        image: postgres
        networks:
            - back-tier

In this example, the "app" service depends on the "db" service. Docker Compose will start the database first, then the application.

Volumes

Volumes are used to persist data generated by and used by Docker containers. They're like external hard drives for your containers.

Host Volumes (Bind Mounts)

Directly map a directory on your host machine to a directory in the container.

Example:

services:
    app:
        image: myapp
        depends_on:
            - db
    db:
        image: postgres
        volumes:
            - ./db:/etc/data
        networks:
            - back-tier

This maps the local "./db" directory to "/etc/data" inside the container.

Named Volumes

Docker-managed volumes that have a specific name and are easier to manage.

Example:

services:
    app:
        image: myapp
        depends_on:
            - db
    db:
        image: postgres
        volumes:
            - db-data:/etc/data
        networks:
            - back-tier

# Volume definition
volumes:
    db-data:

You can also specify access modes like :ro (read-only) or :rw (read-write).

Restart Policy

Docker allows you to specify what should happen when a container exits or crashes. This is controlled by the restart policy.

no

The default restart policy.

Does not restart a container under any circumstances.

always

Always restarts the container until its removal.

Example: Great for services that must always be running.

on-failure

Restarts a container if the exit code indicates an error.

Example: Useful for applications that might occasionally crash.

unless-stopped

Restarts a container irrespective of the exit code but will stop restarting when the service is stopped or removed.

Example in docker-compose.yml:

services:
    app:
        image: myapp
        restart: always
        depends_on:
            - db
    db:
        image: postgres
        restart: always