मुख्य सामग्री पर जाएँ

Terraform Docker: एक व्यापक गाइड

Terraform के साथ Docker पर पुनरुत्पादनीय कंटेनर डिप्लॉयमेंट बनाकर इन्फ्रास्ट्रक्चर-एज़-कोड में महारत हासिल करें। प्रोवाइडर सेटअप से लेकर ऑटोमेटेड CI/CD तक की पाइपलाइन सीखें।
· 13 मि॰ पढ़ें

AI के साथ खोजें

मैंने विकास और प्रोडक्शन दोनों वातावरणों में Docker कंटेनरों को मैन्युअल रूप से प्रबंधित करने में अनगिनत घंटे बिताए हैं। असंगत कॉन्फ़िगरेशन, स्टेट का ड्रिफ्ट होना, और यह अनिश्चितता कि क्या मेरा लोकल सेटअप प्रोडक्शन से मेल खाता है, हर डिप्लॉयमेंट में समस्या बनती थी। जब मैंने Terraform के Docker प्रोवाइडर की खोज की, तो सब कुछ बदल गया।

इस ट्यूटोरियल में, मैं आपको Docker के साथ Terraform को जोड़कर पुनरुत्पादनीय, वर्शन-नियंत्रित इन्फ्रास्ट्रक्चर बनाने की प्रक्रिया से गुजराऊंगा। आप सीखेंगे कि कंटेनर कैसे प्रोविजन करें, नेटवर्क और वॉल्यूम कैसे प्रबंधित करें, संसाधन सीमाएँ कैसे लागू करें, और अपनी टीम के बीच स्टेट कैसे बनाए रखें।

चाहे आप बिल्ड सर्वर प्रबंधित कर रहे हों या माइक्रोसर्विसेज का ऑर्केस्ट्रेशन कर रहे हों, अपना टर्मिनल खोलें और देखें कि आप Docker इन्फ्रास्ट्रक्चर को कैसे संभालते हैं, इसे कैसे बदल सकते हैं।

यदि आप Docker में नए हैं, तो मैं हमारे Introduction to Docker कोर्स से शुरुआत करने की सलाह देता हूँ।

Terraform Docker इंटीग्रेशन क्या है?

Terraform एक इन्फ्रास्ट्रक्चर-एज़-कोड टूल है जो डिक्लेरेटिव वर्कफ़्लो के माध्यम से संसाधनों के जीवनचक्र का प्रबंधन करता है। अलग-अलग Docker कमांड चलाने के बजाय, आप कॉन्फ़िगरेशन फ़ाइलों में इच्छित इन्फ्रास्ट्रक्चर स्टेट परिभाषित करते हैं। फिर Terraform plan-apply-destroy जीवनचक्र निष्पादित करता है: यह आवश्यक परिवर्तनों की गणना करता है, एक प्रीव्यू दिखाता है, और केवल आपकी स्वीकृति के बाद उन्हें लागू करता है।

Terraform Docker प्रोवाइडर HashiCorp Configuration Language (HCL) कोड और Docker API के बीच अनुवाद परत का काम करता है। जब आप कॉन्फ़िगरेशन में resource “docker_container" लिखते हैं, तो प्रोवाइडर उस घोषणा को उपयुक्त Docker API कॉल्स में बदल देता है। यह एब्स्ट्रैक्शन मतलब है कि Docker संसाधनों को उसी वर्कफ़्लो से प्रबंधित किया जा सकता है जिसका उपयोग क्लाउड इन्फ्रास्ट्रक्चर के लिए होता है।

यहाँ देखें कि Terraform Docker Compose से कैसे अलग है।

Compose YAML फ़ाइलों का उपयोग करते हुए प्रोजेक्ट-आधारित तरीके से कंटेनरों का प्रबंधन करता है, लेकिन वह वास्तव में क्या मौजूद है, इसका ट्रैक करने के लिए स्टेट फ़ाइल नहीं रखता। 

इसके विपरीत, Terraform हर उस संसाधन को terraform.tfstate में दर्ज करता है जिसे वह बनाता है, जिससे वह मेरी कॉन्फ़िगरेशन और वास्तविकता के बीच ड्रिफ्ट का पता लगा सकता है। यदि कोई व्यक्ति किसी कंटेनर को मैन्युअल रूप से संशोधित करता है, तो Terraform इसे नोटिस करेगा और उसे परिभाषित स्टेट में बहाल कर सकता है।

Docker Compose बनाम Terraform Docker

यह तरीका कई परिदृश्यों में चमकता है:

  • पुनरुत्पादनीय बिल्ड सर्वरों के लिए, आप एक ही कमांड से पूरे वातावरण को नष्ट करके फिर से बना सकते हैं, जिससे सुसंगति की गारंटी मिलती है। 
  • टेस्टिंग वातावरण में, आप प्रत्येक टेस्ट रन के लिए अलग-थलग इन्फ्रास्ट्रक्चर स्पिन अप कर सकते हैं। 
  • इम्यूटेबल डिप्लॉयमेंट्स के लिए, आप कंटेनरों को जगह पर संशोधित करने के बजाय पूरी तरह बदलते हैं, जिससे डिप्लॉयमेंट जोखिम कम होते हैं।

पूर्वापेक्षाएँ और इंस्टॉलेशन

Terraform कॉन्फ़िगरेशन में उतरने से पहले, सुनिश्चित करें कि आवश्यक टूल इंस्टॉल और सही तरीके से कॉन्फ़िगर हैं।

सिस्टम आवश्यकताओं को पूरा करना

सबसे पहले, जाँचें कि Docker Engine आपकी मशीन पर चल रहा है। 

  • Linux: docker ps से जाँचें

  • macOS या Windows: सुनिश्चित करें कि Docker Desktop इंस्टॉल और रनिंग है

