داکرایز کردن اپلیکیشن گولنگ - آموزش Docker با Go
2025/11/24Docker ابزار استاندارد صنعت برای containerization است. Go و Docker ترکیب عالی هستند - Go باینریهای کوچک و مستقل تولید میکند که در containerهای سبک به خوبی کار میکنند.
پیشنیازها
- نصب Go
- نصب Docker
# بررسی نصب 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-appMulti-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*
.dockerignoreHot Reload در Development
docker-compose.dev.yml:
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "8080:8080"
volumes:
- .:/app
environment:
- GO_ENV=developmentDockerfile.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 = trueProduction 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 | باینری مستقل |