Skip to content
Codeloom
Docker

Docker Init: Generate Dockerfiles Automatically

Learn how to use docker init to scaffold Dockerfiles, Compose files, and .dockerignore for your projects in seconds. Supports Node.js, Python, Go, Rust, and more.

·7 min read · By Codeloom
Beginner 10 min read

What you'll learn

  • What docker init does and why it exists
  • How to scaffold Dockerfiles for various languages
  • Customizing generated files for production use
  • Integrating docker init into your development workflow

Prerequisites

  • Docker Desktop 4.18+ or Docker Engine with CLI plugins
  • Basic understanding of Dockerfiles

If you have ever copied the same Dockerfile boilerplate from project to project, you know the pain. Getting the base image right, setting up multi-stage builds, configuring the correct working directory, and writing a proper .dockerignore all take time. The docker init command solves this by generating production-ready Docker configuration files tailored to your project.

What Is Docker Init?

docker init is a CLI command introduced in Docker Desktop 4.18 that detects your project’s language and framework, then scaffolds a Dockerfile, compose.yaml, and .dockerignore with best practices baked in. It supports Node.js, Python, Go, Rust, Java, and generic projects out of the box.

Think of it as npm init or cargo init, but for your container setup. Instead of hunting through documentation for the right base image or copy-pasting from Stack Overflow, you answer a few interactive prompts and get files you can actually ship.

Getting Started with Docker Init

First, verify that you have a compatible version of Docker installed:

docker --version
# Docker version 27.x or later recommended

docker init --help

Navigate to your project root and run the command:

cd /path/to/your/project
docker init

Docker inspects your project directory, detects the language, and presents an interactive wizard:

Welcome to the Docker Init CLI!

This utility will walk you through creating the following files with
sensible defaults for your project:
  - .dockerignore
  - Dockerfile
  - compose.yaml

Let's get started!

? What application platform does your project use?
  > Node
    Go
    Python
    Rust
    ASP.NET Core
    PHP with Apache
    Java
    Other

Select your platform and answer the follow-up questions. For a Node.js project, it asks about the Node version, package manager, entry point, and port.

Example: Scaffolding a Node.js Project

Suppose you have a simple Express application. Running docker init and selecting Node generates these files:

Generated Dockerfile:

# syntax=docker/dockerfile:1

ARG NODE_VERSION=20.11.0

FROM node:${NODE_VERSION}-alpine AS base
WORKDIR /usr/src/app

FROM base AS deps
RUN --mount=type=bind,source=package.json,target=package.json \
    --mount=type=bind,source=package-lock.json,target=package-lock.json \
    --mount=type=cache,target=/root/.npm \
    npm ci --omit=dev

FROM base AS build
RUN --mount=type=bind,source=package.json,target=package.json \
    --mount=type=bind,source=package-lock.json,target=package-lock.json \
    --mount=type=cache,target=/root/.npm \
    npm ci
COPY . .
RUN npm run build

FROM base AS final
ENV NODE_ENV=production
USER node
COPY package.json .
COPY --from=deps /usr/src/app/node_modules ./node_modules
COPY --from=build /usr/src/app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/index.js"]

Notice the multi-stage build, cache mounts for npm, non-root user, and production-only dependencies. These are all best practices that many developers skip when writing Dockerfiles from scratch.

Generated compose.yaml:

services:
  server:
    build:
      context: .
    ports:
      - "3000:3000"
    environment:
      NODE_ENV: production

Generated .dockerignore:

node_modules
npm-debug.log
Dockerfile*
docker-compose*
compose*
.dockerignore
.git
.gitignore
README.md
LICENSE

Example: Scaffolding a Python Project

For a Python Flask or FastAPI application:

docker init
# Select: Python
# Python version: 3.12
# Port: 8000
# Entry command: gunicorn app:app --bind 0.0.0.0:8000

Generated Dockerfile:

# syntax=docker/dockerfile:1

ARG PYTHON_VERSION=3.12
FROM python:${PYTHON_VERSION}-slim AS base

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

WORKDIR /app

ARG UID=10001
RUN adduser \
    --disabled-password \
    --gecos "" \
    --home "/nonexistent" \
    --shell "/sbin/nologin" \
    --no-create-home \
    --uid "${UID}" \
    appuser