Terraform प्रोवाइडर को Docker डेमन की पहुँच चाहिए, इसलिए आपको यह सुनिश्चित करना होगा कि आपके यूज़र को Linux पर /var/run/docker.sock Unix सॉकेट या Windows पर नेम्ड पाइप तक पहुँच की अनुमति है।

अगले चरण में, HashiCorp की आधिकारिक वेबसाइट से Terraform CLI इंस्टॉल करें। Terraform इंस्टॉल करना ऑपरेटिंग सिस्टम के अनुसार भिन्न होता है:

  • Linux: उपयुक्त पैकेज डाउनलोड करें या अपने डिस्ट्रीब्यूशन के पैकेज मैनेजर का उपयोग करें। 

  • macOS: Homebrew का उपयोग करें। पहले brew tap hashicorp/tap से HashiCorp टैप इंस्टॉल करें, फिर brew install hashicorp/tap/terraform कमांड से Terraform इंस्टॉल करें। 

  • Windows: hashicorp.com से बाइनरी डाउनलोड करें और उसे PATH में जोड़ें, या Chocolatey का उपयोग करें: choco install terraform. 

इंस्टॉल होने के बाद, terraform version चलाकर इंस्टॉलेशन वेरिफाई करें। 

Docker और Terraform वेरिफाई हो जाने के बाद, अगला कदम मेंटेनबिलिटी के लिए प्रोजेक्ट फ़ाइलों का संगठन है।

प्रोजेक्ट संरचना कॉन्फ़िगर करना

Terraform प्रोजेक्ट्स एक स्पष्ट और संरचित दृष्टिकोण से लाभान्वित होते हैं। आमतौर पर, मैं अपने Terraform प्रोजेक्ट के लिए एक समर्पित डायरेक्टरी बनाता हूँ और वर्शन कंट्रोल इनिशियलाइज़ करता हूँ:

mkdir terraform-docker-project
cd terraform-docker-project
git init

इन्फ्रास्ट्रक्चर-एज़-कोड के लिए वर्शन कंट्रोल अत्यंत महत्वपूर्ण है। Docker इन्फ्रास्ट्रक्चर में हर बदलाव ट्रैक, रिव्यू और रिवर्सिबल होना चाहिए। मैं आमतौर पर Terraform की वर्किंग डायरेक्टरी और स्टेट फ़ाइलों को .gitignore फाइल में जोड़ता हूँ ताकि वे वर्शन कंट्रोल से बाहर रहें:

.terraform/
*.tfstate
*.tfstate.backup
.terraform.lock.hcl

अंत में, मैं एक खाली main.tf फ़ाइल बनाता हूँ जहाँ मैं अपनी इन्फ्रास्ट्रक्चर परिभाषित करूँगा। यह फ़ाइल प्रोवाइडर कॉन्फ़िगरेशन और संसाधन परिभाषाएँ रखेगी।

Terraform Docker प्रोवाइडर और कोर संसाधन

प्रोजेक्ट संरचना तैयार होने के साथ, अब Docker प्रोवाइडर को कॉन्फ़िगर करने और संसाधन परिभाषित करना शुरू करने का समय है।

Docker प्रोवाइडर इनिशियलाइज़ करना

सबसे पहले, main.tf में प्रोवाइडर कॉन्फ़िगरेशन जोड़ें:

terraform {
  required_providers {
    docker = {
      source  = "kreuzwerker/docker"
      version = "~> 3.0"
    }
  }
}

provider "docker" {
  host = "unix:///var/run/docker.sock"
}

required_providers ब्लॉक बताता है कि Terraform को प्रोवाइडर प्लगइन कहाँ से डाउनलोड करना चाहिए। वर्ज़न कंस्ट्रेंट (~> 3.0) का उपयोग करने से माइनर वर्ज़न अपडेट्स की अनुमति मिलती है जबकि ब्रेकिंग चेंजिस रोके जाते हैं। रिमोट Docker होस्ट्स के लिए, आप host पैरामीटर को tcp://192.168.1.100:2376 जैसा बदल सकते हैं।

अब प्रोजेक्ट रूट डायरेक्टरी में terraform init चलाएँ। यह Docker प्रोवाइडर प्लगइन डाउनलोड करता है और उसे .terraform/providers/ में स्टोर करता है। कमांड इंस्टॉल हुई सटीक वर्ज़न आउटपुट करता है, और Terraform एक लॉक फ़ाइल बनाता है ताकि मेरी टीम में प्रोवाइडर वर्ज़न सुसंगत रहें।

Terraform Init

कंटेनर इमेज प्रबंधित करना

प्रोवाइडर इनिशियलाइज़ होने के साथ, अगला कदम कंटेनर इमेज परिभाषित करना है। कंटेनर बनाने से पहले, आपको उन इमेजेज़ को प्रबंधित करना होगा जिनका वे उपयोग करेंगे, इसलिए एक इमेज संसाधन परिभाषित करें:

resource "docker_image" "nginx" {
  name         = "nginx:1.29"
  keep_locally = true
}

यह संसाधन प्रोवाइडर ब्लॉक के तुरंत बाद जोड़ें। keep_locally पैरामीटर महत्वपूर्ण है क्योंकि यह terraform destroy चलाने पर Terraform को इमेज हटाने से रोकता है। यह तब उपयोगी है जब कई कंटेनर एक ही इमेज साझा करते हैं या जब मैं डिप्लॉयमेंट्स के बीच कैश्ड इमेजेज़ संरक्षित रखना चाहता हूँ।

प्रोडक्शन डिप्लॉयमेंट्स के लिए, इम्यूटेबिलिटी सुनिश्चित करने हेतु इमेजेज़ को उनके SHA256 डाइजेस्ट से पिन करें:

