Skip to main content
โšก Calmops

Docker and Containerization with Go

Docker and Containerization with Go

Introduction

Docker enables consistent deployment across environments. This guide covers containerizing Go applications, optimizing images, and best practices for production containers.

Core Concepts

Docker Basics

  • Image: Blueprint for containers
  • Container: Running instance of an image
  • Dockerfile: Instructions to build an image
  • Registry: Repository for images

Why Docker?

  • Consistency across environments
  • Isolation and security
  • Easy scaling and deployment
  • Simplified dependency management

Good: Creating Dockerfiles

Basic Dockerfile

# โœ… GOOD: Simple Dockerfile
FROM golang:1.21

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download

COPY . .

RUN go build -o app .

EXPOSE 8080

CMD ["./app"]

Multi-Stage Build

# โœ… GOOD: Multi-stage build for smaller images
FROM golang:1.21 AS builder

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

# Final stage
FROM alpine:latest

RUN apk --no-cache add ca-certificates
WORKDIR /root/

COPY --from=builder /app/app .

EXPOSE 8080
CMD ["./app"]

Optimized Dockerfile

# โœ… GOOD: Optimized for production
FROM golang:1.21-alpine AS builder

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o app .

FROM alpine:latest

RUN apk --no-cache add ca-certificates tzdata
WORKDIR /root/

COPY --from=builder /app/app .

EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1

CMD ["./app"]

Good: Building and Running

Docker Commands

# โœ… GOOD: Build image
docker build -t myapp:1.0 .

# โœ… GOOD: Run container
docker run -p 8080:8080 myapp:1.0

# โœ… GOOD: Run with environment variables
docker run -p 8080:8080 -e DATABASE_URL=postgres://... myapp:1.0

# โœ… GOOD: Run in background
docker run -d -p 8080:8080 myapp:1.0

# โœ… GOOD: View logs
docker logs <container-id>

# โœ… GOOD: Stop container
docker stop <container-id>

# โœ… GOOD: Remove image
docker rmi myapp:1.0

Good: Docker Compose

Docker Compose Setup

# โœ… GOOD: Docker Compose configuration
version: '3.8'

services:
  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      - DATABASE_URL=postgres://user:password@db:5432/mydb
      - LOG_LEVEL=info
    depends_on:
      - db
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    restart: unless-stopped

  db:
    image: postgres:15
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=mydb
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  postgres_data:

Advanced Patterns

.dockerignore

# โœ… GOOD: .dockerignore file
.git
.gitignore
.env
.env.local
node_modules
dist
build
*.log
.DS_Store
.vscode
.idea

Build Arguments

# โœ… GOOD: Using build arguments
FROM golang:1.21 AS builder

ARG VERSION=dev
ARG BUILD_DATE

WORKDIR /app
COPY . .

RUN go build -ldflags="-X main.Version=${VERSION} -X main.BuildDate=${BUILD_DATE}" -o app .

FROM alpine:latest
COPY --from=builder /app/app .
CMD ["./app"]

Layer Caching

# โœ… GOOD: Optimize layer caching
FROM golang:1.21

WORKDIR /app

# Copy only go.mod and go.sum first
COPY go.mod go.sum ./
RUN go mod download

# Copy source code
COPY . .

# Build
RUN go build -o app .

EXPOSE 8080
CMD ["./app"]

Best Practices

1. Use Specific Base Image Versions

# โœ… GOOD: Specific version
FROM golang:1.21-alpine

# โŒ BAD: Latest tag
FROM golang:latest

2. Minimize Image Size

# โœ… GOOD: Multi-stage build
FROM golang:1.21 AS builder
RUN go build -o app .

FROM alpine:latest
COPY --from=builder /app/app .

# โŒ BAD: Large image
FROM golang:1.21
RUN go build -o app .

3. Use Health Checks

# โœ… GOOD: Health check
HEALTHCHECK --interval=30s CMD curl -f http://localhost:8080/health

# โŒ BAD: No health check

4. Don’t Run as Root

# โœ… GOOD: Non-root user
RUN addgroup -g 1000 appuser && adduser -D -u 1000 -G appuser appuser
USER appuser

# โŒ BAD: Run as root
USER root

Resources

Summary

Docker containerization ensures consistent deployment across environments. Use multi-stage builds to minimize image size, implement health checks for reliability, and follow security best practices. Proper containerization makes applications portable, scalable, and easier to manage.

Comments