GoCasts آموزش Go به زبان ساده

بیش از ۱۰۰۰ شرکت‌کننده یادگیری Go و Backend رو از امروز شروع کن
ثبت‌نام دوره + تیم‌سازی

داکرایز کردن اپلیکیشن گولنگ - آموزش Docker با Go

Docker ابزار استاندارد صنعت برای containerization است. Go و Docker ترکیب عالی هستند - Go باینری‌های کوچک و مستقل تولید می‌کند که در container‌های سبک به خوبی کار می‌کنند.

پیش‌نیازها

# بررسی نصب Docker
docker --version
docker-compose --version

برنامه نمونه

یک API ساده برای تست:

main.go:

package main

import (
    "encoding/json"
    "log"
    "net/http"
    "os"
)

type Response struct {
    Message   string `json:"message"`
    Hostname  string `json:"hostname"`
    Version   string `json:"version"`
}

func main() {
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }

    version := os.Getenv("APP_VERSION")
    if version == "" {
        version = "1.0.0"
    }

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        hostname, _ := os.Hostname()

        resp := Response{
            Message:  "سلام از Docker!",
            Hostname: hostname,
            Version:  version,
        }

        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(resp)
    })

    http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("OK"))
    })

    log.Printf("Server starting on port %s", port)
    log.Fatal(http.ListenAndServe(":"+port, nil))
}

Dockerfile ساده

# استفاده از image رسمی Go
FROM golang:1.21

# تنظیم دایرکتوری کاری
WORKDIR /app

# کپی فایل‌های Go module
COPY go.mod go.sum ./

# دانلود وابستگی‌ها
RUN go mod download

# کپی کد منبع
COPY . .

# کامپایل برنامه
RUN go build -o main .

# پورت
EXPOSE 8080

# اجرای برنامه
CMD ["./main"]
# ساخت image
docker build -t my-go-app .

# اجرا
docker run -p 8080:8080 my-go-app

Multi-Stage Build (بهینه)

Dockerfile بهینه‌شده با multi-stage:

# ====== مرحله Build ======
FROM golang:1.21-alpine AS builder

# نصب ابزارهای لازم
RUN apk add --no-cache git ca-certificates tzdata

WORKDIR /app

# کپی و دانلود وابستگی‌ها (cache بهتر)
COPY go.mod go.sum ./
RUN go mod download

# کپی کد منبع
COPY . .

# کامپایل با بهینه‌سازی
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
    go build -ldflags="-w -s" -o /app/main .

# ====== مرحله Runtime ======
FROM scratch

# کپی CA certificates برای HTTPS
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

# کپی timezone data
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo

# کپی باینری
COPY --from=builder /app/main /main

# تنظیم timezone
ENV TZ=Asia/Tehran

# پورت
EXPOSE 8080

# اجرا
ENTRYPOINT ["/main"]

مقایسه اندازه Image

روش اندازه
golang:1.21 ~1.1 GB
golang:1.21-alpine ~300 MB
Multi-stage (scratch) ~10-15 MB

با Alpine (سبک‌تر از scratch)

# ====== مرحله Build ======
FROM golang:1.21-alpine AS builder

WORKDIR /app

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

COPY . .

RUN CGO_ENABLED=0 go build -ldflags="-w -s" -o main .

# ====== مرحله Runtime ======
FROM alpine:3.18

# نصب CA certificates
RUN apk --no-cache add ca-certificates tzdata

WORKDIR /app

# ایجاد کاربر غیر root
RUN adduser -D -g '' appuser

# کپی باینری
COPY --from=builder /app/main .

# تغییر مالکیت
RUN chown -R appuser:appuser /app

# استفاده از کاربر غیر root
USER appuser

EXPOSE 8080

CMD ["./main"]

Docker Compose

docker-compose.yml:

version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    environment:
      - PORT=8080
      - APP_VERSION=1.0.0
      - DB_HOST=db
      - DB_PORT=5432
      - DB_USER=postgres
      - DB_PASSWORD=secret
      - DB_NAME=myapp
    depends_on:
      - db
      - redis
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=myapp
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data

