🕵️ Episode 3: Of Images and Illusions

DinakarDinakar
6 min read

A cold morning breeze drifted into 221B Baker Street. Holmes stood silently near the window, sipping a steaming cup of coffee, his gaze fixed on the grey drizzle that patterned the glass.

I, Watson, sat by the fireplace, replaying Holmes’ last words in my head.

“The details, Watson, are in the layers.”

"What details?" I muttered aloud, lost in thought.

Holmes turned. “Still curious, I see,” he said, walking toward his desk. “Good. Because today, we begin to understand the image.”


đź§ľ The Blueprint of the Lab

Holmes retrieved a folded sheet from his notebook — a sample Dockerfile and its related python file

#app.py
from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return 'Hello, Docker!'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
# Use a lightweight Python base image
FROM python:3.10-slim

# Set the working directory inside the container
WORKDIR /app

# Copy the application files
COPY . /app

# Install dependencies
RUN pip install -r requirements.txt   #I created a file called requirements.txt with flask as dependency

# Define the default command
CMD ["python", "app.py"]

“This,” Holmes said, “is a Dockerfile. The blueprint. Every line is an instruction — like tasks assigned to a clerk in an office.”

He picked up a chalk and wrote on the board:

  • FROM: Choose the base system. Like selecting your office building.

  • WORKDIR: Set where you'll work inside the building.

  • COPY: Bring your files and folders into the space.

  • RUN: Setup — install software or arrange files.

  • CMD: The final task to execute when everything is ready.

“Each command builds upon the previous — forming layers. Change one, and the ones above may need to be redone. Docker caches these layers to save time.”


đź§Ş Building the Image

Following Holmes’ instructions, I typed into my terminal:

docker build -t python-app .

Lines scrolled by. The image was being created.

“You’ve just constructed a portable workspace,” Holmes said. “Identical, every time. No surprises.”


🚀 Running the Container

He scribbled another command and handed me the note:

docker run -d -p 5000:5000 python-app

I watched as my app launched in the browser. Running independently. Reliably.

“A container, Watson, is a copy of your image — alive and executing.”


❌ Breaking and Rebuilding

Holmes turned suddenly. “Delete the image.”

docker rmi -f python-app

Then I tried running the app again:

docker run python-app

The terminal replied with an error: Unable to find image 'python-app:latest' locally

“Without the recipe,” Holmes said, “you can’t bake the cake. Simple, isn’t it?”


🏗️ Multi-Stage Build – For Clean Setup

Holmes next handed me an upgraded Dockerfile.

# Stage 1 - Builder
FROM python:3.10-slim AS builder
WORKDIR /app
COPY . .
RUN pip install --no-cache-dir -r requirements.txt

# Stage 2 - Final Image
FROM python:3.10-slim
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.10/site-packages/ /usr/local/lib/python3.10/site-packages/
COPY app.py requirements.txt ./
CMD ["python", "app.py"]

“In the real world, we don’t carry everything to production — only what’s needed. This is a multi-stage build — it reduces image size and exposure.”

I nodded slowly, understanding how this cleaned up the image and improved efficiency.


🛠️ Other Useful Dockerfile Instructions

Holmes quickly listed more useful commands on his blackboard:

CommandPurpose
ENVSet environment variables
EXPOSEDefine the port container will listen to
ARGDefine variables passed at build-time
ENTRYPOINTAlternative to CMD, defines main executable
LABELAdd metadata (e.g., maintainer info)

These, Holmes said, “are tools. Use them wisely — your image becomes not just functional, but elegant.”


🖼️ Pages & Chalk dust: Holmes' Visual Clues

Holmes stepped over to his desk and pulled out a tattered sheet from his leather-bound diary. With his usual precision, he passed it to me across the table.

“Here,” he said, “is how an image truly forms — layer by layer. Each instruction in the Dockerfile stacks neatly upon the last, forming a tower of logic.”

I looked closely at the aged page. It had the now familiar Docker file next to a stack of labelled boxes — the base image forming the foundation, with additional layers above, annotated with terms like Layer A, Layer B, and Layer C. On the side, an arrow pointed upward marked Update Frequency.

It’s not just a build process, Holmes murmured. It’s a story… and like any story, the beginning defines the end.

Moments later, he walked across the room and picked up a stick of chalk, standing before the board with a sense of theatrical flair. He began sketching again.

“Let’s now refine the story. In reality, we don’t need to carry the whole lab to production — only the results. That’s where multi-stage builds shine.”

With clear strokes, Holmes illustrated two distinct stages on the board:

  • On the left, a builder stage — filled with tools, dependencies, and source code.

  • On the right, a final stage — stripped to the essentials, lean and production-ready.

A good build, he said with a wink, “knows what to leave behind.”


🕰️ The Mystery Deepens

Holmes leaned back in his chair, flipping open his favorite hardbound book. The fire crackled faintly in the silence. Then, just before disappearing into the world of pages, he looked up.

“A sealed lab is safe, Watson… but what good is it if no one can knock on the door?”

He gave me a brief, knowing glance and returned to his book, the glint in his eyes sharper than the flame beside him.

I sat frozen, the container still humming silently on my screen.
A perfect setup. A flawless image.
And yet… no sound, no signal, no sign that it existed to the outside world.

How does one speak to something sealed so tight? How do I open a line of communication… without breaking the box?

The drizzle outside had long stopped.
But now, the questions had begun — a rain of thoughts, persistent and uninvited.


📓 Watson’s Journal — Key Learnings from Episode 3

🗒️ Filed on: The day I constructed the lab’s foundation

đź§  Concepts I Learnt:

  • A Dockerfile defines how to build an image — a portable, layered environment.

  • Docker caches layers to speed up rebuilds.

  • A container is a running instance of the built image.

  • Multi-stage builds keep images lean by separating build and run phases.

  • Additional Dockerfile commands (ENV, EXPOSE, etc.) help refine behavior.

đź’» Commands Used (Windows):

docker build -t python-app .               # Build image
docker run -d -p 5000:5000 python-app      # Run container
docker rmi -f python-app                      # Delete image
docker run python-app                      # Attempt to run deleted image

đź’ˇ Realization:

  • A Dockerfile defines how to build a Docker image, layer by layer — each command adds a new layer.

  • The image serves as a portable blueprint, while a container is its running instance.

  • Commands like FROM, WORKDIR, COPY, RUN, and CMD follow a logical sequence that mimics setting up an app environment.

  • A multi-stage build keeps the image lean by separating build-time and runtime layers.

  • Supporting instructions like ENV, EXPOSE, and ENTRYPOINT help fine-tune the image’s behaviour.

  • I now understand that building with Docker is like engineering a controlled environment — defined, consistent, and repeatable.

0
Subscribe to my newsletter

Read articles from Dinakar directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Dinakar
Dinakar