resource "docker_image" "nginx" {
 name = "nginx@sha256:b60f25eb5acdd79172de1a289891d9cfe4fc3669daddeeb68619240cbe839d9f"
}

डाइजेस्ट कंटेनर रजिस्ट्री से प्राप्त किया जा सकता है। nginx जैसी Docker Hub इमेज के लिए, आप उन्हें आधिकारिक Docker वेबसाइट पर Tags सेक्शन में पा सकते हैं। डाइजेस्ट का उपयोग यह गारंटी देता है कि हर बार बिल्कुल वही इमेज बाइनरी डिप्लॉय होगी, भले ही कोई व्यक्ति उसी टैग के साथ नई इमेज पुश कर दे।

Docker कंटेनर प्रोविजन करना

इमेज परिभाषित होने के बाद, अगला कदम उन्हें संदर्भित करने वाले कंटेनर बनाना है:

resource "docker_container" "web" {
  name  = "nginx-web"
  image = docker_image.nginx.image_id

  ports {
    internal = 80
    external = 8080
  }

  env = [
    "NGINX_HOST=example.com",
    "NGINX_PORT=80"
  ]
}

इमेज को docker_image.nginx.image_id से संदर्भित किया जाता है। यह एक इम्प्लिसिट डिपेंडेंसी बनाता है क्योंकि इमेज मौजूद हुए बिना Terraform कंटेनर बनाने की कोशिश नहीं करेगा। ports ब्लॉक कंटेनर के आंतरिक पोर्ट 80 को मेरे होस्ट के पोर्ट 8080 से मैप करता है, जो docker run -p 8080:80 के बराबर है।

एनवायरनमेंट वेरिएबल्स को स्ट्रिंग्स के रूप में env सूची में रखा जाता है। यदि कोई पैरामीटर बदलता है, तो Terraform कंटेनर को पुनः बनाता है, यह सुनिश्चित करते हुए कि रनिंग इन्फ्रास्ट्रक्चर हमेशा कॉन्फ़िगरेशन से मेल खाता है।

इस बिंदु पर, terraform plan चलाकर देखें कि Terraform क्या बनाएगा, फिर terraform apply से इन्फ्रास्ट्रक्चर प्रोविजन करें। Terraform इमेज और कंटेनर बनाएगा। आप Docker Desktop में संसाधन देखकर या टर्मिनल में docker ps चलाकर इसे वेरिफाई कर सकते हैं।

Terraform में नेटवर्किंग, स्टोरेज, और संसाधन सीमाएँ

अब जब आपका एक बेसिक कंटेनर चल रहा है और आपको कोर वर्कफ़्लो समझ आ गया है, तो चलिए इन्फ्रास्ट्रक्चर को प्रोडक्शन-रेडी फ़ीचर्स के साथ विस्तार करते हैं। अगले सेक्शन इस नींव पर नेटवर्किंग, स्थायी स्टोरेज, और संसाधन बाधाएँ जोड़ते हैं—जो वास्तविक दुनिया के डिप्लॉयमेंट्स के लिए आवश्यक हैं।

नेटवर्किंग प्रबंधित करना

कंटेनरों के बीच संचार सक्षम करने के साथ-साथ आइसोलेशन बनाए रखने के लिए, समर्पित नेटवर्क बनाना आवश्यक है। यहाँ बताया गया है कि कंटेनर कनेक्टिविटी नियंत्रित करने के लिए आइसोलेटेड नेटवर्क कैसे बनाते हैं। main.tf फ़ाइल में निम्न संसाधन जोड़ें:

resource "docker_network" "app_network" {
  name   = "application_net"
  driver = "bridge"
}

अब इस नेटवर्क का उपयोग करने वाला दूसरा कंटेनर जोड़ें। इसे web कंटेनर के बाद जोड़ें:

resource "docker_container" "api" {
  name  = "api-server"
  image = docker_image.nginx.image_id

  networks_advanced {
    name = docker_network.app_network.name
  }
}

यह एक समर्पित ब्रिज नेटवर्क बनाता है और api कंटेनर को उससे जोड़ता है। एक ही नेटवर्क पर कंटेनर अपने कंटेनर नामों को होस्टनाम के रूप में उपयोग करके संवाद कर सकते हैं, जो माइक्रोसर्विसेज आर्किटेक्चर के लिए उपयुक्त है। 

नेटवर्क आइसोलेशन वेरिफाई करने के लिए docker network inspect application_net चलाएँ और सुनिश्चित करें कि केवल इच्छित कंटेनर जुड़े हैं। सुनिश्चित करें कि आप यह कमांड terraform plan और terraform apply से संसाधन बनाने के बाद चलाएँ।

Network Creation Verification

इंटर-कंटेनर संचार के लिए नेटवर्किंग कॉन्फ़िगर हो जाने के बाद, अगला महत्वपूर्ण पहलू डेटा परसिस्टेंस है।

स्थायी वॉल्यूम कॉन्फ़िगर करना

ऐसे डेटा के लिए जो कंटेनर रिस्टार्ट्स के बाद भी बना रहना चाहिए, वॉल्यूम संसाधन जोड़ें। इन्हें कंटेनर परिभाषाओं से पहले डालें:

resource "docker_volume" "db_data" {
  name = "postgres_data"
}

अब इस वॉल्यूम का उपयोग करने वाला एक डेटाबेस कंटेनर जोड़ें:

resource "docker_container" "database" {
  name  = "postgres"
  image = "postgres:15"

 env = [
    "POSTGRES_PASSWORD=mysecretpassword"
  ]

  volumes {
    volume_name    = docker_volume.db_data.name
    container_path = "/var/lib/postgresql/data"
  }
}