volumes:
  postgres_data:
  redis_data:
# اجرای همه سرویس‌ها
docker-compose up -d

# مشاهده لاگ‌ها
docker-compose logs -f app

# توقف
docker-compose down

.dockerignore

# Git
.git
.gitignore

# IDE
.idea
.vscode
*.swp

# Build artifacts
*.exe
*.exe~
*.dll
*.so
*.dylib
bin/
dist/

# Test
*_test.go
*.test
coverage.out

# Docs
*.md
docs/

# Docker
Dockerfile*
docker-compose*
.dockerignore

Hot Reload در Development

docker-compose.dev.yml:

version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "8080:8080"
    volumes:
      - .:/app
    environment:
      - GO_ENV=development

Dockerfile.dev:

FROM golang:1.21-alpine

# نصب air برای hot reload
RUN go install github.com/cosmtrek/air@latest

WORKDIR /app

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

COPY . .

EXPOSE 8080

CMD ["air"]

.air.toml:

root = "."
tmp_dir = "tmp"

[build]
cmd = "go build -o ./tmp/main ."
bin = "./tmp/main"
include_ext = ["go", "tpl", "tmpl", "html"]
exclude_dir = ["tmp", "vendor"]
delay = 1000

[screen]
clear_on_rebuild = true

Production Dockerfile کامل

# ====== Build Stage ======
FROM golang:1.21-alpine AS builder

# Build arguments
ARG VERSION=dev
ARG COMMIT=unknown

# Install dependencies
RUN apk add --no-cache git ca-certificates tzdata

WORKDIR /app

# Copy go mod files
COPY go.mod go.sum ./
RUN go mod download && go mod verify

# Copy source
COPY . .

# Build with version info
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
    go build \
    -ldflags="-w -s -X main.Version=${VERSION} -X main.Commit=${COMMIT}" \
    -o /app/server .

# ====== Runtime Stage ======
FROM alpine:3.18

# Labels
LABEL maintainer="your@email.com"
LABEL version="${VERSION}"

# Install runtime dependencies
RUN apk --no-cache add ca-certificates tzdata && \
    update-ca-certificates

# Create non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

WORKDIR /app

# Copy binary
COPY --from=builder /app/server .
COPY --from=builder /app/configs ./configs

# Set ownership
RUN chown -R appuser:appgroup /app

# Switch to non-root user
USER appuser

# Environment
ENV TZ=Asia/Tehran
ENV GIN_MODE=release

# Port
EXPOSE 8080

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD wget -qO- http://localhost:8080/health || exit 1

# Run
ENTRYPOINT ["./server"]

دستورات کاربردی

# ساخت با tag
docker build -t myapp:1.0.0 .

# ساخت با build args
docker build \
  --build-arg VERSION=1.0.0 \
  --build-arg COMMIT=$(git rev-parse --short HEAD) \
  -t myapp:1.0.0 .

# Push به registry
docker tag myapp:1.0.0 registry.example.com/myapp:1.0.0
docker push registry.example.com/myapp:1.0.0

# اجرا با متغیرهای محیطی
docker run -d \
  --name myapp \
  -p 8080:8080 \
  -e DB_HOST=localhost \
  -e DB_PORT=5432 \
  myapp:1.0.0

# مشاهده لاگ‌ها
docker logs -f myapp

# ورود به container
docker exec -it myapp /bin/sh

# بررسی سلامت
docker inspect --format='' myapp

بهترین شیوه‌ها

شیوه توضیح
Multi-stage build کاهش اندازه image
Non-root user امنیت بیشتر
.dockerignore کاهش context size
Health check مانیتورینگ
Specific tags نه latest
Layer caching سرعت build
CGO_ENABLED=0 باینری مستقل

قدم‌های بعدی

منابع

بیش از ۱۰۰۰ شرکت‌کننده یادگیری Go و Backend رو از امروز شروع کن
ثبت‌نام دوره + تیم‌سازی