RUN --mount=type=cache,target=/root/.cache/pip \
    --mount=type=bind,source=requirements.txt,target=requirements.txt \
    pip install --no-cache-dir -r requirements.txt

USER appuser
COPY . .
EXPOSE 8000
CMD ["gunicorn", "app:app", "--bind", "0.0.0.0:8000"]

The Python template includes a dedicated non-root user with no home directory, pip cache mounts, and environment variables to prevent .pyc files and enable unbuffered output.

Example: Scaffolding a Go Project

Go projects get a particularly clean output because Go compiles to a static binary:

# syntax=docker/dockerfile:1

ARG GO_VERSION=1.22
FROM golang:${GO_VERSION} AS build

WORKDIR /src
RUN --mount=type=cache,target=/go/pkg/mod/ \
    --mount=type=bind,source=go.sum,target=go.sum \
    --mount=type=bind,source=go.mod,target=go.mod \
    go mod download -x

RUN --mount=type=cache,target=/go/pkg/mod/ \
    --mount=type=bind,target=. \
    CGO_ENABLED=0 go build -o /bin/server .

FROM gcr.io/distroless/static-debian12 AS final
COPY --from=build /bin/server /bin/
EXPOSE 8080
ENTRYPOINT ["/bin/server"]

The final stage uses a distroless image, which has no shell, no package manager, and a minimal attack surface. The resulting image is typically under 20 MB.

Customizing the Generated Files

The generated files are a starting point, not a locked configuration. Here are common customizations you should consider.

Adding Health Checks

The generated Dockerfile does not include a HEALTHCHECK instruction. Add one for production readiness:

HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
  CMD ["wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/health"]

Adding Development Services to Compose

Extend the generated compose.yaml with databases and caches:

services:
  server:
    build:
      context: .
    ports:
      - "3000:3000"
    environment:
      NODE_ENV: production
      DATABASE_URL: postgres://user:pass@db:5432/myapp
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: myapp
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 5s
      timeout: 5s
      retries: 5

volumes:
  pgdata:

Tuning the .dockerignore

Add project-specific exclusions:

# Test files
__tests__
*.test.js
coverage/

# IDE files
.vscode/
.idea/

# Environment files
.env*
!.env.example

Non-Interactive Mode

For CI/CD pipelines or scripted setups, you can skip the interactive prompts by pre-answering questions. While docker init does not have full non-interactive flags for every option yet, you can pipe answers or use it in combination with template overrides.

A practical approach for automation is to run docker init once, commit the generated files, and then customize them in version control:

# Generate once
docker init

# Commit the scaffolded files
git add Dockerfile compose.yaml .dockerignore
git commit -m "chore: scaffold Docker configuration with docker init"

# Customize and iterate

When to Use Docker Init vs Writing From Scratch

Use docker init when:

  • You are starting a new project and want best-practice defaults fast.
  • You are containerizing an existing application for the first time.
  • You want to audit your current Dockerfile against recommended patterns.
  • You are onboarding team members who are not familiar with Docker.

Write from scratch when:

  • Your project has unusual build requirements that no template covers.
  • You need fine-grained control over every layer from the start.
  • You are working with a language or framework not yet supported by docker init.

Common Issues and Fixes

“docker init” command not found: Make sure you are running Docker Desktop 4.18+ or have the docker-init CLI plugin installed. On Linux without Docker Desktop, you may need to install the plugin separately.

Wrong language detected: If your project has multiple languages (for example, a Go backend with a React frontend), docker init may pick the wrong one. Select the correct platform manually from the menu or run it in a subdirectory.

Generated file conflicts: If a Dockerfile or compose.yaml already exists, docker init warns you before overwriting. Back up your current files first if you want to compare.

Wrapping Up

docker init removes the friction of writing Docker configuration files from scratch. It generates multi-stage Dockerfiles with cache mounts, non-root users, and production-ready defaults for all major languages. The generated files are a solid starting point that you should customize for your specific needs, adding health checks, development services, and environment-specific configuration as your project grows. Next time you start a new project or containerize an existing one, run docker init before reaching for your old boilerplate.