Cloud & DevOps · PRACTICAL GUIDE

Dockerize Your First Python Application

Create a production-minded Dockerfile, build an image and run a small Python web application inside a repeatable container environment.

HANDBOOK JOURNEYByte 2 of 5View all Bytes
FAMILIAR SCENARIO

Turning a kitchen recipe into a repeatable meal

A written recipe lists ingredients and steps; the kitchen prepares a sealed meal box; the customer checks that it opens and tastes right.

01App files
02Dockerfile
03Build image
04Run + check

Connect the idea: The Dockerfile is the recipe; the image is the prepared package.

Quick Start

DOCKER HANDBOOK 02

What you will build

A tiny Flask health service packaged in a Docker image. You will understand every Dockerfile instruction, build the image, run the container, test it and inspect failures instead of copying commands blindly.

Start from Basics

Before using Docker, understand what the application does. This example has one /health address. When it is working, that address returns a small message saying the service is healthy. It also has a requirements.txt file that records the Flask library it needs.

Create app.py:

PYTHON
01from flask import Flask, jsonify0203app = Flask(__name__)0405@app.get("/health")06def health():07    return jsonify(status="healthy", service="maanavan-demo")0809if __name__ == "__main__":10    app.run(host="0.0.0.0", port=8000)

Create requirements.txt:

TEXT
01Flask==3.1.2

Pinning a version improves reproducibility. In a real project, use your team’s dependency-locking and vulnerability-update process rather than leaving dependencies permanently frozen.

Core Explanation

CONCEPT LAB 02

Build once, then run the result

Follow the command and observe what Docker creates.

Creates an image

Docker reads the Dockerfile and prepares python-health:1.0.

GUIDED COMMAND SIMULATIONRun a command and watch what Docker creates
LEARNING MODE
SIMULATED TERMINAL
$ docker build -t delivery-status:1.0 .

Click execute — no real system changes are made

DOCKER OUTPUTWAITING

The created object will appear here

Browser learning simulation — this does not execute on your computer.
QUICK PREDICTIONAfter changing app.py, is docker run alone enough?

Architecture / Flow Diagram

VISUAL EXPLAINERYOUR FIRST PYTHON CONTAINER
DOCKER
DockerfileDefine runtime
docker buildCreate image
docker runStart instance
localhostReach the app
Build converts the Dockerfile into an image. Run creates a container from that image.
BUILD → RUN → VERIFYFollow one Python app from code to browser
FOLLOW THE FLOW
01
App + requirementsInputs
02
docker buildCreate image
03
docker runStart container
04
Test endpointProve behaviour
Remember: Build creates the reusable package; run creates a disposable process from it.

Types / Components

Read the Dockerfile as seven small decisions

Create a file named exactly Dockerfile:

Dockerfile
01FROM python:3.12-slim0203WORKDIR /app0405COPY requirements.txt .06RUN pip install --no-cache-dir -r requirements.txt0708COPY app.py .0910EXPOSE 800011CMD ["python", "app.py"]

Read it from top to bottom

InstructionDecision it records
FROMThe starting runtime and filesystem
WORKDIRThe default directory for later instructions and runtime
first COPYAdd the dependency definition before frequently changing code
RUNInstall dependencies while building the image
second COPYAdd the application source
EXPOSEDocument the port the application expects to use
CMDSet the default process when a container starts

Copying requirements.txt before app.py helps Docker reuse the dependency layer when only application code changes. This is a practical use of the build cache.

Add a .dockerignore

TEXT
01__pycache__/02*.pyc03.venv/04.git/05.env

The build context is the set of files sent to the builder. A .dockerignore keeps irrelevant, large or sensitive local files out of that context. It is not your only secret-control mechanism, but it reduces accidental inclusion.

Build and start your first container

Run these commands from the directory containing the Dockerfile:

BASH
01docker build -t python-health:1.0 .02docker run --rm --name python-health -p 8000:8000 python-health:1.0

The -p 8000:8000 part creates a path from port 8000 on your laptop to port 8000 inside the container. Think of it as connecting the laptop's front door to the application's door. Ports are explained fully in Byte 03; for now, use this mapping so the browser can reach the app.

Open http://localhost:8000/health or run:

BASH
01curl http://localhost:8000/health

The expected response is a JSON object with status set to healthy. --rm removes the stopped container, not the image.

TAMIL LEARNER SUPPORT

Simple Tanglish — build vs run

docker build app package-ஐ prepare செய்து image create பண்ணும். docker run அந்த image-லிருந்து container start பண்ணும். Code change செய்தால் first image rebuild பண்ணணும்; பிறகு new container start பண்ணணும்.

Manual Setup vs Docker Image

QuestionManual setupDocker image
Who installs the runtime?Every learnerImage build
Who remembers dependencies?Setup documentDockerfile
How is a version repeated?Repeat the stepsStart the tagged image

Real-World Examples

