docker — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited docker (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Container optimization, security hardening, multi-stage builds, and production deployment patterns.
npx clawhub@latest install dockernpm ci && npm cache clean --force)docker compose (v2) with plugin syntax# Stage 1: Dependencies
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
# Stage 2: Build
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build && npm prune --production
# Stage 3: Production
FROM node:20-alpine AS runtime
RUN addgroup -g 1001 -S nodejs && adduser -S app -u 1001
WORKDIR /app
COPY --from=deps --chown=app:nodejs /app/node_modules ./node_modules
COPY --from=build --chown=app:nodejs /app/dist ./dist
COPY --from=build --chown=app:nodejs /app/package*.json ./
USER app
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
CMD ["node", "dist/index.js"]FROM node:20-alpine
# Create non-root user with specific UID/GID
RUN addgroup -g 1001 -S appgroup && \
adduser -S appuser -u 1001 -G appgroup
WORKDIR /app
# Copy with ownership
COPY --chown=appuser:appgroup package*.json ./
RUN npm ci --only=production && npm cache clean --force
COPY --chown=appuser:appgroup . .
# Switch to non-root user
USER 1001
# At runtime: --cap-drop=ALL --read-only --security-opt=no-new-privilegesservices:
app:
build:
context: .
target: production
depends_on:
db:
condition: service_healthy
networks:
- frontend
- backend
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
restart: unless-stopped
db:
image: postgres:16-alpine
environment:
POSTGRES_DB_FILE: /run/secrets/db_name
POSTGRES_USER_FILE: /run/secrets/db_user
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_name
- db_user
- db_password
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- backend
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # No external access
volumes:
postgres_data:
secrets:
db_name:
file: ./secrets/db_name.txt
db_user:
file: ./secrets/db_user.txt
db_password:
file: ./secrets/db_password.txt# Dependencies
node_modules
.pnpm-store
# Build outputs
dist
build
.next
out
# Development
.git
.gitignore
*.md
LICENSE
docs/
# IDE
.vscode
.idea
*.swp
*.swo
# Testing
coverage
.nyc_output
*.test.js
*.spec.js
__tests__
# Environment
.env*
!.env.example
# Docker
Dockerfile*
docker-compose*
.docker
# Misc
.DS_Store
*.log
tmp# Mount build cache for faster rebuilds
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN --mount=type=cache,target=/root/.npm \
npm ci --only=production# BuildKit secrets (never stored in image layers)
FROM alpine
RUN --mount=type=secret,id=api_key \
API_KEY=$(cat /run/secrets/api_key) && \
# Use API_KEY for build process
echo "Key loaded"# Build with secret
docker build --secret id=api_key,src=./api_key.txt .# Create builder for multi-arch
docker buildx create --name multiarch --use
# Build for multiple platforms
docker buildx build --platform linux/amd64,linux/arm64 \
-t myapp:latest --push .# docker-compose.override.yml (auto-loaded in dev)
services:
app:
build:
target: development
volumes:
- .:/app
- /app/node_modules # Anonymous volume for node_modules
environment:
- NODE_ENV=development
- DEBUG=app:*
ports:
- "9229:9229" # Debug port
command: npm run devFROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup -g 1001 -S nodejs && adduser -S nextjs -u 1001
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
CMD ["node", "server.js"]FROM python:3.12-slim AS base
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1
FROM base AS deps
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
FROM base AS runtime
WORKDIR /app
RUN useradd -m -u 1001 appuser
COPY --from=deps /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY --chown=appuser:appuser . .
USER appuser
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /app/server
FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/server /server
USER nonroot:nonroot
EXPOSE 8080
ENTRYPOINT ["/server"]# Analyze layers
docker history myapp:latest --no-trunc
# Use dive for detailed analysis
dive myapp:latest
# Check actual size
docker images myapp --format "{{.Size}}"Common causes:
npm ci --only=production# Enable BuildKit (faster, better caching)
export DOCKER_BUILDKIT=1
# Build with cache export
docker build --cache-from myapp:latest -t myapp:new .
# Check build cache
docker buildx du# Shell into running container
docker exec -it <container> sh
# Shell into failed container
docker run -it --entrypoint sh myapp:latest
# Check container logs
docker logs -f <container>
# Inspect container details
docker inspect <container>:latest)condition: service_healthy~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.