इस तरह के मैनेज्ड वॉल्यूम Docker द्वारा बनाए और नियंत्रित किए जाते हैं, और Docker की डेटा डायरेक्टरी में स्टोर होते हैं। होस्ट से कॉन्फ़िगरेशन फ़ाइलें साझा करने के लिए, बाइंड माउंट्स का उपयोग करें और volume_name के बजाय host_path निर्दिष्ट करें।

volumes {
  host_path      = "/opt/app/config"
  container_path = "/etc/app/config"
  read_only      = true
}

जब यह सुनिश्चित हो जाए कि डेटा कंटेनर रिस्टार्ट्स के बाद भी बना रहता है, उतना ही महत्वपूर्ण है किसी एक कंटेनर को सिस्टम संसाधनों पर एकाधिकार करने से रोकना।

संसाधन सीमाएँ सेट करना

स्टोरेज से आगे, प्रत्येक कंटेनर कितना CPU और मेमोरी उपयोग कर सकता है, इसे नियंत्रित करना सिस्टम स्थिरता के लिए महत्वपूर्ण है। कंटेनरों को अत्यधिक संसाधन उपभोग से रोकने के लिए, संसाधन सीमाएँ लागू करें।

हालाँकि Docker कुछ संसाधन सीमाएँ इन-प्लेस अपडेट करने देता है, Terraform का डिक्लेरेटिव मॉडल अक्सर स्टेट को कॉन्फ़िगरेशन से मिलाने हेतु कंटेनर को रिप्लेस करने की आवश्यकता करता है। इस रिप्लेसमेंट के दौरान डाउनटाइम रोकने के लिए, हम create_before_destroy लाइफसाइकल नियम का उपयोग करते हैं। 

महत्वपूर्ण: हमें रिप्लेसमेंट प्रक्रिया के दौरान नाम संघर्षों को रोकने के लिए फिक्स्ड name आर्ग्युमेंट हटाना होगा। एक विकल्प name_prefix आर्ग्युमेंट का उपयोग करना है।

resource "docker_container" "api" {
  name_prefix       = "api-server-"
  image      = docker_image.nginx.image_id
  memory     = 512
  cpu_shares = 1024

  networks_advanced {
    name = docker_network.app_network.name
  }

 lifecycle {
    create_before_destroy = true
  }
}

memory पैरामीटर RAM को मेगाबाइट्स में सीमित करता है। cpu_shares अलग तरह से काम करता है। यह CPU कंटेंशन होने पर उपयोग होने वाला एक रिलेटिव वेट है। 1024 शेयर वाला कंटेनर 512 शेयर वाले कंटेनर की तुलना में दोगुना CPU टाइम प्राप्त करेगा, लेकिन केवल तब जब होस्ट पर लोड हो। 

हार्ड CPU सीमाओं के लिए, आप cpu_set का उपयोग करके कंटेनरों को विशिष्ट CPU कोर पर पिन कर सकते हैं:

cpu_set = "0,1"
}

इन सीमाओं को docker inspect background-worker --format='{{.HostConfig.Memory}} {{.HostConfig.CpuShares}} चलाकर वेरिफाई करें और देखें कि Memory और NanoCpus मान कॉन्फ़िगरेशन से मेल खाते हैं या नहीं। 

यहाँ भी, जैसा कि ऊपर बताया गया, संसाधन बनाने के लिए पहले आपको terraform plan और terraform apply चलाने की आवश्यकता है।

इस बिंदु पर, main.tf फ़ाइल में प्रोवाइडर कॉन्फ़िगरेशन, एक इमेज, एक नेटवर्क, एक वॉल्यूम, और विभिन्न कॉन्फ़िगरेशन वाले तीन कंटेनर शामिल हैं। 

Terraform में वेरिएबल्स, मॉड्यूल्स, और सीक्रेट्स

जैसे-जैसे इन्फ्रास्ट्रक्चर बढ़ता है, हार्डकोडेड मान अनम्य हो जाते हैं। यह सेक्शन दिखाता है कि वेरिएबल्स, मॉड्यूल्स, और उचित सीक्रेट हैंडलिंग का उपयोग करके कॉन्फ़िगरेशन को पुन: प्रयोज्य कैसे बनाया जाए।

इनपुट वेरिएबल्स का उपयोग

कॉन्फ़िगरेशन को लचीला बनाने का पहला कदम हार्डकोडेड मानों को वेरिएबल्स में निकालना है, जिन्हें मुख्य कोड में बदलाव किए बिना आसानी से बदला जा सकता है। यह उसी डायरेक्टरी में variables.tf नामक नई फ़ाइल बनाकर किया जा सकता है:

variable "web_port" {
  description = "External port for web container"
  type        = number
  default     = 8080

  validation {
    condition     = var.web_port > 1024 && var.web_port < 65535
    error_message = "Port must be between 1024 and 65535."
  }
}

अब main.tf में वेब कंटेनर को इस वेरिएबल का उपयोग करने के लिए अपडेट करें:

resource "docker_container" "web" {
  name  = "nginx-web"
  image = docker_image.nginx.image_id

  ports {
    internal = 80
    external = var.web_port
  }

  env = [
    "NGINX_HOST=example.com",
    "NGINX_PORT=80"
  ]
}

वैलिडेशन ब्लॉक प्रिविलेज्ड पोर्ट्स के उपयोग को रोकता है। डिफ़ॉल्ट मान ओवरराइड करने के लिए, एक terraform.tfvars फ़ाइल बनाएँ:

web_port = 9000

terraform apply चलाते समय Terraform स्वचालित रूप से इस फ़ाइल से मान पढ़ लेगा। वैकल्पिक रूप से, कमांड लाइन के माध्यम से मान पास करें: terraform apply -var="web_port=9000".

