Great! Now let's dive deep into Docker images - understanding what they are, how they work, and how to use them effectively.
Part 1: Understanding Docker Images in Detail
What Exactly is a Docker Image?
Simple Definition:
A Docker image is a read-only template that contains everything needed to run an application.
Real-Life Analogy:
Think of images like:
Recipe Book (Image):
├── List of ingredients (dependencies)
├── Step-by-step instructions (configuration)
├── Cooking method (commands)
└── Expected result (application)
The Actual Dish (Container):
└── Made by following the recipe
└── Can make multiple dishes from same recipe
Another Analogy:
Software Installation CD (Image):
├── Contains all files
├── Instructions how to install
├── Configuration settings
└── Everything packaged together
Installed Software (Container):
└── Running instance on your computer
└── Can install multiple times from same CD
What's Inside a Docker Image?
An image contains:
Docker Image = Package containing:
│
├── 1. Base Operating System
│ └── Usually minimal Linux (Ubuntu, Alpine, etc.)
│
├── 2. Application Files
│ └── Your code, scripts, executables
│
├── 3. Dependencies
│ └── Libraries, packages, frameworks
│
├── 4. Configuration Files
│ └── Settings, environment variables
│
├── 5. Metadata
│ └── Author, version, description
│
└── 6. Default Commands
└── What to run when container starts
Example: Nginx Image Contains:
nginx:latest image includes:
├── Minimal Linux OS (Debian-based)
├── Nginx web server (compiled binary)
├── Default configuration files
├── HTML files (welcome page)
├── Required libraries (SSL, etc.)
└── Start command (run nginx)
Total size: ~141MB
Everything packaged together! ✓
Images are Read-Only
Important Concept:
Images are IMMUTABLE (cannot be changed):
Image = Read-Only Template
├── Once created, cannot be modified
├── Like a sealed recipe book
└── Always the same
Container = Writable Layer on Top
├── Can make changes while running
├── Changes don't affect the image
└── Like writing notes on a photocopy
Visual:
┌─────────────────────────┐
│ Container │
│ (Writable Layer) │ ← Your changes here
├─────────────────────────┤
│ Image Layer 3 │
│ (Read-only) │
├─────────────────────────┤
│ Image Layer 2 │
│ (Read-only) │
├─────────────────────────┤
│ Image Layer 1 │
│ (Read-only) │ ← Base image
└─────────────────────────┘
Part 2: Image Layers Concept
What are Image Layers?
Docker images are built in LAYERS - like a cake!
Simple Example:
Think of making a cake:
Layer 1 (Bottom): Cake base
Layer 2: Cream filling
Layer 3: Chocolate layer
Layer 4: Icing
Layer 5 (Top): Decorations
Each layer is separate,
but together they make the whole cake!
Docker Image Layers:
Example: Building a Python web app image
Layer 1: Base OS (Ubuntu) [200MB]
↓
Layer 2: Python installed [+300MB]
↓
Layer 3: Pip packages installed [+50MB]
↓
Layer 4: Your application code [+10MB]
↓
Layer 5: Configuration files [+1MB]
Total: 561MB
Why Layers Matter - Efficiency!
Key Benefit: Layer Caching
Scenario:
You have two images:
Image A (Python Web App 1):
├── Layer 1: Ubuntu (200MB)
├── Layer 2: Python (300MB)
├── Layer 3: Flask (50MB)
└── Layer 4: App1 code (10MB)
Image B (Python Web App 2):
├── Layer 1: Ubuntu (200MB) ← Same as Image A!
├── Layer 2: Python (300MB) ← Same as Image A!
├── Layer 3: Flask (50MB) ← Same as Image A!
└── Layer 4: App2 code (10MB) ← Different
Storage needed:
Without layers: 560MB + 560MB = 1,120MB
With layers: 550MB + 10MB = 560MB
Saved: 560MB! ✓
Docker is Smart:
Docker reuses common layers:
├── Layers 1, 2, 3 stored ONCE
├── Both images share these layers
└── Only unique layers are stored separately
Multiple images using same base:
10 Python apps using same base
├── Without layers: 10 × 500MB = 5GB
└── With layers: 500MB + (10 × 10MB) = 600MB
Huge savings! ✓
Seeing Image Layers
Let's examine an image's layers!
docker pull nginx
Look at the pull output carefully:
Using default tag: latest
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete ← Layer 1
a9edb18cadd1: Pull complete ← Layer 2
589b7251471a: Pull complete ← Layer 3
186b1aaa4aa6: Pull complete ← Layer 4
b4df32aa5a72: Pull complete ← Layer 5
a0bcbecc962e: Pull complete ← Layer 6
Each line = One layer being downloaded!
Inspect image layers:
docker history nginx
Output:
IMAGE CREATED CREATED BY SIZE
605c77e624dd 2 weeks ago CMD ["nginx" "-g" "daemon off;"] 0B
<missing> 2 weeks ago STOPSIGNAL SIGQUIT 0B
<missing> 2 weeks ago EXPOSE map[80/tcp:{}] 0B
<missing> 2 weeks ago ENTRYPOINT ["/docker-entrypoint.sh"] 0B
<missing> 2 weeks ago COPY docker-entrypoint.sh / 1.2kB
<missing> 2 weeks ago RUN /bin/sh -c set -x && apt-get update... 61MB
<missing> 2 weeks ago ENV NGINX_VERSION=1.25.3 0B
<missing> 2 weeks ago LABEL maintainer=NGINX Docker Maintainers 0B
<missing> 3 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 3 weeks ago /bin/sh -c #(nop) ADD file:d25aab2dd... in / 77MB
Understanding the output:
CREATED BY = Command that created this layer
SIZE = How much storage this layer uses
Notice:
├── Some layers are 0B (just metadata)
├── Large layers are actual files
└── Total = Sum of all layer sizes
Layer Caching in Action
Example: Pull Python image
docker pull python:3.11
Now pull Python with different tag:
docker pull python:3.11-slim
Watch the output:
a2abf6c4d29d: Already exists ← Docker reused this!
b8e89f3d8926: Already exists ← And this!
c9f8e5d2a1b3: Pull complete ← Only downloading new layers
What happened:
python:3.11 and python:3.11-slim share base layers:
├── Both use same Ubuntu base
├── Docker: "I already have these layers!"
├── Only downloads different layers
└── Faster download! Less storage! ✓
Part 3: Docker Hub - The Image Repository
What is Docker Hub?
Simple Definition:
Docker Hub = The "App Store" for Docker images.
Website: https://hub.docker.com
What you can find:
Docker Hub contains:
├── Official Images (verified by Docker)
├── Community Images (made by users)
├── Public Images (free to download)
├── Private Images (your own, paid feature)
└── Millions of ready-to-use images!
Exploring Docker Hub
Let's explore Docker Hub together!
Open browser and go to: https://hub.docker.com
Homepage shows:
┌────────────────────────────────────┐
│ Docker Hub │
│ │
│ [Search box] │
│ │
│ Popular Images: │
│ ├── nginx │
│ ├── ubuntu │
│ ├── python │
│ ├── node │
│ ├── postgres │
│ └── mysql │
└────────────────────────────────────┘
Searching for Images
Method 1: On Docker Hub Website
1. Go to hub.docker.com
2. Use search box at top
3. Type: nginx
4. Press Enter
You'll see:
├── nginx (Official Image) ⭐
├── nginx-proxy
├── nginx-alpine
└── Many more...
Method 2: Using Command Line
docker search nginx
Output:
NAME DESCRIPTION STARS OFFICIAL
nginx Official build of Nginx. 19000+ [OK]
jwilder/nginx-proxy Automated nginx proxy for Docker containers 2000+
nginxinc/nginx-unpri... Unprivileged NGINX Dockerfiles 150+
nginx/nginx-ingress NGINX and NGINX Plus Ingress Controllers 100+
...
Understanding columns:
NAME = Image repository name
DESCRIPTION = What the image does
STARS = Like GitHub stars (popularity)
OFFICIAL = [OK] means official image ✓
Understanding Image Names
Full Image Name Format:
REGISTRY/USERNAME/REPOSITORY:TAG
Examples:
1. nginx:latest
└── Short form (Docker Hub default)
Full: docker.io/library/nginx:latest
2. ubuntu:22.04
└── Short form
Full: docker.io/library/ubuntu:22.04
3. myusername/myapp:v1.0
└── User image with version tag
4. ghcr.io/company/app:latest
└── GitHub Container Registry
Breaking it down:
docker.io/library/nginx:latest
│ │ │ │
│ │ │ └── TAG (version)
│ │ └──────── REPOSITORY (image name)
│ └──────────────── USERNAME/NAMESPACE
└──────────────────────── REGISTRY (where it's stored)
When you type:
docker pull nginx
Docker automatically expands to:
docker pull docker.io/library/nginx:latest
Part 4: Official vs Community Images
Official Images
What are Official Images?
Official Images are:
├── Curated by Docker, Inc.
├── Verified and maintained
├── Security scanned regularly
├── High quality
├── Best practices followed
└── Marked with "Official Image" badge
Examples:
├── nginx
├── ubuntu
├── python
├── node
├── redis
├── postgres
└── mysql
How to identify:
On Docker Hub:
├── Badge says: "Docker Official Image"
├── Name is simple: nginx (not username/nginx)
└── Usually most popular (high stars)
In command:
docker search nginx
└── OFFICIAL column shows: [OK]
Viewing Image Details on Docker Hub
Let's look at nginx image in detail:
Go to: https://hub.docker.com/_/nginx
Page shows:
┌────────────────────────────────────────────┐
│ nginx │
│ Docker Official Image │
│ ⭐ 19,000+ stars │
│ │
│ [Overview] [Tags] [Dockerfile] │
│ │
│ Description: │
│ Official build of Nginx web server... │
│ │
│ Quick reference: │
│ ├── Where to file issues │
│ ├── Maintained by │
│ └── Supported architectures │
│ │
│ How to use this image: │
│ $ docker run -d -p 80:80 nginx │
│ │
│ Environment Variables: │
│ ... │
│ │
│ Volumes: │
│ ... │
└────────────────────────────────────────────┘
Available Tags
Click "Tags" tab on nginx page:
Tags show different versions:
┌────────────────────────────────────────┐
│ TAG SIZE UPDATED │
├────────────────────────────────────────┤
│ latest 141MB 1 day ago│
│ 1.25 141MB 1 day ago│
│ 1.25.3 141MB 1 day ago│
│ 1.25-alpine 41MB 1 day ago│
│ stable 141MB 1 week │
│ stable-alpine 41MB 1 week │
│ mainline 143MB 2 days │
│ alpine 41MB 1 day │
└────────────────────────────────────────┘
Understanding tags:
latest = Most recent stable version
1.25 = Major.minor version
1.25.3 = Specific version (major.minor.patch)
alpine = Lightweight version (smaller)
stable = Current stable release
mainline = Development version
Why so many tags?
Different use cases:
Production:
└── Use specific version: nginx:1.25.3
└── Ensures consistency
Development:
└── Use latest: nginx:latest
└── Always get updates
Low resources:
└── Use alpine: nginx:alpine
└── Smaller size
Alpine vs Regular Images
What is Alpine?
Alpine Linux:
├── Minimal Linux distribution
├── Only 5MB base size!
├── Includes only essentials
└── Used for lightweight images
Regular (Debian/Ubuntu based):
├── Full-featured Linux
├── More packages included
├── Larger size
└── More compatible
Size Comparison:
nginx:latest = 141MB (Debian-based)
nginx:alpine = 41MB (Alpine-based)
Difference: 100MB saved! ✓
python:3.11 = 1.01GB
python:3.11-alpine = 51MB
Difference: 959MB saved! ✓
When to use each:
Use Regular (Debian/Ubuntu):
├── Need specific packages
├── Better compatibility
├── Easier debugging
└── Size not critical
Use Alpine:
├── Want smaller images
├── Faster downloads
├── Save disk space
└── Basic functionality enough
Community Images
What are Community Images?
Community Images:
├── Created by individual users
├── Often by companies/organizations
├── Not officially verified
├── May be high quality or not
└── Username included in name
Examples:
├── jwilder/nginx-proxy
├── bitnami/nginx
├── linuxserver/nginx
└── company/custom-app
How to evaluate community images:
Before using, check:
1. Stars (popularity):
└── High stars = trusted by many
2. Downloads (pull count):
└── Many downloads = widely used
3. Last updated:
└── Recently updated = actively maintained
4. Description:
└── Clear documentation = professional
5. Dockerfile availability:
└── Can review what's inside
6. User/organization reputation:
└── Known company = more trustworthy
Verified Publishers
Another category on Docker Hub:
Verified Publishers:
├── Companies verified by Docker
├── More trustworthy than random users
├── Examples:
│ ├── bitnami/*
│ ├── gitlab/*
│ └── microsoft/*
└── Badge: "Verified Publisher"
Part 5: Pulling and Managing Images
Pulling Specific Versions
Pull latest version:
docker pull nginx
# Same as: docker pull nginx:latest
Pull specific version:
docker pull nginx:1.25.3
Pull alpine version:
docker pull nginx:alpine
Pull from specific registry:
# From GitHub Container Registry
docker pull ghcr.io/company/app:latest
# From AWS ECR
docker pull 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:v1.0
Listing Images (Detailed)
docker images
Output:
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 2 weeks ago 141MB
nginx alpine 8e75cbc5b25c 2 weeks ago 41MB
nginx 1.25.3 605c77e624dd 2 weeks ago 141MB
python 3.11 a5d7930b60cc 4 weeks ago 1.01GB
ubuntu 22.04 ba6acccedd29 3 weeks ago 77.8MB
Notice:
Same IMAGE ID for nginx:latest and nginx:1.25.3:
605c77e624dd = 605c77e624dd
Why?
└── They're the SAME image!
└── Just different tags pointing to same image
└── No extra storage used! ✓
Filtering Images
Show images from specific repository:
docker images nginx
Output:
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 2 weeks ago 141MB
nginx alpine 8e75cbc5b25c 2 weeks ago 41MB
nginx 1.25.3 605c77e624dd 2 weeks ago 141MB
Show dangling images (unused):
docker images -f "dangling=true"
Dangling images = layers with no tag:
<none> <none> b8d7c9f3e5a1 1 week ago 150MB
<none> <none> c9e1d4f6a8b2 2 weeks ago 200MB
These are leftover layers from old builds
Inspecting Images
Get detailed information:
docker image inspect nginx
Output (JSON format):
[
{
"Id": "sha256:605c77e624dd...",
"RepoTags": [
"nginx:latest"
],
"Created": "2025-01-15T10:30:00Z",
"Size": 141000000,
"Architecture": "amd64",
"Os": "linux",
"Config": {
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:...",
"NGINX_VERSION=1.25.3"
],
"Cmd": [
"nginx",
"-g",
"daemon off;"
],
"ExposedPorts": {
"80/tcp": {}
}
}
}
]
Useful information from inspect:
Id = Full image hash
Size = Total size in bytes
Created = When image was built
Config.Cmd = Default command to run
Config.Env = Environment variables
ExposedPorts= Which ports container uses
Tagging Images
Give an image another name/tag:
docker tag nginx:latest my-nginx:v1.0
Check result:
docker images
Output:
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 2 weeks ago 141MB
my-nginx v1.0 605c77e624dd 2 weeks ago 141MB
↑ ↑
New name Same IMAGE ID!
What happened:
docker tag creates another reference to same image:
Original:
nginx:latest → Image 605c77e624dd
After tagging:
nginx:latest → Image 605c77e624dd
my-nginx:v1.0 → Image 605c77e624dd (same!)
No extra storage used!
Just another name pointing to same image ✓
Removing Images
Remove by name:
docker rmi nginx:alpine
Remove by ID:
docker rmi 605c77e624dd
Remove multiple:
docker rmi nginx:latest ubuntu:22.04 python:3.11
Force remove (even if containers exist):
docker rmi -f nginx:latest
Remove all unused images:
docker image prune
Output:
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Deleted Images:
untagged: ...
deleted: sha256:...
deleted: sha256:...
Total reclaimed space: 1.5GB
Remove ALL images (careful!):
docker image prune -a
Saving and Loading Images
Save image to file:
docker save nginx:latest -o nginx-backup.tar
What this does:
Creates a .tar file containing:
├── All image layers
├── Metadata
└── Configuration
File: nginx-backup.tar (141MB)
Use case:
└── Transfer image to another computer without internet
Load image from file:
docker load -i nginx-backup.tar
Output:
Loaded image: nginx:latest
Image restored! ✓
Practical scenario:
Computer A (with internet):
1. docker pull nginx
2. docker save nginx -o nginx.tar
3. Copy nginx.tar to USB drive
Computer B (no internet):
1. Copy nginx.tar from USB
2. docker load -i nginx.tar
3. docker run nginx ✓
Transfer images offline! ✓
Practice Exercises
Let's practice everything we learned!
Exercise 1: Explore Docker Hub
1. Go to hub.docker.com
2. Search for "redis"
3. Click on official redis image
4. Read the description
5. Check available tags
6. Note the size differences between tags
Exercise 2: Pull and Compare Images
# Pull different versions
docker pull redis:latest
docker pull redis:alpine
docker pull redis:7.2
# List and compare sizes
docker images redis
# Question: Which is smallest? Why?
Exercise 3: Inspect Images
# Inspect nginx
docker image inspect nginx:latest
# Find answers:
# - What is the default command?
# - Which ports are exposed?
# - What environment variables are set?
Exercise 4: Tag and Manage
# Pull an image
docker pull ubuntu:22.04
# Create custom tags
docker tag ubuntu:22.04 my-ubuntu:v1
docker tag ubuntu:22.04 my-ubuntu:production
# List all
docker images my-ubuntu
# Remove one tag
docker rmi my-ubuntu:v1
# Check - original still there?
docker images ubuntu
Exercise 5: Cleanup
# See all images
docker images
# Remove unused images
docker image prune
# Remove specific image
docker rmi redis:7.2
# Verify removal
docker images redis
Summary
What We Learned:
✅ What Docker images are
✅ Image layers and how they work
✅ Layer caching benefits
✅ Docker Hub exploration
✅ Official vs Community images
✅ Image tags and versions
✅ Alpine vs Regular images
✅ Pulling specific versions
✅ Listing and filtering images
✅ Inspecting image details
✅ Tagging images
✅ Removing images
✅ Saving/Loading images
Key Concepts:
1. Images are templates (read-only)
2. Images are built in layers
3. Layers are cached and reused
4. Tags are different names for same/different versions
5. Official images are more trustworthy
6. Alpine images are smaller
7. Always check Docker Hub for documentation
No comments:
Post a Comment