Objective. Students write a Dockerfile for a simple web application, build a Docker image, run the container locally, and describe how containerization improves environment consistency.
This lesson, its worked examples and its practice questions has not yet been verified by an industry-certified professional or by a certification or approval body. It is a study draft and may contain errors. Do not use it as instructions for work on a job site or on live equipment. Always follow your instructor, your supervising professional, and current official references and regulations.
VoTechWorks program approval and accreditation are still in progress. Credentials are issued only by the certifying bodies named in each program, after their own exams.
When you build a web application on your laptop, it works perfectly. Then you deploy it to a server and it crashes because the server runs a different Python version, is missing a library, or has a conflicting package. This is the classic "it works on my machine" problem. Containerization solves it by packaging your application together with everything it needs—runtime, libraries, configuration files—into a single portable unit called a container.
A container is not a virtual machine. A virtual machine emulates an entire computer, including its own operating system kernel, which makes VMs large and slow to start. Containers share the host operating system's kernel but keep each application's file system, processes, and network stack isolated. This makes containers lightweight, fast to start, and efficient with resources.
Docker is the most widely used containerization platform. It provides:
When you install Docker Engine on a Linux VPS or local machine, you get all three components you need for this lab.
Two terms are essential:
Images are built from a text file called a Dockerfile. Each line in a Dockerfile adds a layer to the image. Docker caches layers, so if you change only your application code, Docker reuses the cached OS and dependency layers—builds stay fast.
Here is a Dockerfile for a simple Python Flask application:
```
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]
```
FROM – Every Dockerfile starts with a base image. `python:3.11-slim` is an official, minimal Python 3.11 image. Using official images from Docker Hub is safer than building from scratch because they are maintained and regularly patched for security vulnerabilities.
WORKDIR – Sets the working directory inside the container. All subsequent commands run relative to this path.
COPY – Copies files from your host machine into the image. Copying `requirements.txt` before the rest of the code is intentional: it lets Docker cache the `pip install` layer separately. If you only change `app.py`, Docker skips reinstalling packages.
RUN – Executes a shell command during the image build. Use it to install dependencies. The `--no-cache-dir` flag keeps the image smaller by not storing pip's download cache.
EXPOSE – Documents which port the application listens on inside the container. It does not automatically open that port to the outside world; that happens at `docker run`.
CMD – The default command Docker runs when the container starts. Use the JSON array form (`["python", "app.py"]`) to avoid shell-wrapping issues.
From the folder containing your Dockerfile, build the image:
```
docker build -t my-flask-app .
```
The `-t` flag gives your image a name (tag). The `.` tells Docker to look for the Dockerfile in the current directory.
To run the container and make it accessible:
```
docker run -d -p 8080:5000 --name flask-demo my-flask-app
```
Open a browser to `http://localhost:8080` or run `curl http://localhost:8080` to verify the app responds.
Useful inspection commands:
| Command | What it does |
|---|---|
| `docker ps` | Lists running containers |
| `docker images` | Lists built images and their sizes |
| `docker logs flask-demo` | Shows container stdout/stderr |
| `docker stop flask-demo` | Stops the container |
| `docker rm flask-demo` | Removes the stopped container |
Because the container image includes the exact runtime and dependencies, the same image runs identically on a developer's laptop, a QA server, and a production cloud instance. This consistency is foundational to modern CI/CD pipelines: your pipeline builds the image once, runs automated tests against it, and pushes that exact artifact to production—no environment drift.
Answer each question, then check it. Nothing is recorded; this is your own practice.
A free tech program — complimentary, as our commitment to get America working. Help us build VoTechWorks. Tell us what works, what doesn’t, and what you want to learn.