पुन: प्रयोज्य मॉड्यूल बनाना

वेरिएबल्स हार्डकोडेड मानों की समस्या हल करते हैं, लेकिन यदि आपको सभी संसाधनों सहित उसी पूरे पैटर्न को कई बार डिप्लॉय करना हो तो क्या करें? 

यहीं मॉड्यूल्स उत्कृष्ट हैं। एक मॉड्यूल को ऐसे ब्लूप्रिंट के रूप में सोचें जो उन सभी अलग-अलग हिस्सों को एक पैकेज में बाँधता है, जिससे आप उस पूरे जटिल सेटअप को एक यूनिट के रूप में बार-बार 'स्टैम्प आउट' कर सकें।

मॉड्यूल डायरेक्टरी संरचना बनाकर शुरू करें:

mkdir -p modules/web-app

अब modules/web-app/variables.tf फ़ाइल बनाएँ और निम्न जोड़ें:

variable "environment" {
  description = "Environment name"
  type        = string
}

variable "port" {
  description = "External port"
  type        = number
}

इसके बाद, मुख्य फ़ाइल modules/web-app/main.tf बनाएँ और यह संसाधन जोड़ें:

resource "docker_container" "app" {
  name  = "app-${var.environment}"
  image = var.image_id

  ports {
    internal = 80
    external = var.port
  }
}

अंत में, आउटपुट्स फ़ाइल modules/web-app/outputs.tf बनाएँ, जिसका उपयोग मुख्य रूप से terraform apply चलाने के बाद टर्मिनल में इच्छित मान दिखाने के लिए किया जाता है:

output "container_ip" {
  value       = docker_container.app.network_data[0].ip_address
  description = "IP address of the application container"
}

मॉड्यूल परिभाषाएँ जोड़ने के बाद, मॉड्यूल्स इंस्टॉल करने के लिए terraform init चलाएँ, फिर एक ही टेम्पलेट से दोनों कंटेनर बनाने के लिए terraform apply चलाएँ। आपको Docker Desktop में सभी संसाधन दिखाई देने चाहिए।

Terraform Modulesमॉड्यूल्स के माध्यम से पुन: प्रयोज्य इन्फ्रास्ट्रक्चर पैटर्न स्थापित करने के साथ, कॉन्फ़िगरेशन प्रबंधन का एक और महत्वपूर्ण पहलू बचता है: पासवर्ड और API कीज़ जैसी संवेदनशील जानकारी को सुरक्षित रूप से संभालना।

संवेदनशील डेटा हैंडल करना

डेटाबेस पासवर्ड जैसी संवेदनशील वैल्यूज़ को हार्डकोड नहीं किया जाना चाहिए। इसके बजाय, आप variables.tf फ़ाइल का उपयोग कर सकते हैं और sensitive = true सेट कर सकते हैं:

variable "db_password" {
  description = "Database root password"
  type        = string
  sensitive   = true
}

अब main.tf में डेटाबेस कंटेनर को डेटाबेस पासवर्ड संदर्भित करने के लिए अपडेट करें:

resource "docker_container" "database" {
  name  = "postgres"
  image = "postgres:15"

  env = [
    "POSTGRES_PASSWORD=${var.db_password}"
  ]

  volumes {
    volume_name    = docker_volume.db_data.name
    container_path = "/var/lib/postgresql/data"
  }
}

पासवर्ड को terraform.tfvars में डालकर हार्डकोड करने के बजाय, इसे एनवायरनमेंट वेरिएबल के रूप में सेट करें:

export TF_VAR_db_password="your-secure-password"
terraform apply

sensitive = true फ़्लैग Terraform को कंसोल आउटपुट में वैल्यू दिखाने से रोकता है। 

हालाँकि, ये वैल्यूज़ terraform.tfstate में सादा पाठ के रूप में स्टोर होती हैं, इसलिए यह सुनिश्चित करने के लिए कि यह फ़ाइल सुरक्षित है, हम एन्क्रिप्शन के साथ रिमोट बैकएंड्स का उपयोग करके इसे सुरक्षित कर सकते हैं। आइए देखें कि यह कैसे करना है।

Terraform स्टेट प्रबंधन और CI/CD इंटीग्रेशन

यह सेक्शन प्रोडक्शन डिप्लॉयमेंट्स के लिए आवश्यक स्टेट मैकेनिक्स और ऑटोमेशन वर्कफ़्लोज़ को कवर करता है। लेकिन ऑटोमेशन लागू करने से पहले, यह समझना ज़रूरी है कि Terraform अपनी स्टेट फ़ाइल के माध्यम से आपकी इन्फ्रास्ट्रक्चर को कैसे ट्रैक करता है। 

स्टेट मैकेनिक्स समझना

स्टेट, Terraform की इन्फ्रास्ट्रक्चर प्रबंधन क्षमता की नींव है। terraform.tfstate फ़ाइल कॉन्फ़िगरेशन को वास्तविक Docker कंटेनर IDs और संसाधन एट्रिब्यूट्स से मैप करती है। terraform apply चलाते समय, Terraform इस स्टेट की तुलना कॉन्फ़िगरेशन से करता है और आवश्यक न्यूनतम बदलावों की गणना करता है।

वर्तमान स्टेट का निरीक्षण terraform show से करें, जो हर मैनेज्ड संसाधन दिखाता है। टीमों के लिए, लोकल स्टेट फ़ाइलें समस्याएँ, संघर्ष और संभावित डेटा लॉस पैदा करती हैं। समाधान है रिमोट बैकएंड्स।

क्लाउड इंफ्रा के बिना Docker-केंद्रित वर्कफ़्लो के लिए, Terraform Cloud का फ्री टियर आदर्श है। main.tf में terraform सेक्शन में एक बैकएंड ब्लॉक जोड़ें:

