🕵️ Episode 3: Of Images and Illusions


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:
Command | Purpose |
ENV | Set environment variables |
EXPOSE | Define the port container will listen to |
ARG | Define variables passed at build-time |
ENTRYPOINT | Alternative to CMD, defines main executable |
LABEL | Add 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
, andCMD
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
, andENTRYPOINT
help fine-tune the image’s behaviour.I now understand that building with Docker is like engineering a controlled environment — defined, consistent, and repeatable.
Subscribe to my newsletter
Read articles from Dinakar directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
