DEV Community

EME GUG
EME GUG

Posted on

Cách viết Dockerfile an toàn hơn

Nhiều Dockerfile mình review có lỗi bảo mật cơ bản. Đây là checklist mình dùng.

1. Không chạy root

# Bad
FROM node:20-alpine
COPY . .
CMD ["node", "app.js"]
# Container chạy bằng root!

# Good
FROM node:20-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY --chown=appuser:appgroup . .
USER appuser
CMD ["node", "app.js"]
Enter fullscreen mode Exit fullscreen mode

Nếu app bị hack, attacker chỉ có quyền appuser, không phải root.

2. Pin exact versions

# Bad: image có thể thay đổi bất cứ lúc nào
FROM python:3
FROM node:latest

# Good: pin version
FROM python:3.12.4-slim-bookworm
FROM node:20.15.1-alpine3.20
Enter fullscreen mode Exit fullscreen mode

latest hôm nay có thể khác latest ngày mai → build không reproducible.

3. Dùng slim/alpine base

# Big: ~900MB, nhiều packages không cần
FROM ubuntu:22.04

# Smaller: ~150MB
FROM python:3.12-slim

# Smallest: ~50MB
FROM python:3.12-alpine
Enter fullscreen mode Exit fullscreen mode

Ít packages = ít attack surface = ít CVEs.

4. Multi-stage build

# Build stage: có compiler, build tools
FROM golang:1.22 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o server

# Runtime stage: chỉ có binary
FROM alpine:3.20
RUN apk --no-cache add ca-certificates
COPY --from=builder /app/server /server
USER nobody
CMD ["/server"]
Enter fullscreen mode Exit fullscreen mode

Build tools không vào production image.

5. Không copy secrets

# Bad: secrets baked vào image layer
COPY .env .
ENV API_KEY=secret123

# Good: pass at runtime
# docker run --env-file .env myapp
Enter fullscreen mode Exit fullscreen mode

Ai pull image đều thấy secrets trong layers:

docker history myapp --no-trunc
Enter fullscreen mode Exit fullscreen mode

6. COPY cụ thể, không COPY .

# Bad: copy everything kể cả .git, .env, node_modules
COPY . .

# Good: copy chỉ những gì cần
COPY package*.json ./
RUN npm ci --production
COPY src/ ./src/
COPY public/ ./public/
Enter fullscreen mode Exit fullscreen mode

Kết hợp với .dockerignore:

.git
.env*
node_modules
tests
*.md
docker-compose*.yml
Enter fullscreen mode Exit fullscreen mode

7. Health check

HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
    CMD curl -f http://localhost:3000/health || exit 1
Enter fullscreen mode Exit fullscreen mode

Orchestrator (Docker Swarm, K8s) dùng healthcheck để restart container khi app hang.

8. Scan for vulnerabilities

# Docker Scout
docker scout cves myapp:latest

# Trivy
trivy image myapp:latest

# Snyk
snyk container test myapp:latest
Enter fullscreen mode Exit fullscreen mode

Chạy scan trong CI/CD, block deploy nếu có critical CVE.

Checklist

  • [ ] Không chạy root
  • [ ] Pin exact image version
  • [ ] Dùng slim/alpine base
  • [ ] Multi-stage build
  • [ ] .dockerignore đầy đủ
  • [ ] Không có secrets trong image
  • [ ] HEALTHCHECK
  • [ ] Scan CVE trong CI/CD

Dockerfile của bạn check được mấy điểm? Có tip bảo mật nào khác không?

Top comments (0)