terraform {
  required_providers {
    docker = {
      source  = "kreuzwerker/docker"
      version = "~> 3.0"
    }
  }
  
  backend "remote" {
    organization = "your-org-name"
    
    workspaces {
      name = "docker-infrastructure"
    }
  }
}

एक फ्री खाता Terraform वेबसाइट पर बनाएँ। फिर terraform login चलाकर दिए गए टोकन से प्रमाणित करें, और फिर स्टेट माइग्रेट करने के लिए terraform init चलाएँ। यह रिमोट वर्कस्पेस में स्टेट लॉकिंग और क्लाउड इन्फ्रास्ट्रक्चर के बिना टीम सहयोग प्रदान करता है। 

हालाँकि, AWS या GCP जैसे क्लाउड प्रोवाइडर्स में भी रिमोट बैकएंड बनाना संभव है।

Terraform Cloud Remote Backend

वर्कफ़्लो ऑटोमेट करना

स्टेट प्रबंधन कॉन्फ़िगर होकर रिमोटली स्टोर होने के साथ, इन्फ्रास्ट्रक्चर टीम सहयोग के लिए तैयार है। अंतिम हिस्सा CI/CD पाइपलाइनों के माध्यम से डिप्लॉयमेंट प्रक्रिया को ऑटोमेट करना है, जिससे बदलाव सुसंगत और रिव्यूएबल रहें।

सबसे पहले, .github/workflows/terraform.yml बनाएँ:

name: Terraform Docker Deploy

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]

jobs:
  terraform:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      
      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v3
        
      - name: Terraform Init
        run: terraform init
        
      - name: Terraform Plan
        if: github.event_name == 'pull_request'
        run: terraform plan
        
      - name: Terraform Apply
        if: github.event_name == 'push' && github.ref == 'refs/heads/main'
        run: terraform apply -auto-approve

यह वर्कफ़्लो हर पुल रिक्वेस्ट पर terraform plan चलाता है, जिससे रिव्यूअर्स देख सकें कि कौन से इन्फ्रास्ट्रक्चर परिवर्तन होंगे। जब बदलाव मुख्य शाखा में मर्ज किए जाते हैं, तो terraform apply स्वचालित रूप से निष्पादित होता है, यह सुनिश्चित करते हुए कि हर इन्फ्रास्ट्रक्चर परिवर्तन कोड परिवर्तनों की तरह ही रिव्यू प्रक्रिया से गुजरे।

Terraform Docker समस्याएँ: ट्रबलशूटिंग

सावधानीपूर्वक कॉन्फ़िगरेशन के बावजूद, समस्याएँ आ सकती हैं। सामान्य मुद्दों को समझना और कब विकल्पों पर विचार करना चाहिए, बेहतर आर्किटेक्चरल निर्णय लेने में मदद करता है। 

“Permission denied”

Linux पर सबसे आम त्रुटि Docker सॉकेट से कनेक्ट करते समय "permission denied" है। यह तब होता है जब यूज़र के पास /var/run/docker.sock तक पहुँच की अनुमति नहीं होती। इसे यूज़र को docker समूह में जोड़कर ठीक करें:

sudo usermod -aG docker $USER

फिर लॉग आउट करके दोबारा लॉग इन करें।

WSL2 कनेक्टिविटी समस्याएँ

Windows पर WSL2 के साथ, कनेक्टिविटी समस्याएँ इसलिए आती हैं क्योंकि सॉकेट पाथ अलग होता है। सुनिश्चित करें कि Docker Desktop की "Expose daemon on tcp://localhost:2375 without TLS" सेटिंग सक्षम है, फिर main.tf में प्रोवाइडर अपडेट करें:

provider "docker" {
  host = "tcp://localhost:2375"
}

प्राइवेट रजिस्ट्री प्रमाणीकरण विफलताएँ

प्राइवेट Docker रजिस्ट्रीज़ के लिए, प्रोवाइडर ब्लॉक में ऑथेंटिकेशन जोड़ें, क्रेडेंशियल्स को वेरिएबल्स के रूप में परिभाषित करें, और हार्डकोडिंग से उत्पन्न समस्याओं से बचने के लिए उन्हें एनवायरनमेंट वेरिएबल्स के माध्यम से सेट करें।

hclprovider "docker" {
  host = "unix:///var/run/docker.sock"
  
  registry_auth {
    address  = "registry.mycompany.com"
    username = var.registry_username
    password = var.registry_password
  }
}

Terraform के विकल्प

ट्रबलशूटिंग से परे, यह समझना भी उतना ही मूल्यवान है कि कब आपके विशेष उपयोग-केस के लिए Terraform से अधिक उपयुक्त अन्य टूल हो सकते हैं।

Terraform बनाम Kubernetes

Kubernetes कहीं अधिक परिष्कृत ऑर्केस्ट्रेशन क्षमताएँ प्रदान करता है: 

  • सेल्फ-हीलिंग
  • उन्नत शेड्यूलिंग
  • सर्विस डिस्कवरी
  • बिल्ट-इन लोड बैलेंसिंग

जटिल मल्टी-नोड डिप्लॉयमेंट्स जिनमें उच्च उपलब्धता की आवश्यकता होती है, उनके लिए Kubernetes बेहतर विकल्प है। Terraform Kubernetes इन्फ्रास्ट्रक्चर प्रोविजन कर सकता है, जबकि Helm या Kubernetes मैनिफेस्ट्स एप्लिकेशन डिप्लॉयमेंट संभालते हैं।

Terraform बनाम Ansible

