Decoding Docker π : Breakdown Docker Fileπ


π Quick Intro π
Yo devs!
So If you havenβt yet messed with Docker basics - Images, Containers, Networks and Volumes, check out this cool intro I wrote
Else now you must be wondering βHow do I build my own image for my project?β
Well, the answer is simple: Dockerfile.
Letβs break it down fully - all in proper detail, but in our Indian style. No boring gyaan here! π
π What is Dockerfile ποΈ
It is basically a recipe (a text file) with step-by-step instructions for Docker on how to build your custom image for your project.
Think of it as setting up a new laptop from scratchβinstalling necessary applications and libraries, pulling your code, running the code, and more. A Dockerfile automates all of that for you.
Its like saying βOye Docker, yeh steps follow kar aur meri image bana de!β πͺ
π File Structure & Format π’
A Dockerfile is packed with multiple instructions, each lined up one after other for different tasks! π
The first and must-have instruction is
FROM
(we'll dive into this in the sections below).The correct format for writing an instruction is shown below:
# Comment (describe the purpose) COMMAND arguments
The
COMMAND
doesn't have to be in uppercase, but it's a common practice to make it stand out from the arguments.Here's a basic Dockerfile example for a Node.js app, just to give you a sneak peek of what it looks like! Get ready to dive deeper into it in the sections below β it's going to be awesome! π
# Use Node.js version 18 as the base image FROM node:18 # Set the working directory inside the container to /app WORKDIR /app # Copy all files from current directory on host to working directory in container COPY . . # Install dependencies using npm RUN npm install # Command to run when the container starts CMD ["node", "index.js"]
π Image Building ποΈ
Build Context
To build your Docker image, just run the
docker build -t <image_name> <dir>
command, and make sure you point it to the directory where your Dockerfile is hanging out.The
.dockerignore
file comes in handy when you want to skip over some files in your Docker image context directory.
Layers ποΈ
Each instruction in a Dockerfile adds a new layer. It's like stacking blocks: each step makes a container, runs the instruction, and saves the result as a new layer.
These layers pile up, and the final image is a mix of all these layers.
When you run an image and spin up a container, a new writable layer, called the container layer, gets added on top of the existing layers.
Container layer is where all the action happens β any changes you make, like adding new files, tweaking existing ones, or deleting stuff, all get handled here.
Cache πΎ
Docker keeps intermediate images to speed up future builds.
When you rebuild an image, Docker uses cached layers if nothing's changed.
"Using cache" means Docker is reusing layers it already made, instead of creating new ones.
Caching makes the build process much faster for the parts of your Dockerfile that stay the same.
π Instructions β
FROM
Sets the Base Image for the next steps.
FROM [--platform=<platform>] <image> [AS <name>] FROM [--platform=<platform>] <image>[:<tag>] [AS <name>] FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
βBhai, Python environment chahiye mujhe.β
FROM python:3.11
COPY
Copies files and directories from the host machine to the Docker image. πΈ
# syntax COPY <source> <destination> # example COPY localfile.txt /app/localfile.txt COPY . .
ADD
It copies files and directories to the Docker image, downloads files from URLs π, and unzips tar files π¦ directly into the destination folder.
# syntax ADD <source> <destination> # example ADD anotherfile.txt /app/anotherfile.txt ADD https://example.com/file.txt /app/file.txt ADD archive.tar.gz /app/
RUN
Executes commands during build (executable or shell).
# shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows RUN <command> # exec form RUN ["executable", "param1", "param2"]
βPackage install karna hai? Run it here.β
# Install python packages RUN pip install -r requirements.txt
CMD
Tells Docker what to run when container starts.
Dockerfile can only contain one CMD instruction. If you enter more than one CMD, only the last one will be executed.
Donβt confuse CMD with RUN !!! (RUN at build-time, CMD at run-time)
# exec form, this is the preferred form CMD ["executable","param1","param2"] # as default parameters to ENTRYPOINT CMD ["param1","param2"] # shell form CMD command param1 param2
"Container start hone par HOME env variable ki value print karna hai ?"
CMD echo $HOME or CMD ["sh", "-c", "echo $HOME"]
WORKDIR
Sets the working directory inside the container and changes the directory for the next commands.
So, whatever RUN, CMD, and everything else happens, it executes at the given path.
βFrom now on, kaam yahin se hoga.β
# syntax WORKDIR <directory> # example WORKDIR /usr/src/app
ENTRYPOINT
Ensures that a specific command or task always runs when the container starts, regardless of any additional commands you provide.
# exec form, which is the preferred form ENTRYPOINT ["executable", "param1", "param2"] # shell form ENTRYPOINT command param1 param2
You should include at least one CMD or ENTRYPOINT command in the Dockerfile.
If you want to use the container as a program, you need to set ENTRYPOINT.
Use CMD to set default arguments for ENTRYPOINT.
Overriding CMD and ENTRYPOINT
FROM ubuntu:latest
ENTRYPOINT ["echo", "Default ENTRYPOINT:"]
CMD ["Hello from CMD"]
# Default behaviour will be like below
# Default ENTRYPOINT: Hello from CMD
CMD can be overriden by adding more arguments when you run the container
docker run <container_name> <arguments>
docker run mycontainer "Overridden CMD" # CMD overriden output will be like below # Default ENTRYPOINT: Overridden CMD
ENTRYPOINT can be overriden by
--entrypoint
docker run --entrypoint <command> <container_name> <arguments>
docker run --entrypoint /bin/echo mycontainer "Overridden ENTRYPOINT" # ENTRYPOINT overriden output will be like below # Overridden ENTRYPOINT
LABEL
Adds metadata (information) to the image.
βYeh image maine banaya hai β haan bhai, credit toh banta hai!β π
LABEL maintainer="you@example.com"
SHELL
The SHELL instruction lets you switch up the default shell for shell-form commands. On Linux, it usually defaults to
["/bin/sh", "-c"]
, and on Windows, it's["cmd", "/S", "/C"]
.This comes in handy on Windows, where cmd, powershell, and sh are pretty common.
You can use the SHELL instruction more than once, and each time you do, it replaces the previous one and changes all the commands that come after it.
SHELL ["executable", "parameters"]
βChalo powershell use karte hainβ¦β
SHELL ["powershell", "-command"] RUN echo Hello
HEALTHCHECK
Checks if your app inside container is still running properly.
HEALTHCHECK CMD curl --fail http://localhost:3000 || exit 1
βApp down hai ya nahi? Yeh check karega.β
VOLUME
To persist data outside the container.
Container delete hone ke baad bhi data safe rahega.
VOLUME <dir>
ENV
Sets environment variables.
Multiple <key>=<value>β¦ variables can be set at the same time using the ENV instruction.
# Syntax ENV <key>=<value> # Example ENV APP_NAME="MyApp"
EXPOSE
Opens a port.
The EXPOSE instruction doesn't really open the port. It's more like a hint for the image creator and container user about which ports should be opened.
To open and map ports, use the
-p
flag withdocker run
for specific ports, or use the-P
flag to open all exposed ports and map them to higher ports.EXPOSE assumes TCP by default. You can also use UDP.
Its like saying βOye Docker, listen on this port.β π
# Syntax EXPOSE <port> EXPOSE <port> [<port>/<protocol>...] # Example EXPOSE 8080 EXPOSE 80/udp
π Best Practices & Common Mistakes π
Best Practices
Use Multi-Stage Builds: Keep your final image slim.
.dockerignore is your BFF: Skip unnecessary files. π«
# sample .dockerignore file *.pyc __pycache__/ *.log config/ README.md
Avoid using latest: Version everything properly. π’
Chain RUN commands: Reduce layers and improve caching.
Don't run as root: Use USER for safety.
Common Gotchas
COPY fails? Check your paths and .dockerignore.
CMD not working? Switch to ENTRYPOINT. π
Caching issues? Reorder instructions β COPY before RUN if files change often.
π Folder Structure π
my-project/
βββ Dockerfile
βββ .dockerignore
βββ app/
β βββ main.py
β βββ requirements.txt
β βββ utils.py
βββ config/
β βββ config.yaml
βββ README.md
π Examples π
Python
# Use the official Python image FROM python:3.9 # Set the working directory WORKDIR /app # Copy requirements file and install dependencies COPY requirements.txt . RUN pip install -r requirements.txt # Copy the rest of the application code COPY . . # Set the default command to run the application CMD ["python", "app.py"]
React
# Use the official Node.js image FROM node:14 # Set the working directory WORKDIR /app # Copy package.json and package-lock.json and install dependencies COPY package.json package-lock.json ./ RUN npm install # Copy the rest of the application code COPY . . # Build the application RUN npm run build # Expose the port the app runs on EXPOSE 3000 # Set the default command to run the application CMD ["npm", "start"]
π Conclusion β
You're CRUSHING IT with Docker now! π₯ Upcoming Part 3 - Docker Compose blog SOON! ππ³ Stay tuned - it's gonna be EPIC! #DockerGang β¨ Till thenβ¦
Happy Learning !!! π
Subscribe to my newsletter
Read articles from Sudhanshu Sanjay Motewar directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
