Images & Dockerfiles
Complete guide to Docker image management, Dockerfile creation, and building best practices.
Image Management
Basic Image Operations
# Pull an image
docker pull nginx:latest
# Build an image
docker build -t myapp:latest .
# Build with custom Dockerfile
docker build -f Dockerfile.prod -t myapp:prod .
# Push to registry
docker push myapp:latest
# List images
docker images
# Remove image
docker rmi myapp:latest
# Remove unused images
docker image prune
# Remove all unused images
docker image prune -a
Image Information
# Inspect image
docker inspect myapp:latest
# Show image history
docker history myapp:latest
# Show image layers
docker inspect myapp:latest | grep -A 10 "RootFS"
# Tag an image
docker tag myapp:latest myapp:v1.0
# Save image to tar file
docker save myapp:latest > myapp.tar
# Load image from tar file
docker load < myapp.tar
Dockerfile Reference
Basic Structure
# Base image
FROM node:18-alpine
# Set working directory
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy source code
COPY . .
# Expose port
EXPOSE 3000
# Set environment variables
ENV NODE_ENV=production
# Create non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
# Change ownership
RUN chown -R nextjs:nodejs /app
USER nextjs
# Define entrypoint
ENTRYPOINT ["npm", "start"]
Dockerfile Instructions
FROM
# Use specific tags, not 'latest'
FROM node:18.17-alpine
# Use official images
FROM nginx:1.24-alpine
# Multi-stage build base
FROM node:18-alpine AS builder
WORKDIR
# Set working directory
WORKDIR /app
# Multiple working directories
WORKDIR /app/src
WORKDIR /data
COPY vs ADD
# COPY - preferred for simple file copying
COPY package*.json ./
COPY src/ ./src/
# ADD - has additional features (auto-extract, URLs)
ADD https://example.com/file.tar.gz /tmp/
ADD archive.tar.gz /extracted/ # Auto-extracts
RUN
# Minimize layers by combining commands
RUN apt-get update && apt-get install -y \
curl \
vim \
git \
&& rm -rf /var/lib/apt/lists/*
# Use cache mounts for package managers
RUN \
apt-get update && apt-get install -y curl
# Install Node.js dependencies with cache
RUN \
npm ci --only=production
USER
# Create and switch to non-root user
RUN addgroup -g 1001 -S appgroup
RUN adduser -S appuser -u 1001 -G appgroup
USER appuser
# Switch back to root if needed
USER root
RUN apt-get update
USER appuser
ENV & ARG
# Build-time variables
ARG NODE_VERSION=18
ARG BUILD_DATE
# Runtime environment variables
ENV NODE_ENV=production
ENV PORT=3000
ENV PATH="/app/bin:$PATH"
# Use ARG in FROM
ARG NODE_VERSION=18
FROM node:${NODE_VERSION}-alpine
# Use ARG as ENV
ARG API_URL
ENV API_URL=$API_URL
EXPOSE
# Document exposed ports
EXPOSE 3000
EXPOSE 8080/tcp
EXPOSE 53/udp
VOLUME
# Create mount points
VOLUME ["/data", "/logs"]
VOLUME /var/lib/mysql
HEALTHCHECK
# Health check configuration
HEALTHCHECK \
CMD curl -f http://localhost:3000/health || exit 1
# Disable health check
HEALTHCHECK NONE
Multi-Stage Builds
Basic Multi-Stage
# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# Test stage
FROM builder AS tester
RUN npm ci
COPY . .
RUN npm test
# Production stage
FROM node:18-alpine AS production
WORKDIR /app
COPY /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
USER node
CMD ["npm", "start"]
Advanced Multi-Stage
# Dependencies stage
FROM node:18-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Runtime stage
FROM node:18-alpine AS runtime
WORKDIR /app
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
COPY /app/node_modules ./node_modules
COPY /app/dist ./dist
USER nextjs
EXPOSE 3000
CMD ["node", "dist/index.js"]
Building Specific Stages
# Build only the builder stage
docker build --target builder -t myapp:builder .
# Build production stage
docker build --target production -t myapp:prod .
# Build with build args
docker build --build-arg NODE_ENV=production -t myapp .
# Build with cache from another image
docker build --cache-from myapp:latest -t myapp:new .
Dockerfile Best Practices
Optimization Techniques
# 1. Use specific base image tags
FROM node:18.17-alpine # ✓ Specific
FROM node:latest # ✗ Unstable
# 2. Minimize layers
RUN apt-get update && apt-get install -y curl vim \
&& rm -rf /var/lib/apt/lists/* # ✓ Single layer
RUN apt-get update # ✗ Multiple layers
RUN apt-get install -y curl
RUN apt-get install -y vim
# 3. Order instructions by change frequency
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./ # Changes less frequently
RUN npm ci
COPY . . # Changes more frequently
# 4. Use .dockerignore
# Create .dockerignore file:
# node_modules
# .git
# .env
# *.log
Security Best Practices
# Use minimal base images
FROM alpine:3.18
FROM distroless/nodejs18
# Don't run as root
FROM node:18-alpine
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
USER nextjs
# Don't store secrets in images
# ✗ Bad
ENV API_KEY=secret123
# ✓ Good - use runtime secrets
ENV API_KEY_FILE=/run/secrets/api_key
# Keep images up to date
FROM node:18.17-alpine # Use specific, recent versions
RUN apk update && apk upgrade
.dockerignore
# Dependencies
node_modules
npm-debug.log*
# Build outputs
dist
build
.next
# Development
.git
.gitignore
README.md
Dockerfile*
.dockerignore
# IDE
.vscode
.idea
# OS
.DS_Store
Thumbs.db
# Logs
*.log
# Environment
.env
.env.local
.env.*.local
Build Context & Performance
Optimizing Build Context
# Check build context size
docker build --no-cache --progress=plain .
# Build with specific context
docker build -f Dockerfile.prod ./app
# Build from stdin
docker build -t myapp - < Dockerfile
Build Arguments
# Pass build arguments
docker build --build-arg NODE_ENV=production \
--build-arg VERSION=1.0.0 \
-t myapp:1.0.0 .
# Use build arguments in Dockerfile
ARG NODE_ENV=development
ARG VERSION
ENV APP_VERSION=$VERSION
Build Cache
# Disable cache
docker build --no-cache -t myapp .
# Use cache from specific image
docker build --cache-from myapp:latest -t myapp:new .
# Use BuildKit for advanced caching
DOCKER_BUILDKIT=1 docker build -t myapp .
Quick Reference
Essential Commands
docker build -t name .- Build imagedocker images- List imagesdocker rmi image- Remove imagedocker tag source target- Tag imagedocker push image- Push to registrydocker pull image- Pull from registry
Best Practices
- Use specific base image tags
- Leverage multi-stage builds
- Minimize layers and image size
- Use .dockerignore effectively
- Don't run containers as root
- Keep base images updated
- Cache package installations