Ansible कंटेनरों के अंदर कॉन्फ़िगरेशन मैनेजमेंट में उत्कृष्ट है। जहाँ Terraform इन्फ्रास्ट्रक्चर प्रोविजन करता है, वहीं Ansible सॉफ़्टवेयर कॉन्फ़िगरेशन और पैकेज इंस्टॉलेशन को प्रबंधित करता है। अक्सर दोनों टूल साथ काम करते हैं: Terraform Docker कंटेनर बनाता है, फिर Ansible उनके भीतर चलने वाले एप्लिकेशनों को कॉन्फ़िगर करता है।

Terraform बनाम Docker Compose

सरल लोकल डेवलपमेंट वातावरण के लिए, Docker Compose सबसे व्यवहारिक विकल्प बना रहता है। Terraform पुनरुत्पादनीय डिप्लॉयमेंट्स में और जब अन्य इन्फ्रास्ट्रक्चर घटकों के साथ एकीकरण की आवश्यकता होती है, तब चमकता है।

यह तय करने में मदद के लिए कि आपको कौन सा चुनना चाहिए, मैंने सबसे महत्वपूर्ण अंतर इस तालिका में संक्षेपित किया है:

टूल

मुख्य खूबियाँ

सर्वोत्तम उपयोग-केस

Terraform की तुलना में

Kubernetes

उन्नत ऑर्केस्ट्रेशन (सेल्फ-हीलिंग, उन्नत शेड्यूलिंग, लोड बैलेंसिंग)।

हाई एवेलिबिलिटी की आवश्यकता वाले जटिल मल्टी-नोड डिप्लॉयमेंट्स।

पूरक: Terraform इन्फ्रास्ट्रक्चर (क्लस्टर) प्रोविजन करता है, जबकि Kubernetes एप्लिकेशन डिप्लॉयमेंट मैनेज करता है।

Ansible

कॉन्फ़िगरेशन मैनेजमेंट, पैकेज इंस्टॉलेशन, और सॉफ़्टवेयर सेटअप।

कंटेनरों के अंदर सॉफ़्टवेयर और कॉन्फ़िगरेशन का प्रबंधन।

पूरक: Terraform Docker कंटेनर बनाता है, और Ansible उनके अंदर चलने वाले एप्लिकेशनों को कॉन्फ़िगर करता है।

Docker Compose

सरल, व्यवहारिक प्रोजेक्ट-आधारित प्रबंधन।

सरल लोकल डेवलपमेंट वातावरण।

विकल्प: लोकल डेवलपमेंट के लिए Compose आसान है, लेकिन अलग-अलग वातावरणों में पुनरुत्पादनीय डिप्लॉयमेंट्स के लिए Terraform बेहतर है।

यदि आप Docker को बदलने के लिए किसी टूल की तलाश कर रहे हैं, तो हमारे शीर्ष Docker विकल्पों पर गाइड देखें।

निष्कर्ष

Docker को Terraform के लाइफसाइकल मैनेजमेंट के अधीन लाने से कंटेनर डिप्लॉयमेंट्स मैन्युअल प्रक्रियाओं से बदलकर पुनरुत्पादनीय, वर्शन-नियंत्रित इन्फ्रास्ट्रक्चर बन जाते हैं। इस ट्यूटोरियल में, मैंने प्रोवाइडर और एक सिंगल कंटेनर से शुरुआत करके, फिर क्रमिक रूप से नेटवर्किंग, स्टोरेज, वेरिएबल्स, मॉड्यूल्स, और ऑटोमेशन जोड़ते हुए चरण-दर-चरण एक संपूर्ण इन्फ्रास्ट्रक्चर कैसे बनता है, यह दिखाया।

मुख्य भेद यह है कि Terraform डिक्लेरेटिव कॉन्फ़िगरेशन के आधार पर संसाधनों का प्रोविज़निंग, निर्माण, अपडेट और विनाश संभालता है। स्वचालित स्केलिंग और सेल्फ-हीलिंग के साथ पूर्ण ऑर्केस्ट्रेशन के लिए Kubernetes या Docker Swarm जैसे टूल्स चाहिए। Terraform इन ऑर्केस्ट्रेटरों को प्रोविजन कर सकता है, लेकिन यह उनका स्थानापन्न नहीं है।

अगले चरणों के लिए, उन्नत संसाधन विकल्पों—जैसे Swarm के लिए Docker सेवाएँ, सीक्रेट मैनेजमेंट, और प्लगइन कॉन्फ़िगरेशन—को खोजने हेतु Docker प्रोवाइडर के लिए आधिकारिक Terraform Registry डाक्यूमेंटेशन देखें।

यदि आप कंटेनरों के साथ कुछ व्यावहारिक अनुभव पाना चाहते हैं, तो मैं हमारे इंटरैक्टिव Containerization and Virtualization with Docker and Kubernetes स्किल ट्रैक में दाखिला लेने की सिफारिश करता हूँ।

Terraform Docker FAQs

terraform destroy चलाते समय मैं Terraform को Docker इमेज हटाने से कैसे रोकूँ?

अपने docker_image संसाधन में keep_locally = true पैरामीटर का उपयोग करें। यह Terraform को बताता है कि इन्फ्रास्ट्रक्चर नष्ट करने के बाद भी इमेज को लोकली कैश्ड रखें, जो तब उपयोगी है जब कई कंटेनर एक ही इमेज साझा करते हैं या जब आप डिप्लॉयमेंट्स के बीच कैश्ड इमेजेज़ संरक्षित रखना चाहते हैं।

Terraform Cloud "Cannot connect to Docker daemon" त्रुटियाँ क्यों देता है?

