Back to tools
What is a Dockerfile?
A Dockerfile is a text file containing instructions to build a Docker image. Using multi-stage builds allows creating optimized and lightweight images.
- Multi-stage builds: Separates build from production for smaller images
- FROM: Defines the base image
- COPY/ADD: Copies files to the container
- RUN: Executes commands during build
- EXPOSE: Defines exposed ports
- CMD/ENTRYPOINT: Defines the default command
Frequently Asked Questions
What is a multi-stage build in Dockerfile and why should you use it?
A multi-stage build uses multiple FROM statements in a single Dockerfile, each with a different base image. Only necessary artifacts are copied between stages with `COPY --from=`. The final image becomes significantly smaller because build tools, temporary libraries, and intermediate files are excluded. For example, compile a Go app in a golang:alpine image and deploy the binary in a scratch image, reducing the final image from 800 MB to under 20 MB while keeping the same functionality.
How to create an optimized Dockerfile for Node.js applications?
For an optimized Node.js Dockerfile use two stages. Builder stage: `node:20-alpine`, copy `package*.json`, run `npm ci --only=production`, copy source code and run `npm run build`. Production stage: fresh `node:20-alpine`, copy only `node_modules` and `dist` from builder. Add `USER node` for security, expose the port, and set `CMD ["node", "dist/index.js"]`. This removes devDependencies, source maps and source files from the final image, substantially reducing its size.
How to write a Dockerfile for Python Flask or Django applications?
Start with `python:3.11-slim` base image. Copy `requirements.txt` and run `pip install --no-cache-dir -r requirements.txt`. The `--no-cache-dir` flag prevents pip cache from bloating the image. Then copy your application code. For Flask expose port 5000 with `CMD ["gunicorn", "-b", "0.0.0.0:5000", "app:app"]`. For Django expose port 8000. Order layers from least to most frequently changing to maximize Docker layer caching: install dependencies first, add application code last.
What are Dockerfile security best practices for production?
Dockerfile security best practices include: use official lightweight base images like `alpine` or `slim`, avoid running as root by adding `USER nonroot`, install only necessary packages with flags like `--no-cache-dir` or `apt-get clean`, copy only required files using `.dockerignore`, prefer `COPY` over `ADD` for local files, pin specific image versions instead of using `latest`, enable `HEALTHCHECK` instructions, and always use multi-stage builds in production to minimize the attack surface.