Go और Docker — एकदम सही जोड़ी क्यों?
\n\nGo (या Golang) एक ऐसी भाषा है जो शुरू से ही आधुनिक क्लाउड आर्किटेक्चर के लिए बनाई गई थी। Docker के मानक बनने से पहले ही, Go स्टैटिक बाइनरी में कंपाइल हो जाता था जिसे किसी डिपेंडेंसी की ज़रूरत नहीं होती। और Docker वह तकनीक है जो आपके एप्लिकेशन को उसके पूरे वातावरण के साथ एक हल्के कंटेनर में पैक कर देती है। जब आप इन दोनों तकनीकों को जोड़ते हैं, तो आपको लगभग परफेक्ट समाधान मिलता है: न्यूनतम इमेज साइज़, बिजली की गति से स्टार्टअप, और डिपेंडेंसी कॉन्फ्लिक्ट का कोई झंझट नहीं।
\n\nइस लेख में हम कंटेनरीकरण के सिद्धांतों पर लेक्चर नहीं देंगे। इसके बजाय, हम एक सरल Go एप्लिकेशन लिखेंगे, उसे Docker इमेज में बनाएंगे, multi-stage build से ऑप्टिमाइज़ करेंगे, और सुनिश्चित करेंगे कि हमारा कंटेनर प्रोडक्शन के लिए तैयार है। यह सब — वास्तविक कोड उदाहरणों के साथ, जिन्हें आप अभी चला सकते हैं।
\n\nचरण 1: एक सरल Go एप्लिकेशन लिखें
\n\nसबसे पहले, Go में एक सरल HTTP सर्वर बनाते हैं। यह हमारा 'टेस्ट' प्रोग्राम होगा। main.go नामक फ़ाइल बनाएं और इसमें निम्नलिखित कोड डालें:
package main\n\nimport (\n "fmt"\n "log"\n "net/http"\n "os"\n)\n\nfunc main() {\n port := os.Getenv("PORT")\n if port == "" {\n port = "8080"\n }\n\n http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {\n fmt.Fprintf(w, "Go कंटेनर से नमस्ते! 🐹")\n })\n\n log.Printf("सर्वर पोर्ट %s पर शुरू हुआ", port)\n log.Fatal(http.ListenAndServe(":"+port, nil))\n}\n\n\nयह कोड क्लासिक है: यह एक पोर्ट सुनता है (जिसे PORT एनवायरनमेंट वेरिएबल से सेट किया जा सकता है) और किसी भी रिक्वेस्ट पर एक सरल अभिवादन भेजता है। अब हम चाहते हैं कि यह एप्लिकेशन Docker में चले, चाहे कंटेनर किसी भी ऑपरेटिंग सिस्टम पर चल रहा हो।
चरण 2: पहला Dockerfile — सरल तरीका
\n\nGo एप्लिकेशन को 'कंटेनरीकृत' करने का सबसे आसान तरीका है पूरा Go इमेज लेना, उसमें कोड कॉपी करना और चलाना। Dockerfile नामक फ़ाइल बनाएं:
# आधिकारिक Go इमेज का उपयोग करें\nFROM golang:1.22\n\n# वर्किंग डायरेक्टरी सेट करें\nWORKDIR /app\n\n# प्रोजेक्ट फ़ाइलें कॉपी करें\nCOPY go.mod go.sum ./\nRUN go mod download\nCOPY . .\n\n# एप्लिकेशन बनाएं\nRUN go build -o main .\n\n# चलाएं\nCMD ["./main"]\n\n\nइमेज बनाएं और चलाएं:
\n\ndocker build -t go-app:v1 .\ndocker run -p 8080:8080 go-app:v1\n\n\nब्राउज़र खोलें और http://localhost:8080 पर जाएं। काम कर रहा है? बढ़िया। लेकिन एक समस्या है: इमेज का साइज़। आइए चेक करें:
docker images go-app:v1\n\n\nआपको कुछ इस तरह दिखेगा 1.2 GB। यह एक आपदा है! इमेज में पूरा Go कंपाइलर, पैकेज मैनेजर, सिस्टम यूटिलिटीज़ — वह सब कुछ है जो तैयार बाइनरी के लिए ज़रूरी नहीं है। प्रोडक्शन में ऐसी इमेज लोड होने में बहुत समय लेगी और बहुत जगह घेरेगी।
चरण 3: Multi-stage Build — हल्की इमेज का राज़
\n\nDocker multi-stage build को सपोर्ट करता है। इसका मतलब है कि आप एक ही Dockerfile में कई FROM इंस्ट्रक्शन का उपयोग करते हैं, और केवल अंतिम स्टेज ही फाइनल इमेज में जाती है। पहली स्टेज — 'बिल्ड' स्टेज — में कंपाइलर और सभी टूल्स होते हैं। दूसरी स्टेज — न्यूनतम, जैसे scratch (खाली इमेज) या alpine।
आइए अपने Dockerfile को फिर से लिखें:
\n\n# स्टेज 1: बिल्ड\nFROM golang:1.22 AS builder\n\nWORKDIR /app\n\n# डिपेंडेंसी कैश करें\nCOPY go.mod go.sum ./\nRUN go mod download\n\n# सोर्स कोड कॉपी करें और बिल्ड करें\nCOPY . .\nRUN CGO_ENABLED=0 GOOS=linux go build -o main .\n\n# स्टेज 2: फाइनल इमेज\nFROM alpine:latest\n\nRUN apk --no-cache add ca-certificates\n\nWORKDIR /root/\n\n# पहली स्टेज से केवल बाइनरी कॉपी करें\nCOPY --from=builder /app/main .\n\nEXPOSE 8080\n\nCMD ["./main"]\n\n\nयहाँ क्या हुआ? हमने दो स्टेज बनाईं: