Image vs container — the template vs the running instance
Concept
Image vs container — an image is the blueprint; a container is the running instance. The same image can run as many containers simultaneously.
Docker image:
- A read-only, layered snapshot of a filesystem and configuration.
- Built from a
Dockerfilewithdocker build. - Stored in a registry (Docker Hub, GitHub Container Registry, AWS ECR).
- Tagged:
myapp:latest,myapp:v1.2.3,php:8.4-fpm-alpine. - Immutable: once built, an image doesn't change.
Docker container:
- A running (or stopped) instance of an image.
- Created with
docker run. - Has its own writable layer on top of the image layers.
- Ephemeral: when deleted, any changes to its filesystem are lost.
- You can run 10 containers from the same image simultaneously.
The analogy: Image = class definition. Container = object instance. The same class (image) can be instantiated (run) many times into separate objects (containers).
Layers: Images are built in layers. Each RUN, COPY, ADD in the Dockerfile adds a layer. Layers are cached — if nothing in a layer changed, Docker reuses the cache. Ordering matters: put frequently changing steps (COPY source code) last, stable steps (install dependencies) first.
Image tags: Used for versioning. :latest is the default tag but not recommended in production — always pin to a specific version tag for reproducible builds.
Code Example
# BUILD an image from Dockerfile
docker build -t myapp:latest .
docker build -t myapp:v2.1.0 -f Dockerfile.prod .
# LIST images
docker images
# REPOSITORY TAG IMAGE ID CREATED SIZE
# myapp latest abc123 2 hours ago 142MB
# php 8.4-fpm def456 3 days ago 445MB
# PUSH to registry
docker tag myapp:latest ghcr.io/username/myapp:latest
docker push ghcr.io/username/myapp:latest
# RUN a container from an image
docker run -d \
--name myapp-1 \
-p 8080:80 \
-e APP_ENV=production \
-v /data/storage:/var/www/storage \
myapp:latest
# Run another instance from the same image (different port)
docker run -d --name myapp-2 -p 8081:80 myapp:latest
# LIST running containers
docker ps
# CONTAINER ID IMAGE STATUS PORTS
# xyz789 myapp:latest Up 2 hours 0.0.0.0:8080->80/tcp
# abc123 myapp:latest Up 2 hours 0.0.0.0:8081->80/tcp
# Container is just a process from an image
docker exec -it myapp-1 bash # shell into running container
docker stop myapp-1 # stop container
docker rm myapp-1 # remove container (image still exists)
# LAYERS — inspect image layer cache behavior
# Dockerfile optimized for caching:
FROM php:8.4-fpm-alpine
# Layer 1: system packages (changes rarely → cached)
RUN apk add --no-cache libpng-dev
# Layer 2: PHP extensions (changes rarely → cached)
RUN docker-php-ext-install pdo pdo_mysql gd
# Layer 3: composer dependencies (changes when composer.lock changes)
COPY composer.json composer.lock ./
RUN composer install --no-dev
# Layer 4: application code (changes most often → rebuilds from here)
COPY . .
# If you only change PHP files, layers 1-3 use cache → fast rebuild