Skip to content
Back to skills

2935 Dockerfile Best Practices Fbac54ba

CSecurity

Use multi-stage builds to reduce final image size:

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
devopspythongojavabashnodenodejsspringdockergitsecurity

Works with

  • cli

Security analysis

C68/100
  • mediumUses curl or wget to download content
  • criticalAccesses sensitive system or user directories
  • highPerforms destructive filesystem operations
  • mediumInstalls packages at runtime which could introduce malicious dependencies
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 2935-dockerfile_best_practices_fbac54ba --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2935 Dockerfile Best Practices Fbac54ba?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2935 Dockerfile Best Practices Fbac54ba
[![Security: C — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2935-dockerfile-best-practices-fbac54ba/badge)](https://www.skillsdirectory.com/skills/tools-only-2935-dockerfile-best-practices-fbac54ba)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# Dockerfile Best Practices

## Multi-Stage Builds

Use multi-stage builds to reduce final image size:

```dockerfile
# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Production stage
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/index.js"]
```

**Benefits**:
- Smaller final image (build tools not included)
- Faster deployments
- Reduced attack surface

## Layer Caching Optimization

Order instructions from least to most frequently changing:

```dockerfile
# ✅ Good - Dependencies change less often than code
COPY package*.json ./
RUN npm ci
COPY . .

# ❌ Bad - Cache invalidated on every code change
COPY . .
RUN npm ci
```

## Security Best Practices

### 1. Use Non-Root Users

```dockerfile
# Create and use non-root user
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001 -G nodejs

USER nodejs
```

### 2. Use Specific Base Image Tags

```dockerfile
# ✅ Good - Specific version
FROM node:18.17.0-alpine

# ❌ Bad - Latest tag (unpredictable)
FROM node:latest
```

### 3. Scan for Vulnerabilities

```bash
docker scan myapp:latest
```

### 4. Use .dockerignore

```.dockerignore
node_modules
npm-debug.log
.git
.env
.DS_Store
*.md
```

## Image Size Optimization

### 1. Use Alpine Images

```dockerfile
FROM node:18-alpine  # ~170MB
# vs
FROM node:18         # ~900MB
```

### 2. Clean Up in Same Layer

```dockerfile
RUN apt-get update && \
    apt-get install -y package && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*
```

### 3. Use .dockerignore

Exclude unnecessary files from build context.

## Health Checks

Define health checks for container monitoring:

```dockerfile
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1
```

## Environment Variables

Use ARG for build-time variables, ENV for runtime:

```dockerfile
# Build-time variable
ARG NODE_VERSION=18

# Runtime variable
ENV NODE_ENV=production
```

## Common Patterns by Language

### Node.js

```dockerfile
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .

FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app .
USER node
EXPOSE 3000
CMD ["node", "index.js"]
```

### Python

```dockerfile
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user -r requirements.txt

FROM python:3.11-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
CMD ["python", "app.py"]
```

### Java (Spring Boot)

```dockerfile
FROM eclipse-temurin:17-jdk AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN ./mvnw package -DskipTests

FROM eclipse-temurin:17-jre
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
```

### Go

```dockerfile
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o main .

FROM alpine:latest
RUN apk --no-cache add ca-certificates
COPY --from=builder /app/main .
CMD ["./main"]
```

## Build Arguments

Use build arguments for flexibility:

```dockerfile
ARG APP_VERSION=latest
ARG BUILD_DATE
ARG VCS_REF

LABEL org.opencontainers.image.version="${APP_VERSION}" \
      org.opencontainers.image.created="${BUILD_DATE}" \
      org.opencontainers.image.revision="${VCS_REF}"
```

Build with arguments:

```bash
docker build \
  --build-arg APP_VERSION=1.0.0 \
  --build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
  --build-arg VCS_REF=$(git rev-parse --short HEAD) \
  -t myapp:1.0.0 .
```

## Metadata Labels

Add metadata using labels:

```dockerfile
LABEL maintainer="team@example.com" \
      version="1.0.0" \
      description="My application"
```

## Volume Management

Define volumes for persistent data:

```dockerfile
VOLUME ["/app/data", "/app/logs"]
```

## Networking

Expose ports:

```dockerfile
EXPOSE 8080 8443
```

## Entrypoint vs CMD

**ENTRYPOINT**: Defines the executable

```dockerfile
ENTRYPOINT ["python", "app.py"]
```

**CMD**: Provides default arguments

```dockerfile
CMD ["--host", "0.0.0.0"]
```

**Combined**:

```dockerfile
ENTRYPOINT ["python", "app.py"]
CMD ["--host", "0.0.0.0"]
```

Override CMD at runtime:

```bash
docker run myapp --host 127.0.0.1
```

## Development vs Production

### Development Dockerfile

```dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install  # Install all deps including dev
COPY . .
CMD ["npm", "run", "dev"]
```

### Production Dockerfile

```dockerfile
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production  # Only production deps
COPY . .
RUN npm run build

FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
USER node
CMD ["node", "dist/index.js"]
```

## Troubleshooting

### Build fails with permission error

```dockerfile
# Ensure correct ownership
RUN chown -R appuser:appuser /app
USER appuser
```

### Image too large

- Use multi-stage builds
- Use Alpine base images
- Clean up in same RUN layer
- Use .dockerignore

### Container exits immediately

- Check CMD/ENTRYPOINT
- Verify application starts correctly
- Check logs: `docker logs <container>`

### Cannot connect to container

- Verify EXPOSE matches application port
- Check port mapping: `-p 3000:3000`
- Verify application binds to `0.0.0.0`, not `localhost`

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.