Understanding Docker Images in Detail

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

Understanding Docker Images in Detail

Great! Now let's dive deep into Docker images - understanding what they are, how they work, and how to use them effectively. Part 1: U...