Create general-purpose Dockerfiles for Node.js, Python, Go, Rust, and Java projects. Covers base image selection, dependency installation, user permissions, COPY patterns, ENTRYPOINT vs CMD, and .dockerignore. Use when containerizing an application for the first time, creating a consistent build/runtime environment, preparing an app for cloud deployment or Docker Compose, or when no existing Dockerfile is present in the project.
Scanned 9/3/2026
Install to Claude Code
npx -y skills add pjt222/agent-almanac --skill create-dockerfile --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Create Dockerfile?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/pjt222-create-dockerfile-45bc48a2)More formats (shields.io, HTML) on the badges page.
---
name: create-dockerfile
locale: caveman
source_locale: en
source_commit: 82c77053
fence_basis_commit: 82c77053
translator: "Julius Brussee homage — caveman"
translation_date: "2026-04-19"
description: >
Create general-purpose Dockerfiles for Node.js, Python, Go, Rust, and Java
projects. Covers base image selection, dependency installation, user
permissions, COPY patterns, ENTRYPOINT vs CMD, and .dockerignore. Use when
containerizing an application for the first time, creating a consistent
build/runtime environment, preparing an app for cloud deployment or Docker
Compose, or when no existing Dockerfile is present in the project.
license: MIT
allowed-tools: Read Write Edit Bash Grep Glob
metadata:
author: Philipp Thoss
version: "1.0"
domain: containerization
complexity: basic
language: Docker
tags: docker, dockerfile, node, python, go, rust, java, container
---
# Create Dockerfile
Write production-ready Dockerfile for general-purpose application projects.
## When Use
- Containerizing Node.js, Python, Go, Rust, or Java app
- Making consistent build/runtime environment
- Preparing app for cloud deploy or Docker Compose
- No existing Dockerfile in project
## Inputs
- **Required**: Project language and entry point (e.g., `npm start`, `python app.py`)
- **Required**: Dependency manifest (package.json, requirements.txt, go.mod, Cargo.toml, pom.xml)
- **Optional**: Target environment (development or production)
- **Optional**: Exposed ports
## Steps
### Step 1: Choose Base Image
| Language | Dev Image | Prod Image | Size |
|---|---|---|---|
| Node.js | `node:22-bookworm` | `node:22-bookworm-slim` | ~200MB |
| Python | `python:3.12-bookworm` | `python:3.12-slim-bookworm` | ~150MB |
| Go | `golang:1.23-bookworm` | `gcr.io/distroless/static` | ~2MB |
| Rust | `rust:1.82-bookworm` | `debian:bookworm-slim` | ~80MB |
| Java | `eclipse-temurin:21-jdk` | `eclipse-temurin:21-jre` | ~200MB |
**Got:** Pick slim/distroless variant for production images.
### Step 2: Write Dockerfile (by language)
#### Node.js
```dockerfile
FROM node:22-bookworm-slim
RUN groupadd -r appuser && useradd -r -g appuser -m appuser
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY . .
USER appuser
EXPOSE 3000
CMD ["node", "src/index.js"]
```
#### Python
```dockerfile
FROM python:3.12-slim-bookworm
RUN groupadd -r appuser && useradd -r -g appuser -m appuser
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
USER appuser
EXPOSE 8000
CMD ["python", "app.py"]
```
#### Go
```dockerfile
FROM golang:1.23-bookworm AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app/server ./cmd/server
FROM gcr.io/distroless/static
COPY --from=builder /app/server /server
EXPOSE 8080
ENTRYPOINT ["/server"]
```
#### Rust
```dockerfile
FROM rust:1.82-bookworm AS builder
WORKDIR /src
COPY Cargo.toml Cargo.lock ./
RUN mkdir src && echo "fn main() {}" > src/main.rs && cargo build --release && rm -rf src
COPY . .
RUN touch src/main.rs && cargo build --release
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
COPY --from=builder /src/target/release/myapp /usr/local/bin/myapp
EXPOSE 8080
ENTRYPOINT ["myapp"]
```
#### Java (Maven)
```dockerfile
FROM eclipse-temurin:21-jdk AS builder
WORKDIR /src
COPY pom.xml .
RUN mvn dependency:go-offline -B
COPY src ./src
RUN mvn package -DskipTests
FROM eclipse-temurin:21-jre
COPY --from=builder /src/target/*.jar /app/app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
```
**Got:** `docker build -t myapp .` finishes without errors.
**If fail:** Check base image availability and dependency install commands.
### Step 3: ENTRYPOINT vs CMD
| Directive | Purpose | Override |
|---|---|---|
| `ENTRYPOINT` | Fixed executable | Override with `--entrypoint` |
| `CMD` | Default arguments | Override with trailing args |
| Both | `ENTRYPOINT` + default args via `CMD` | Args override CMD only |
Use `ENTRYPOINT` for compiled binaries with single purpose. Use `CMD` for interpreted languages where might want `docker run myapp bash`.
### Step 4: Create .dockerignore
```text
.git
.gitignore
node_modules
__pycache__
*.pyc
target/
.env
.env.*
*.md
!README.md
.vscode
.idea
Dockerfile
docker-compose*.yml
```
**Got:** Build context drops dev artifacts.
### Step 5: Add Non-Root User
Always run as non-root in production:
```dockerfile
RUN groupadd -r appuser && useradd -r -g appuser -m appuser
USER appuser
```
For distroless images, use built-in nonroot user:
```dockerfile
FROM gcr.io/distroless/static:nonroot
USER nonroot
```
### Step 6: Build and Verify
```bash
docker build -t myapp:latest .
docker run --rm myapp:latest
docker image inspect myapp:latest --format '{{.Size}}'
```
**Got:** Container starts, responds on expected port, runs as non-root.
**If fail:** Check logs with `docker logs`. Verify WORKDIR, COPY paths, exposed ports.
## Checks
- [ ] `docker build` finishes without errors
- [ ] Container starts and app responds
- [ ] `.dockerignore` drops unneeded files
- [ ] App runs as non-root user
- [ ] Dependencies copied before source code (cache efficiency)
- [ ] No secrets or `.env` files baked into image
## Pitfalls
- **COPY before dependency install**: Invalidates dependency cache on every code change. Always copy manifest file first.
- **Running as root**: Default Docker user is root. Always add non-root user for production.
- **Missing .dockerignore**: Sending `node_modules` or `.git` into build context wastes time and disk.
- **Using `latest` tag for base images**: Pin to specific versions (e.g., `node:22.11.0`) for reproducibility.
- **Forgetting `--no-cache-dir`**: Python `pip` caches packages by default, bloating image.
- **ADD vs COPY**: Use `COPY` unless need URL download or tar extraction (`ADD` auto-extracts).
## See Also
- `create-r-dockerfile` - R-specific Dockerfile using rocker images
- `create-multistage-dockerfile` - multi-stage patterns for minimal production images
- `optimize-docker-build-cache` - advanced caching strategies
- `setup-compose-stack` - orchestrate containerized app with other services
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!