Skip to content
Back to skills

Container Security

BSecurity

Dockerfile best practices, secure base images, no secrets in build context, multi-stage builds, non-root execution, and image scanning guidance.

  • 7 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added May 27, 2026
developmentpythongonodedockergitdatabasesecurity

Security analysis

B88/100
  • criticalAccesses sensitive system or user directories

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

Scanned May 27, 2026

npx -y skills add Vimalk0703/shipworthy --skill container-security --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Container Security?

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

Security grade badge for Container Security
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/vimalk0703-container-security/badge)](https://www.skillsdirectory.com/skills/vimalk0703-container-security)

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

Download with Pro
SKILL.md
---
name: container-security
description: Dockerfile best practices, secure base images, no secrets in build context, multi-stage builds, non-root execution, and image scanning guidance.
invoke_when: Use when writing or reviewing Dockerfiles, docker-compose files, container build pipelines, or discussing container deployment and image security.
---

# Container Security

## Base Image Rules

1. **Use official or verified images only** -- `node:22-slim`, `python:3.12-slim`, `alpine:3.20`.
2. **Pin by digest, not just tag** -- tags are mutable.
3. **Prefer `-slim` or `-alpine` variants** -- smaller attack surface.
4. **Never use `latest`** -- builds must be reproducible.

```dockerfile
# BAD
FROM node:latest

# GOOD -- pinned tag + slim variant
FROM node:22.12-slim
```

## No Secrets in the Dockerfile

Secrets in the build context end up in image layers. Layers are permanent and extractable.

```dockerfile
# BAD -- secret baked into the image
ENV DATABASE_URL=postgres://user:password@host/db
COPY .env /app/.env

# GOOD -- inject at runtime via docker run -e or --env-file
# For build-time secrets, use BuildKit secret mounts:
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ci
```

## Multi-Stage Builds

Keep build tools out of the final image:

```dockerfile
FROM node:22.12-slim AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:22.12-slim
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
USER node
CMD ["node", "dist/server.js"]
```

## Non-Root User

Always run as a non-root user. Most official images ship one (e.g., `node`).

```dockerfile
RUN addgroup --system app && adduser --system --ingroup app app
USER app
```

## .dockerignore Is Required

Every project with a Dockerfile must have a `.dockerignore`:

```
.git
.env*
node_modules
*.md
.github
tests
coverage
```

## Image Scanning

Scan images in CI before pushing to a registry. **Tools:** Trivy (free, fast), Snyk Container, Docker Scout.

**Policy:** No CRITICAL vulnerabilities in production images. HIGH must be triaged within 7 days.

```yaml
- name: Scan image
  uses: aquasecurity/trivy-action@master
  with:
    image-ref: myapp:${{ github.sha }}
    severity: CRITICAL,HIGH
    exit-code: 1
```

## Dockerfile Review Checklist

- [ ] Base image is official/verified, pinned to a specific version
- [ ] No `ENV` or `COPY` of secrets -- runtime injection only
- [ ] Multi-stage build separates build tools from production image
- [ ] Final stage runs as non-root user
- [ ] `.dockerignore` exists and excludes `.env*`, `.git`, `node_modules`
- [ ] Image is scanned in CI with a fail-on-critical policy

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…