Dockerfile
Canonical implementation for Dockerfile
Dockerfile Entrypoint
Entrypoint script, generally named docker-entrypoint.sh, is a common practice to encapsulate initialization logic before starting the main application. This script can handle tasks like:
- Setting up environment variables
- Parsing configuration files
- Processing command-line arguments
#!/usr/bin/env bash
set -eux
# Initialization logic
exec "$@"
Multi-Process Docker Containers with tini Init System
When building Docker containers with multi-processes running inside, it’s important to ensure that the application runs smoothly as PID 1. Problems can arise if container runs complex applications that spawn child processes. For example, running application servers like gunicorn, pm2, supervisord or any long-running services.
Init systems’ responsibilities include:
- Forwarding signals (e.g., SIGTERM, SIGINT) to child processes
- Reaping zombie processes to prevent resource leaks
Container runtime may or may not handle init systems properly:
- Docker CLI:
docker run --initadds a minimal init system (tini) at runtime. - Docker Compose:
init: trueoption adds tini. - Kubernetes: automatically adds an init process for containers.
Manually adding tini to the Dockerfile ensures consistent behavior for any runtime. Add package tini to your image, and use it as the entrypoint:
# Debian or Ubuntu based images
RUN apt-get update && apt-get install -yq --no-install-recommends tini \
&& rm -rf /var/lib/apt/lists/*
COPY docker-entrypoint.sh /docker-entrypoint.sh
ENTRYPOINT ["tini", "--", "/docker-entrypoint.sh"]
As a result, when your container starts, tini will be PID 1, and it will properly forward signals and reap zombie processes for any child processes spawned by your application.
Using uv for Python Docker Images
For Python applications running in Docker, using uv can significantly improve development experience as it significantly reduces build time. Below is multi-stage Dockerfile with uv that manages Python dependencies efficiently:
FROM python:3.13-slim AS builder
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
WORKDIR /usr/src/app
COPY pyproject.toml uv.lock ./
ENV UV_PYTHON_PREFERENCE=only-system
RUN uv sync --frozen
FROM python:3.13-slim
WORKDIR /usr/src/app
COPY --from=builder /usr/src/app/.venv .venv
ENV PATH="/usr/src/app/.venv/bin:$PATH"
See the uv manual for more details.