Dockerfile

Dockerfile Explained (With Best Practices & Scenarios)

A Dockerfile is a script containing instructions to automate the building of a Docker image. Each instruction creates a new image layer, and optimizing these layers improves performance and efficiency.

Big Images to lead high startup time for container


1. Basic Structure of a Dockerfile

# Base image
FROM ubuntu:20.04  

# Maintainer information (optional)
LABEL maintainer="[email protected]"

# Set working directory
WORKDIR /app  

# Copy application files
COPY . /app  

# Install dependencies
RUN apt-get update && apt-get install -y curl  

# Default command
CMD ["echo", "Hello, Docker!"]

2. Key Dockerfile Instructions

2.1 FROM (Base Image)

  • Defines the base OS/image for your container.

  • Example:

  • Best Practice: Use minimal base images like alpine for smaller images.


2.2 WORKDIR (Working Directory)

  • Sets the working directory for subsequent commands.

  • Example:

  • Best Practice: Avoid using RUN cd /path && command, use WORKDIR.


2.3 COPY vs ADD

Feature
COPY
ADD

Function

Copies files/directories

Copies + Extracts archives (tar, gzip)

Security

More secure

May introduce security risks

Use Case

When copying files

When adding & extracting archives, allows downloading files from URLs. ADD http://untrusted-source.com/script.sh /usr/local/bin/

  • Example:

  • Best Practice: Prefer COPY unless you need automatic extraction.

  • If a remote URL is used instead of a verified source, an attacker could inject a malicious file.


2.4 RUN (Execute Commands)

  • Executes commands inside the container during image build.

  • Example:

  • Best Practice:

    • Use a single RUN command to minimize layers.

    • Clean up unnecessary files to reduce image size:


2.5 CMD vs ENTRYPOINT

Feature
CMD
ENTRYPOINT

Purpose

Default command

Fixed command

Overridable?

Yes (docker run <override>)

No (unless --entrypoint is used)

Use Case

Scripts or defaults

Applications that must always execute a specific binary

  • Example of CMD (Can be overridden):

  • Example of ENTRYPOINT (Fixed command, cannot be overridden):

  • Best Practice:

    • Use ENTRYPOINT for essential commands (e.g., nginx, java).

    • Combine with CMD for default parameters:


2.6 EXPOSE (Ports)

  • Declares the port the container listens on.

  • Example:

  • Best Practice:

    • EXPOSE is just documentation; you still need to use -p in docker run.


2.7 VOLUME (Persistent Storage)

  • Creates a mount point for persistent data.

  • Example:

  • Best Practice: Use named volumes instead of anonymous ones.


2.8 ENV (Environment Variables)

  • Sets environment variables inside the container.

  • Example:

  • Best Practice:

    • Use environment variables instead of hardcoding values.

    • Store secrets in external tools (like AWS Secrets Manager) instead of ENV.


2.9 HEALTHCHECK (Container Health Monitoring)

  • Monitors container health and restarts if needed.

  • Example:

  • Best Practice: Use HEALTHCHECK to detect application failures.


3. Reducing Docker Image Size

  • Use lightweight base images (alpine, distroless).

  • Remove unnecessary files:

  • Use multi-stage builds (explained below).

  • Avoid adding node_modules, .git, or unnecessary logs.


4. Multi-Stage Dockerfile (Best for Production)

  • Reduces image size by building dependencies separately.

  • Example (Node.js app):

  • Benefits:

    • Keeps final image clean and small.

    • No extra dependencies (e.g., build tools like gcc are removed).


5. Best Practices for Writing Dockerfiles

Use Minimal Base Images (Alpine, Distroless) ✅ Leverage Multi-Stage BuildsReduce Layers by Combining RUN CommandsUse COPY Instead of ADD for SecurityAvoid Running Containers as Root (USER directive)Set a HEALTHCHECK for Service MonitoringUse .dockerignore to Exclude Unnecessary Files


6. Scenario-Based Questions on Dockerfile

Q1: How would you reduce the size of a Docker image?

Answer:

  • Use alpine or distroless base images.

  • Combine RUN commands to reduce layers.

  • Remove unnecessary dependencies (rm -rf /var/lib/apt/lists/*).

  • Use multi-stage builds to remove build-time dependencies.


Q2: When would you use ENTRYPOINT over CMD?

Answer: Use ENTRYPOINT when you want a fixed command (e.g., nginx, python, java). Use CMD when you need default arguments that can be overridden.


Q3: What happens if you specify both CMD and ENTRYPOINT?

Answer:

  • ENTRYPOINT runs first.

  • CMD arguments are passed to ENTRYPOINT.

  • Example:

    • Runs as python app.py.


Q4: How do you prevent unnecessary files from being copied into the image?

Answer:

  • Use .dockerignore:


7. Summary

Topic
Key Takeaways

Base Images

Use lightweight images (alpine, distroless)

COPY vs ADD

Prefer COPY for security

CMD vs ENTRYPOINT

ENTRYPOINT is fixed, CMD is overrideable

Reducing Size

Use multi-stage builds, minimize layers, clean up

Multi-Stage

Separate build dependencies to keep images small

Best Practices

Use .dockerignore, USER, HEALTHCHECK, and keep it clean

This covers Dockerfiles, best practices, and interview scenarios! 🚀 Let me know if you need more details. 😊

Last updated