🚀 Mastering the Dockerfile: A Developer’s Guide to Building Images with Docker

Sonica SonawaneSonica Sonawane
4 min read

If you're exploring Docker, one of the first tools you’ll encounter is the Dockerfile, a script that defines how to build a Docker image from the ground up. Whether you're containerizing a simple web app or creating complex multi-stage builds, the Dockerfile is your starting point.

In this post, we’ll walk through what a Dockerfile is, why it’s important, and break down each key instruction with explanations and use-cases.


📦 What is a Dockerfile?

A Dockerfile is a text document that contains a series of commands/instructions. These commands tell Docker how to build an image, layer by layer.

Think of it as a recipe for your application’s container. Instead of manually typing out commands to install packages, set environment variables, or copy files, you write it all in a Dockerfile—once—and Docker handles the rest.


🧱 Dockerfile Basics

📝 Format

# This is a comment
INSTRUCTION arguments
  • Instructions are not case-sensitive, but UPPERCASE is preferred for readability.

  • The file must begin with a FROM instruction.

  • Docker executes each line in the Dockerfile in order to create the image.


🔧 Essential Dockerfile Instructions (With Examples)

Here’s a breakdown of the most commonly used Dockerfile instructions:

1. FROM – The Base Image

FROM ubuntu:20.04

This defines the base image you’re building on. Every Dockerfile must start with a FROM.


2. RUN – Execute Commands

RUN apt-get update && apt-get install -y curl

Used to run shell commands during build time. Each RUN creates a new image layer.


3. COPY – Copy Local Files

COPY ./app /usr/src/app

Copies files or directories from your host into the image.


4. ADD – Like COPY but More

ADD https://example.com/file.tar.gz /tmp/

Adds files/directories with support for remote URLs and automatic unpacking of compressed files.


5. CMD – Default Command

CMD ["node", "app.js"]

Defines the default command to run when the container starts. Can be overridden.


6. ENTRYPOINT – Main Executable

ENTRYPOINT ["python3"]

Like CMD, but preferred when the container is meant to run a single application. Can work with CMD for additional arguments.


7. ENV – Set Environment Variables

ENV NODE_ENV=production

Persists an environment variable in the image.


8. ARG – Build-Time Variables

ARG VERSION=1.0
RUN echo $VERSION

Used to pass values at build time using --build-arg.


9. EXPOSE – Document Ports

EXPOSE 3000

Indicates which port the container listens on (documentation only; doesn’t actually publish the port).


10. WORKDIR – Set Working Directory

WORKDIR /usr/src/app

Sets the directory for subsequent instructions.


11. USER – Set User

USER node

Specifies the username or UID the container should use.


12. VOLUME – Define Mount Point

VOLUME /data

Creates a mount point for external volumes.


13. LABEL – Add Metadata

LABEL maintainer="sonica@example.com"

Useful for adding metadata like version, author, or license.


14. HEALTHCHECK – Monitor Container Health

HEALTHCHECK CMD curl --fail http://localhost:3000 || exit 1

Used to define a command that tests the container's health.


15. STOPSIGNAL – Signal to Stop

STOPSIGNAL SIGTERM

Specifies the system signal used to stop the container gracefully.


16. ONBUILD – Trigger for Child Builds

ONBUILD COPY . /app

Used to define instructions that execute later, when the image is used as a base for another build.


17. SHELL – Override Default Shell

SHELL ["/bin/bash", "-c"]

Changes the shell used for RUN commands.


📁 Sample Dockerfile: Node.js App

# Step 1: Base image
FROM node:18

# Step 2: Set working directory
WORKDIR /usr/src/app

# Step 3: Copy files
COPY package*.json ./
RUN npm install

COPY . .

# Step 4: Expose port and set command
EXPOSE 3000
CMD ["node", "server.js"]

🔍 Tips for Writing Better Dockerfiles

  • Minimize the number of layers by combining commands using &&.

  • Use .dockerignore to avoid copying unnecessary files.

  • Always pin to specific versions (e.g., python:3.11-slim) for consistency.

  • Keep your images lean by removing cache, temp files, or using alpine base images.


🧠 Final Thoughts

The Dockerfile is a cornerstone of containerized development. Once you master it, you'll have full control over how your application images are built, configured, and run.

If you’re just getting started with Docker, creating and modifying Dockerfiles is a great way to build hands-on skills. Start small, experiment often, and you'll be Docker-fluent in no time!


🔗 Resources


Let’s learn together. 🐳💬

0
Subscribe to my newsletter

Read articles from Sonica Sonawane directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Sonica Sonawane
Sonica Sonawane

Hi, I'm Sonica! 👋 I’m currently diving into the world of DevOps, focusing on AWS, Docker, Kubernetes, Linux, and GitHub. My passion lies in automating systems, building cloud infrastructure, and optimizing workflows. I’m committed to continuous learning, hands-on projects, and sharing my journey with others in the tech community. Before shifting to DevOps, I worked in IT Sales, where I gained valuable skills in client communication, requirement gathering, and problem-solving. This experience taught me how to connect technical solutions to business needs, which has been instrumental as I transition into DevOps, where technical expertise and problem-solving go hand in hand. Now, I’m eager to apply my sales experience alongside my growing technical skills in cloud engineering and DevOps. Join me as I explore the latest trends, challenges, and solutions in the world of cloud computing!