Dockerfile Tutorial: FROM, COPY, ADD, RUN, CMD

dockerfile tutorial from run cmd example

In our previous blog, we learned about Docker basics and commands. Now, we are learning the essential skill of writing a Dockerfile.

In this blog, you will learn:

  • What a Dockerfile is and why it’s needed
  • Syntax of a Dockerfile
  • Explanation of each instruction: FROM, LABEL, WORKDIR, COPY, ADD, RUN, EXPOSE, CMD, and ENTRYPOINT.
  • Best practices for efficient Dockerfiles
  • How to write a Dockerfile for a Python application

By the end of this blog, you’ll be able to write Dockerfiles confidently for any application.


What Is a Dockerfile?

A Dockerfile is a plain text file that contains a set of instructions used to build a Docker image. Each instruction creates a new layer in the image.


Why You Need a Dockerfile

  • Build images consistently every time.
  • Share the Dockerfile so anyone can build the same image.
  • Store Dockerfiles in Git for version control.
  • Run the same image on any machine without compatibility issues.

Before learning Dockerfiles in depth, check our Docker Tutorial for Beginners – Installation, Introduction, and Basic Commands for a solid foundation.


Syntax of a Dockerfile

INSTRUCTION argument
  • Instructions are written in uppercase by convention.
  • Common instructions are: FROM, LABEL, WORKDIR, COPY, ADD, RUN, EXPOSE, CMD, and ENTRYPOINT.
  • Arguments vary for each instruction.
  • Docker executes instructions from top to bottom, creating a new layer for each step.

Dockerfile Instructions

1. FROM

Sets the base image for your Docker image. It can be an OS image like Ubuntu or a language image like Python or Java.

Note: Use lightweight base images to reduce image size and improve security.

FROM python:3.11-slim

2. LABEL

Used to add metadata to a Docker image. This helps describe the image.

Arguments are written in key-value format.

LABEL maintainer="venkat@thedevopsguide.in" \
version="1.0" \
description="Docker tutorial app" \
project="The DevOps Guide"

3. WORKDIR

Sets the working directory inside the container. All following instructions run in this directory unless changed.

WORKDIR /app

4. COPY

Copies files or directories from the local system into the Docker image.

COPY requirements.txt .

5. ADD

Similar to COPY, but also supports downloading files and extracting local archives.

Best practice: Use COPY unless you specifically need ADD features.

ADD https://example.com/app.tar.gz /app/

6. RUN

Used to install dependencies or execute commands during the image build process.

RUN pip install --no-cache-dir -r requirements.txt

7. EXPOSE

Documents which port the container listens on. It does not publish the port.

EXPOSE 5000

8. CMD

Defines the default command that runs when the container starts. If multiple CMD instructions exist, only the last one is used.

RUN executes at build time, while CMD runs at container start time. CMD can be overridden at runtime.

CMD ["python", "app.py"]

9. ENTRYPOINT

Similar to CMD, but it is not easily overridden. It is commonly used for fixed startup commands.

ENTRYPOINT ["python", "app.py"]

10. ARG

Defines build-time variables. These variables are not available inside the running container unless passed to ENV.

ARG APP_VERSION=1.0

11. ENV

Defines environment variables that are available inside the running container.

ENV MODE=prod

12. USER

Runs the container using a specified user instead of root.

USER 1001

Best Practices for Dockerfiles

  • Use small base images like python:3.11-slim.
  • Optimize layers by combining RUN commands.
  • Use a .dockerignore file.
  • Ignore unnecessary files like logs, venv/, and .git/.
  • Use multi-stage Dockerfiles for smaller final images.
  • Avoid running containers as root for better security.

Multi-Stage Dockerfile Example

Multi-stage Dockerfiles help reduce image size by separating the build environment from the runtime environment.

# Stage 1: Build stage
FROM python:3.11-slim AS builder

WORKDIR /app

COPY requirements.txt .

RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

COPY . .


# Stage 2: Runtime stage
FROM python:3.11-slim

WORKDIR /app

COPY --from=builder /install /usr/local

COPY --from=builder /app /app

EXPOSE 5000

CMD ["python", "app.py"]
  • The first stage installs dependencies and prepares the app.
  • The second stage copies only the required files from the first stage.
  • This keeps the final image smaller and more secure.
  • Build tools and cache files are not included in the final image.

Python Application Dockerfile Example

For a simple Flask app:

# Base image
FROM python:3.11-slim

# Set working directory
WORKDIR /app

# Copy dependencies
COPY requirements.txt .

# Install dependencies
RUN pip install --no-cache-dir -r requirements.txt

# Copy app code
COPY . .

# Expose port
EXPOSE 5000

# Run the app
CMD ["python", "app.py"]
  • Lightweight and clean.
  • Works for Flask, Django, or any Python project.

How to Build and Run the Image

# Build Docker image
docker build -t my-flask-app .

# Run container
docker run -p 5000:5000 my-flask-app

Check your app at http://localhost:5000.

Be the first to comment

Leave a Reply

Your email address will not be published.


*