مقدمة
\nحاويات تطبيقات Go باستخدام Docker هي معيار التطوير الحديث. ومع ذلك، غالبًا ما تكون ملفات Dockerfile الأساسية بعيدة عن المثالية: الصور ثقيلة، والبناء بطيء، وفي الإنتاج تظهر مشاكل مع التسجيل والإشارات وفحوصات الصحة. في هذه المقالة، سنستعرض تقنيات متقدمة: من البناء متعدد المراحل إلى الضبط الدقيق للشبكة ووحدات التخزين. ستتعلم كيفية جعل صورة تطبيق Go صغيرة وآمنة وجاهزة للإنتاج.
\n\n1. البناء متعدد المراحل: صورة صغيرة في ثوانٍ
\nGo يُترجم إلى ملف ثنائي ثابت، وهو مثالي للحاويات. ولكن إذا كنت تستخدم الصورة الكاملة golang:1.22 للتشغيل، فأنت تحمل المترجم ومدير الحزم والأدوات النظامية. الحل هو البناء متعدد المراحل.
Dockerfile أساسي مع بناء متعدد المراحل
\n# المرحلة 1: البناء\nFROM golang:1.22-alpine AS builder\nWORKDIR /app\nCOPY go.mod go.sum ./\nRUN go mod download\nCOPY . .\nRUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /app/main ./cmd/\n\n# المرحلة 2: صورة صغيرة\nFROM alpine:3.19\nRUN apk add --no-cache ca-certificates tzdata\nCOPY --from=builder /app/main /usr/local/bin/main\nEXPOSE 8080\nENTRYPOINT ["/usr/local/bin/main"]\n\nلماذا يعمل هذا؟
\n- \n
- Alpine — 5 ميجابايت، مجموعة أدوات صغيرة. \n
CGO_ENABLED=0— يعطل التبعيات C، يصبح الملف الثنائي ثابتًا. \n -ldflags="-s -w"— يزيل معلومات التصحيح، مما يقلل حجم الملف الثنائي بنسبة 30-40%. \n ca-certificatesوtzdata— لطلبات HTTPS والوقت الصحيح. \n
النتيجة: صورة بحجم 10-15 ميجابايت بدلاً من 800+ ميجابايت. البناء — 15-20 ثانية (مع تخزين التبعيات مؤقتًا).
\n\n2. تحسين التخزين المؤقت والطبقات
\nDocker يخزن الطبقات مؤقتًا. إذا قمت بنسخ كل الكود قبل go mod download، فإن أي تغيير في ملفات .go يعيد تعيين ذاكرة التخزين المؤقت للتبعيات. الترتيب الصحيح:
COPY go.mod go.sum ./\nRUN go mod download\nCOPY . .\n\nأيضًا استخدم .dockerignore:
.git\n*.md\ntest/\ncoverage/\n.env\nDockerfile\n\nهذا يستبعد الملفات غير الضرورية من سياق البناء، مما يسرع النقل إلى daemon Docker.
\n\nخدعة متقدمة: تخزين الوحدات مؤقتًا
\nإذا كنت تستخدم Go modules، يمكنك تركيب ذاكرة التخزين المؤقت:
\nFROM golang:1.22-alpine AS builder\nWORKDIR /app\nRUN --mount=type=cache,target=/go/pkg/mod \\\n --mount=type=cache,target=/root/.cache/go-build \\\n go build -ldflags="-s -w" -o /app/main ./cmd/\n\nهذا يحافظ على الوحدات التي تم تنزيلها ونتائج البناء بين عمليات تشغيل docker build.
3. فحوصات الصحة والإشارات والإيقاف الآمن
\nDocker يمكنه التحقق من صحة الحاوية. أضف في Dockerfile:
\n\nHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\\n CMD ["/usr/local/bin/main", "health"]\n\nفي كود Go، نفذ نقطة النهاية /healthz:
package main\n\nimport (\n "net/http"\n "os"\n "os/signal"\n "syscall"\n)\n\nfunc main() {\n http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {\n w.WriteHeader(http.StatusOK)\n w.Write([]byte("ok"))\n })\n\n srv := &http.Server{Addr: ":8080"}\n\n // إيقاف آمن\n go func() {\n sigint := make(chan os.Signal, 1)\n signal.Notify(sigint, syscall.SIGTERM, syscall.SIGINT)\n <-sigint\n srv.Shutdown(nil)\n }()\n\n srv.ListenAndServe()\n}\n\nمهم: يجب على تطبيق Go معالجة SIGTERM بشكل صحيح (الذي يرسله Docker عند إيقاف الحاوية). بدون إيقاف آمن، قد تفقد بيانات أو تترك اتصالات مفتوحة.