πŸ“ Writing a Dockerfile

πŸ“‹ Basic Structure

[INSTRUCTION] [ARGUMENTS]
 
# Base Image (Layer 1)
FROM ubuntu:20.04  
# Copy code to /app (Layer 2)
COPY . /app     
# Run a command (Layer 3)
RUN apt-get update

πŸ”¨ Building the Docker Image πŸ“¦

docker build -t [tagName] .
ParameterDescription
-t [tagName]Assigns a name to the image
. (dot)Specifies the current directory as the build context, which contains the Dockerfile

🎸 Basic Instructions

1. FROM

FROM python:3.9
  • Specifies the base image
  • Every Dockerfile starts with FROM. It defines the starting point of the image

2. RUN

RUN apt-get update && apt-get install -y curl
  • Executes commands during the image build process (like installing dependencies)

3. COPY

COPY . /app
  • Copies files from the host machine to the container

4. ADD

ADD myfile.tar.gz /app/
  • Similar to COPY, but supports remote URLs and compressed files

5. WORKDIR

WORKDIR /app
  • Sets the working directory inside the container

6. EXPOSE

EXPOSE 8080
  • Informs Docker about the port the container listens on
  • The EXPOSE command is only informational. It doesn’t actually make the port accessible from outside the container

7. ENV

ENV APP_ENV=production
  • Sets environment variables inside the container

8. ENTRYPOINT

ENTRYPOINT ["python", "app.py"]
  • Defines the main executable or command when the container runs

9. CMD

CMD ["--port=8080"]
  • Provides default arguments for ENTRYPOINT

πŸš€ Advanced Instructions

1. ARG

ARG VERSION=1.0
  • Defines build-time variables

2. VOLUME

VOLUME /data
  • Creates a mount point for persistent storage

3. USER

USER appuser
  • Switches to a non-root user inside the container

4. HEALTHCHECK

HEALTHCHECK --interval=30s CMD curl -f http://localhost/ || exit 1
  • Defines a health check command to monitor the container’s status

5. LABEL

LABEL version="1.0" author="Om"
  • Adds metadata information (like version or author)

βœ… Best Practice Example (Multi-stage Build)

# Base image (Alpine for lightweight build)
FROM node:16-alpine as builder
 
# Set working directory
WORKDIR /app
 
# Install dependencies separately for better caching
COPY package*.json ./
RUN npm install --production
 
# Copy the application code
COPY . .
 
# Run build step (if needed)
RUN npm run build
 
# Multi-stage build to keep final image lightweight
FROM node:16-alpine
 
# Set working directory
WORKDIR /app
 
# Copy only the built files and node_modules from the builder stage
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
 
# Set environment variables
ENV NODE_ENV=production \
    PORT=3000 \
    DB_HOST=localhost \
    DB_USER=admin
 
# Expose port
EXPOSE 3000
 
# Set non-root user for security
USER node
 
# Run the application
CMD ["node", "dist/server.js"]

πŸ“š Pro Tips

  • Always use minimal base images (like alpine) to keep the image lightweight
  • Combine multiple RUN commands to reduce layers and optimize caching
  • Setting non-root user (USER node) for better security
  • Use .dockerignore file to exclude unnecessary files from build context
  • Order Dockerfile instructions from least to most frequently changing for better caching