DevLearningTools

LEARN · DOCKER

Dockerfile and Building an Image

A Dockerfile is a text file of instructions that Docker follows to build an image. Learn the common instructions, what EXPOSE really does, and how instruction order affects build speed.

A Dockerfile is a plain text file with one instruction per line. Docker runs the instructions top to bottom to build an image. The order matters, because Docker reuses earlier steps when nothing above them has changed.

Learning Objectives

  • Read a Dockerfile and say what each instruction does.
  • Explain what EXPOSE does and doesn't do.
  • Order instructions so rebuilds stay fast.

A Simple Dockerfile

Dockerfile
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "app.py"]

What Each Instruction Does

InstructionPurpose
FROMThe base image to build on
WORKDIRThe folder commands run in inside the image
COPYCopies files from your project into the image
RUNRuns a command while building, such as installing packages
EXPOSEDocuments the port the app listens on
CMDThe command a container runs when it starts

A Real Detail: EXPOSE Doesn't Open a Port

EXPOSE only documents which port the app uses. It doesn't make the port reachable from your computer. To publish it, you map it when you run the container with -p, for example docker run -p 8000:8000. Docker's own documentation says EXPOSE is documentation between the person who builds the image and the person who runs it.

Why the Order Matters

Copying requirements.txt and installing packages before copying the rest of the code means that changing a line of application code doesn't reinstall every package. Docker reuses the cached install step, so rebuilds take seconds instead of minutes.

Build It

Shell
docker build -t my-python-app .
docker run -p 8000:8000 my-python-app
NOTE

The . at the end tells Docker to use the current folder as the build context, which is where COPY reads files from.

Learning Check

Why put COPY requirements.txt before COPY . .?

So the package install step is cached. Changing application code only reruns the final COPY, not the install.

Does EXPOSE 8000 make the app reachable from my browser?

No. You also need -p 8000:8000 when running the container.

Step by Step: Build and Run Your Own Image

  • Create a project folder with your app file and a requirements.txt listing its packages.
  • Create a file named Dockerfile (no extension) with the instructions from above.
  • Create a .dockerignore file that lists files Docker should not copy, such as .git and __pycache__.
  • Build the image: docker build -t my-python-app .
  • Run it with a port mapping: docker run -p 8000:8000 my-python-app, then open http://localhost:8000.

Common Mistakes

Copying all the code before installing packages

Any code change then invalidates the install cache, so every build reinstalls everything. Copy requirements.txt first, install, then copy the rest.

Forgetting a .dockerignore file

Without it, COPY . . also copies .git folders, local virtual environments, and secret files into the image.

Assuming EXPOSE makes the port reachable

EXPOSE only documents the port. Publish it with -p when you run the container.

Running the app as root by default

Many images run processes as root. Create a non-root user in the Dockerfile for production images.

Interview Questions

What's the difference between CMD and ENTRYPOINT?

ENTRYPOINT sets the executable that always runs. CMD provides default arguments to it, and those can be overridden when you run the container.

Why does instruction order matter in a Dockerfile?

Docker caches each instruction's result. Putting rarely changing steps first means changes lower down reuse the cache above them.

What does a .dockerignore file do?

It lists files and folders excluded from the build context, which keeps images smaller and stops secrets or local files from being copied in.

Summary

A Dockerfile lists the steps that build an image. Put the instructions that change least often near the top so Docker can reuse them, and remember that EXPOSE documents a port while -p publishes it.