SEE IT IN PRACTICE

Every learner receives the same kit

Imagine a Python workshop where every learner installs tools manually. Some use different Python versions, others miss a library and several have old configuration. The trainer spends the session repairing laptops.

The image is a prepared lab kit: runtime, dependency and application versions are assembled once. Each container opens a fresh instance of that kit. Learners can still have host-level differences, but the application environment is much more predictable.

BEFORE → ACTION → AFTERRead each story from the failed setup to the result the team can see.
Python health API
Before Docker
The app works locally, but there is no repeatable package.
Team action
Write the Dockerfile and build python-health:1.0.
After Docker
A container returns the expected /health response.
SETUP MATCHED
Code update
Before Docker
Karthik changes app.py, but the old container still shows the previous response.
Team action
Rebuild the image and start a new container.
After Docker
The browser shows the updated response from the new image.
SETUP MATCHED
QA handoff
Before Docker
QA receives code but does not know the exact start command.
Team action
Share the tagged image and one docker run command.
After Docker
QA starts the same prepared application.
SETUP MATCHED
Docker does not fix application bugs. In these examples, it removes uncertainty about the Python version, libraries and selected release package.

Imagine Pannunga

The image is like a prepared practical-lab kit. The Dockerfile is the packing list; docker build prepares the kit; docker run opens one working kit.

Use Cases

Each engineering role uses the same image for a different decision: build it, verify it, automate it or review what entered it.

WHO USES THIS — AND WHY?Choose the person first; the Docker benefit becomes clearer.
Application developer

“How do I record the app setup?”

Write and maintain the Dockerfile
QA engineer

“How do I verify the packaged app?”

Run the tagged image and check /health
DevOps engineer

“How do I build it consistently?”

Automate docker build in CI
Security engineer

“What entered the image?”

Review base image, dependencies and context
Docker is useful when the learner needs the same prepared application setup in another place.

Common Mistakes and Fixes

SymptomCheckLikely cause
Build cannot find a filedocker build output and current directoryWrong build context or .dockerignore rule
Container exits immediatelydocker ps -a then docker logs python-healthMain process completed or crashed
Browser cannot connectport mapping and application bind addressMissing -p or app bound only to 127.0.0.1
Code change not visibleimage creation time and tagImage was not rebuilt
Dependency install failsversion, network and package logsInvalid or unavailable package version

Useful inspection commands:

BASH
01docker image ls02docker ps -a03docker logs python-health04docker inspect python-health

Improve it later for production

The development server in this learning example is not a production server. A production Python web service should normally use a suitable application server, run as a non-root user, expose a health endpoint, receive configuration at runtime and use a deliberately selected base-image version.

Also avoid installing editors and debugging utilities “just in case.” Smaller, purpose-built images reduce attack surface and transfer time.

AVOID THESE

Common mistakes

  • Using COPY . . before dependency installation and invalidating the build cache on every edit.
  • Confusing EXPOSE 8000 with publishing a host port; docker run -p performs the publishing.
  • Binding the Python app to 127.0.0.1 inside the container.
  • Copying .env, credentials or a local virtual environment into the image.
  • Debugging by rebuilding randomly instead of reading build output and container logs.

Key Takeaways

  1. Confirm that the application works before containerising it.
  2. A Dockerfile records repeatable build decisions.
  3. docker build creates an image.
  4. docker run starts a container.
  5. .dockerignore keeps unnecessary files out.
  6. EXPOSE documents a port; -p creates the mapping.
  7. Rebuild the image after changing application code.
  8. Logs identify failures more reliably than random rebuilds.

Final Thought + Next Path

You have now moved from a Docker mental model to a working container. The important skill is not memorising every instruction; it is reading the flow: prepare a tiny working app, record its setup in a Dockerfile, build a named image, start one container and verify the visible result. In Byte 03, you will give that container three practical capabilities: a door for browser traffic, safe storage for selected data and start-time settings that can change without rebuilding the image.

FAQ + Knowledge Check

LESSON CHECKPOINTConfirm the concept before moving forward

Choose an answer, inspect the explanation and explain the idea in your own words.

RETENTION
CAREER

What happens during docker build and docker run?

Strong answer: docker build processes a Dockerfile and build context to produce a layered image. docker run creates a container from that image, adds runtime configuration such as ports and environment variables, and starts the configured process. Build-time decisions belong in the image; environment-specific configuration belongs at runtime.

Does docker run build an image? No. docker build creates the image; docker run starts a container from it.

Why use .dockerignore? To prevent irrelevant or sensitive local files from entering the build context.

Knowledge check: Which instruction defines the default startup command? CMD. What must happen after app.py changes? Rebuild the image.

Learning rule: explain the answer in your own words before checking the next Byte.

Official references

OPTIONAL LEARNING CONNECTIONS

Continue by concept

Choose only what supports your next goal. This Byte does not require either link.