DockerImagesContainers
Beginner
4 min read
02-Docker Images & Containers
Learn how Docker images work, how to pull images from Docker Hub, run containers, inspect them, and manage their lifecycle.
Understanding Docker Images
A Docker image is a read-only template made up of layers. Each instruction in a Dockerfile adds a new layer on top of the previous one.
┌─────────────────────────────┐ ← Your App Layer
├─────────────────────────────┤ ← npm install Layer
├─────────────────────────────┤ ← COPY package.json Layer
├─────────────────────────────┤ ← node:18-alpine Base Layer
└─────────────────────────────┘
Why layers matter
Docker caches each layer. If only your app code changes, Docker reuses all the earlier layers — making builds dramatically faster.Pulling Images from Docker Hub
Docker Hub is the default public registry. Images follow the format: name:tag
# Pull the official Nginx image (latest tag)
docker pull nginx
# Pull a specific version
docker pull nginx:1.25-alpine
# Pull Node.js 18 on Alpine Linux (very small base)
docker pull node:18-alpine
# Pull Ubuntu 22.04
docker pull ubuntu:22.04
Listing and Inspecting Images
# List all locally available images
docker images
# or
docker image ls
# Example output:
# REPOSITORY TAG IMAGE ID CREATED SIZE
# nginx latest a6bd71f48f68 2 weeks ago 187MB
# nginx 1.25-alpine 1ae23480369f 3 weeks ago 43.2MB
# node 18-alpine b5b9bec2fc07 1 month ago 127MB
# Inspect image details (layers, env vars, entrypoint)
docker image inspect nginx
# See the layer history of an image
docker image history nginx
Running Your First Container
# Run Nginx and map port 80 on host to port 80 in container
docker run -p 80:80 nginx
Visit http://localhost — you’ll see the Nginx welcome page!
Important docker run Flags
| Flag | Purpose | Example |
|---|---|---|
-d | Run in background (detached mode) | docker run -d nginx |
-p | Port mapping host:container | -p 8080:80 |
--name | Give container a name | --name my-nginx |
-e | Set environment variable | -e NODE_ENV=production |
-v | Mount a volume | -v $(pwd):/app |
--rm | Auto-remove container when stopped | docker run --rm ubuntu echo hi |
-it | Interactive + TTY (for shells) | docker run -it ubuntu bash |
Detached Mode (Background)
# Run Nginx in the background
docker run -d -p 8080:80 --name my-nginx nginx
# Run a named container with environment variable
docker run -d \
--name my-postgres \
-e POSTGRES_PASSWORD=secret \
-p 5432:5432 \
postgres:15-alpine
Managing Container Lifecycle
# List running containers
docker ps
# List ALL containers (including stopped)
docker ps -a
# Stop a container gracefully (SIGTERM → waits 10s → SIGKILL)
docker stop my-nginx
# Start a stopped container
docker start my-nginx
# Restart a container
docker restart my-nginx
# Kill a container immediately (SIGKILL)
docker kill my-nginx
# Remove a stopped container
docker rm my-nginx
# Force remove a running container
docker rm -f my-nginx
# Remove ALL stopped containers
docker container prune
Interacting with Running Containers
# Execute a command inside a running container
docker exec my-nginx ls /etc/nginx
# Open an interactive shell inside a running container
docker exec -it my-nginx /bin/sh
# View container logs (stdout/stderr)
docker logs my-nginx
# Follow logs in real time (like tail -f)
docker logs -f my-nginx
# Show last 50 lines
docker logs --tail 50 my-nginx
# Inspect container details (IP, mounts, env vars)
docker inspect my-nginx
# View resource usage (CPU, memory, network)
docker stats
docker stats my-nginx # single container
Practical Exercise
Let’s run a real development database:
# 1. Start a PostgreSQL container
docker run -d \
--name dev-postgres \
-e POSTGRES_USER=admin \
-e POSTGRES_PASSWORD=secret123 \
-e POSTGRES_DB=myapp \
-p 5432:5432 \
postgres:15-alpine
# 2. Check it's running
docker ps
# 3. Connect to it with psql (inside the container)
docker exec -it dev-postgres psql -U admin -d myapp
# 4. Inside psql, create a table
# CREATE TABLE users (id serial PRIMARY KEY, name varchar);
# INSERT INTO users (name) VALUES ('Alice'), ('Bob');
# SELECT * FROM users;
# \q
# 5. Stop and clean up
docker stop dev-postgres
docker rm dev-postgres
One-liner cleanup
docker rm -f $(docker ps -aq) stops and removes all containers at once. Useful in development — never run this in production!Cleaning Up Images
# Remove a specific image
docker rmi nginx:1.25-alpine
# Remove all unused images (dangling)
docker image prune
# Remove ALL unused images (not just dangling)
docker image prune -a
# Nuclear option — remove everything unused
docker system prune -a
# ⚠️ WARNING: removes all stopped containers, unused networks, images, and build cache
Summary
| Command | What it does |
|---|---|
docker pull image:tag | Download an image |
docker images | List local images |
docker run -d -p host:container --name NAME image | Start a container |
docker ps | List running containers |
docker stop NAME | Stop a container |
docker rm NAME | Remove a container |
docker exec -it NAME sh | Shell into a container |
docker logs -f NAME | Stream container logs |
docker inspect NAME | Full container metadata |
In the next lesson, you’ll write your first Dockerfile to build custom images for your own application!