डिफ़ॉल्ट रूप से, Terraform Cloud रिमोट एक्ज़ीक्यूशन मोड में चलता है, यानी कमांड्स Terraform Cloud के सर्वरों पर निष्पादित होते हैं जहाँ Docker उपलब्ध नहीं होता। आपको अपने वर्कस्पेस को लोकल एक्ज़ीक्यूशन मोड का उपयोग करने के लिए कॉन्फ़िगर करना होगा: जाएँ Settings > General > Execution Mode > Local। यह स्टेट को रिमोटली स्टोर करते हुए Terraform कमांड्स को आपकी लोकल मशीन पर चलाता है, जहाँ Docker सुलभ होता है।

मैं Terraform में डेटाबेस पासवर्ड जैसी संवेदनशील वैल्यूज़ कैसे प्रबंधित कर सकता/सकती हूँ?

वेरिएबल डेफिनिशन में sensitive = true का उपयोग करके वेरिएबल्स को संवेदनशील मार्क करें। Terraform Cloud के लिए, वर्कस्पेस UI में संवेदनशील वेरिएबल्स सेट करें और उन्हें "Sensitive" के रूप में चिह्नित करें। लोकल एक्ज़ीक्यूशन के लिए, TF_VAR_ प्रीफिक्स वाले एनवायरनमेंट वेरिएबल्स का उपयोग करें (उदा., export TF_VAR_db_password="password")। ध्यान दें कि वैल्यूज़ अभी भी terraform.tfstate में सादा पाठ में स्टोर होती हैं, इसलिए अपनी स्टेट फ़ाइल को हमेशा सुरक्षित रखें।

कंटेनर प्रबंधन के लिए Terraform और Docker Compose में क्या अंतर है?

Docker Compose स्टेट फ़ाइलें मेंटेन किए बिना प्रोजेक्ट-आधारित YAML दृष्टिकोण के माध्यम से कंटेनरों का प्रबंधन करता है। Terraform हर संसाधन को terraform.tfstate में रिकॉर्ड करता है, जिससे कॉन्फ़िगरेशन और वास्तविकता के बीच ड्रिफ्ट का पता लगाना संभव होता है। Terraform अलग-अलग वातावरणों में पुनरुत्पादनीय डिप्लॉयमेंट्स और अन्य इन्फ्रास्ट्रक्चर के साथ इंटीग्रेशन में उत्कृष्ट है, जबकि Docker Compose लोकल डेवलपमेंट के लिए सरल है। Terraform स्पष्ट स्टेट मैनेजमेंट और लाइफसाइकल कंट्रोल (plan/apply/destroy) प्रदान करता है।

मैं Docker कंटेनर की संसाधन सीमाएँ बिना त्रुटियों के कैसे अपडेट करूँ?

हालाँकि Docker CLI इन-प्लेस अपडेट्स का समर्थन करता है, Terraform Docker प्रोवाइडर अक्सर स्टेट सुसंगति सुनिश्चित करने के लिए संसाधन रिप्लेसमेंट को बाध्य करता है। इस रिप्लेसमेंट के दौरान डाउनटाइम से बचने के लिए, lifecycle { create_before_destroy = true } ब्लॉक जोड़ें। महत्वपूर्ण रूप से, आपको अपने संसाधन डिफिनिशन से फिक्स्ड name आर्ग्युमेंट भी हटाना होगा (या name_prefix का उपयोग करें)। यदि आप name = "web-server" जैसा फिक्स्ड नाम रखते हैं, तो नया कंटेनर पुराने को नष्ट होने से पहले "name already in use" त्रुटि के साथ स्टार्ट होने में विफल रहेगा।

Benito Martin

लेखक

Benito Martin

Martin Data Solutions के संस्थापक और एक फ्रीलांस डेटा वैज्ञानिक, ML और AI इंजीनियर के रूप में, मेरे पास रिग्रेशन, क्लासिफिकेशन, NLP, LLM, RAG, न्यूरल नेटवर्क्स, एंसेंबल मेथड्स, और कंप्यूटर विज़न में विविध अनुभव है।

  • AWS और GCP पर डेटा क्लीनिंग, एनालिटिक्स, मॉडलिंग और डिप्लॉयमेंट सहित कई एंड-टू-एंड ML प्रोजेक्ट सफलतापूर्वक विकसित किए, जिन्होंने प्रभावशाली और स्केलेबल समाधान प्रदान किए।
  • विभिन्न उद्योग उपयोग मामलों के लिए Streamlit और Gradio का उपयोग करके इंटरैक्टिव और स्केलेबल वेब एप्लिकेशन बनाए।
  • डेटा साइंस और एनालिटिक्स में छात्रों को पढ़ाया और मेंटर किया, और वैयक्तिकृत सीखने के तरीकों से उनके पेशेवर विकास को प्रोत्साहित किया।
  • एंटरप्राइज़ आवश्यकताओं के अनुरूप retrieval-augmented generation (RAG) एप्लिकेशन के लिए पाठ्य सामग्री डिज़ाइन की।
  • MLOps, वेक्टर डेटाबेस और LLMs जैसे विषयों पर उच्च-प्रभाव वाले AI और ML तकनीकी ब्लॉग लिखे, जिनसे उल्लेखनीय सहभागिता प्राप्त हुई।

हर प्रोजेक्ट में, मैं सॉफ्टवेयर इंजीनियरिंग और DevOps की नवीनतम प्रथाओं—जैसे CI/CD, कोड लिंटिंग, फॉर्मेटिंग, मॉडल मॉनिटरिंग, एक्सपेरिमेंट ट्रैकिंग, और मजबूत एरर हैंडलिंग—का पालन करता हूँ। मैं संपूर्ण समाधान प्रदान करने के लिए प्रतिबद्ध हूँ, जो डेटा इनसाइट्स को व्यावहारिक रणनीतियों में बदलते हैं, ताकि व्यवसाय बढ़ें और डेटा साइंस, मशीन लर्निंग और AI का अधिकतम लाभ उठा सकें।

विषय