What is a Dockerfile?

A Dockerfile is a recipe for building a Docker image.

Dockerfile

docker build

    Image

docker run

  Container

Think of it like:

Recipe -> Cake
Source -> Binary
Dockerfile -> Image

Basic Dockerfile

FROM ubuntu:24.04
 
CMD ["bash"]

Build:

docker build -t myubuntu .

Run:

docker run -it myubuntu

Common Instructions

FROM

Base image.

FROM ubuntu:24.04

RUN

Execute commands while building the image.

RUN apt-get update && \
    apt-get install -y git vim tree

RUN executes only during docker build.


WORKDIR

Set the working directory for subsequent instructions.

WORKDIR /workspace

Equivalent to:

cd /workspace

for all following instructions.


COPY

Syntax:

COPY <source> <destination>

Examples:

COPY hello.txt /tmp/
COPY . .
COPY . /app

COPY . . means:

  • First .: current build context (host)
  • Second .: current working directory inside the image

Usually used together with:

WORKDIR /app
COPY . .

ENV

Define environment variables.

ENV APP_HOME=/workspace

CMD

Default command executed when the container starts.

CMD ["bash"]

Can be overridden:

docker run myimage ls

ENTRYPOINT

Defines the executable.

ENTRYPOINT ["python3"]

Then

docker run myimage script.py

actually runs

python3 script.py

Docker Image Layers

Example:

FROM ubuntu
 
RUN apt-get update
RUN apt-get install -y git
WORKDIR /app
COPY . .
RUN make

Layers:

Ubuntu
├── apt update
├── install git
├── WORKDIR
├── COPY source
└── make

Docker caches each layer.

If only source code changes, Docker reuses the earlier layers and rebuilds only:

COPY
RUN make

Layer Ordering

Good:

FROM ubuntu
 
RUN apt-get update
RUN apt-get install -y git
 
WORKDIR /app
 
COPY . .
 
RUN make

Bad:

COPY . .
 
RUN apt-get install -y git

Changing one source file forces all later layers to rebuild.


Build Context

The final . in:

docker build -t myapp .

means:

Send the current directory to Docker as the build context.

COPY . . copies files from this build context.


.dockerignore

Exclude unnecessary files from the build context.

Example:

.git
build
node_modules
*.log
*.o

Almost every real project should have a .dockerignore.


Build

docker build -t myimage .

Specify Dockerfile:

docker build -f Dockerfile.dev -t myimage .

Naming Convention

Docker 29+ accepts both:

Dockerfile
dockerfile

However, the community convention is:

Dockerfile

Reasons:

  • Matches documentation
  • Used by nearly all open-source projects
  • Better IDE support
  • More portable across environments

Best Practices

  • Keep stable instructions first.
  • Put COPY . . near the end.
  • Use .dockerignore.
  • Use WORKDIR instead of manually creating directories.
  • Build images once; run containers many times.

Key Takeaways

  • Dockerfile describes how to build an image.
  • docker build creates an image.
  • docker run creates a container from the image.
  • Docker caches image layers to speed up rebuilds.
  • COPY . . copies the build context into the current WORKDIR.
  • Prefer Dockerfile as the filename even though modern Docker also accepts dockerfile.