Docker Code Review Rules
Security (Critical)
- •Run as non-root user (
USERdirective) - •Don't store secrets in image (use runtime injection)
- •Don't use
--privilegedwithout justification - •Scan images for vulnerabilities
- •Set
readonlyroot filesystem where possible - •Review any use of build-time variables (e.g.,
ARG,ENV,LABELvalues) that can be influenced by external inputs (such as--build-argvalues or CI/CD environment variables sourced from untrusted users) to ensure they are not used in a way that enables build-time injection - •Never use HTML comments (
<!-- -->) in Dockerfiles
Base Images
- •Pin base image to specific version (not
latest) - •Use official images from trusted sources
- •Prefer minimal images (
alpine,slim,distroless) - •Regularly update base images for security patches
Build Optimization
- •Use multi-stage builds to reduce final image size
- •Order instructions by change frequency (cache optimization)
- •Combine
RUNcommands to reduce layers - •Use
.dockerignoreto exclude unnecessary files, sensitive data, and build artifacts likenode_modules
Instructions (Essential)
- •Use
COPYinstead ofADD(unless extracting archives) - •Set
WORKDIRbeforeCOPY/RUN - •Use explicit
EXPOSEfor documentation - •Set meaningful
LABELmetadata
Additional Instructions
- •Explicitly set
SHELLif bash/sh features are needed - •Set environment variables with
ENVfor configuration (not secrets) - •Clean up package manager caches after install (e.g.,
apt-get clean) - •Understand
ENTRYPOINTvsCMD: useENTRYPOINTfor main command,CMDfor default args - •Document container usage with OCI labels (
org.opencontainers.image.*)
Health Checks
- •Include
HEALTHCHECKinstruction - •Health check should verify app is actually working
- •Set appropriate interval and timeout
Example Good Dockerfile Pattern
dockerfile
# Build stage FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci --only=production # Runtime stage FROM node:20-alpine # Add OCI labels for documentation LABEL org.opencontainers.image.title="My App" LABEL org.opencontainers.image.description="Production web application" LABEL org.opencontainers.image.version="1.0.0" RUN addgroup -S appgroup && adduser -S appuser -G appgroup WORKDIR /app # Copy dependencies and app files COPY --from=builder /app/node_modules ./node_modules COPY . . # Set environment variables (not secrets) ENV NODE_ENV=production USER appuser EXPOSE 3000 HEALTHCHECK CMD wget -q --spider http://localhost:3000/health || exit 1 # Use ENTRYPOINT for main command, CMD for default args ENTRYPOINT ["node"] CMD ["server.js"]