CI သို့မဟုတ် စမ်းသပ်ပတ်ဝန်းကျင်အတွက် Docker-in-Docker အသုံးမပြုမီ သေချာစဉ်းစားပါ။

CI သို့မဟုတ် စမ်းသပ်ပတ်ဝန်းကျင်အတွက် Docker-in-Docker အသုံးမပြုမီ သေချာစဉ်းစားပါ။

Docker-in-Docker သည် ကွန်တိန်နာပုံများကို တည်ဆောက်ရန်အတွက် ကွန်တိန်နာအတွင်း လည်ပတ်နေသည့် virtualized Docker daemon ပတ်ဝန်းကျင်တစ်ခုဖြစ်သည်။ Docker-in-Docker ဖန်တီးခြင်း၏ အဓိကရည်ရွယ်ချက်မှာ Docker ကိုယ်တိုင်ဖွံ့ဖြိုးတိုးတက်စေရန် ကူညီပေးရန်ဖြစ်သည်။ Jenkins CI ကို run ဖို့ လူတော်တော်များများက အသုံးပြုကြပါတယ်။ ၎င်းသည် အစပိုင်းတွင် ပုံမှန်ဖြစ်ပုံရသော်လည်း Jenkins CI ကွန်တိန်နာတွင် Docker ကို ထည့်သွင်းခြင်းဖြင့် ရှောင်ရှားနိုင်သည့် ပြဿနာများ ပေါ်ပေါက်လာသည်။ ဒီဆောင်းပါးမှာ ဒီလိုလုပ်နည်းကို ပြောပြထားပါတယ်။ အသေးစိတ်အချက်အလက်များမပါဘဲ နောက်ဆုံးဖြေရှင်းချက်ကို စိတ်ဝင်စားပါက ဆောင်းပါး၏နောက်ဆုံးအပိုင်းဖြစ်သော “ပြဿနာဖြေရှင်းခြင်း” ကိုဖတ်ပါ။

CI သို့မဟုတ် စမ်းသပ်ပတ်ဝန်းကျင်အတွက် Docker-in-Docker အသုံးမပြုမီ သေချာစဉ်းစားပါ။

Docker-in-Docker- "ကောင်းပြီ"

လွန်ခဲ့တဲ့ နှစ်နှစ်ကျော်က ကျွန်တော် Docker မှာ တင်ခဲ့တယ်။ အလံ - အခွင့်ထူးခံပြီးရေးတယ်။ dind ၏ပထမဗားရှင်း. ရည်ရွယ်ချက်မှာ အမာခံအဖွဲ့ Docker ကို ပိုမိုမြန်ဆန်စွာ ဖွံ့ဖြိုးတိုးတက်စေရန် ကူညီပေးရန်ဖြစ်သည်။ Docker-in-Docker မတိုင်မီ၊ ပုံမှန်ဖွံ့ဖြိုးတိုးတက်မှုစက်ဝန်းသည် ဤကဲ့သို့ဖြစ်သည်-

  • ဟက်ခ်ဟက်ခ်;
  • တည်ဆောက်;
  • လည်ပတ်နေသော Docker daemon ကိုရပ်တန့်ခြင်း၊
  • Docker daemon အသစ်ကို စတင်ခြင်း
  • စမ်းသပ်ခြင်း;
  • သံသရာကိုပြန်လုပ်ပါ။

အကယ်၍ သင်သည် လှပ၍ မျိုးပွားနိုင်သော စည်းဝေးပွဲ (ဆိုလိုသည်မှာ ကွန်တိန်နာတစ်ခု) တွင် ပြုလုပ်လိုပါက ၎င်းသည် ပိုမိုရှုပ်ထွေးလာပါသည်။

  • ဟက်ခ်ဟက်ခ်;
  • Docker ၏ အလုပ်လုပ်ဆောင်မှု ဗားရှင်းတစ်ခု အလုပ်လုပ်နေကြောင်း သေချာပါစေ။
  • Docker အဟောင်းဖြင့် Docker အသစ်ကိုတည်ဆောက်ပါ။
  • Docker daemon ကိုရပ်တန့်ပါ။
  • Docker daemon အသစ်တစ်ခုစတင်ပါ။
  • စမ်းသပ်မှု;
  • Docker daemon အသစ်ကို ရပ်ပါ။
  • ထပ်လုပ်ပါ။

Docker-in-Docker ထွန်းကားလာသည်နှင့်အမျှ၊ လုပ်ငန်းစဉ်သည် ပိုမိုရိုးရှင်းလာပါသည်။

  • ဟက်ခ်ဟက်ခ်;
  • စည်းဝေးပွဲ + စင်မြင့်တစ်ခုတွင် စတင်ခြင်း၊
  • သံသရာကိုပြန်လုပ်ပါ။

ဒီနည်းက ပိုကောင်းတာမဟုတ်ဘူးလား။

CI သို့မဟုတ် စမ်းသပ်ပတ်ဝန်းကျင်အတွက် Docker-in-Docker အသုံးမပြုမီ သေချာစဉ်းစားပါ။

Docker-in-Docker- "ဆိုး"

သို့သော်၊ လူကြိုက်များသောယုံကြည်ချက်နှင့်ဆန့်ကျင်ဘက်၊ Docker-in-Docker သည် 100% ကြယ်များ၊ မြင်းများနှင့်ယူနီကွန်များမဟုတ်ပါ။ ကျွန်တော်ဆိုလိုသည်မှာ developer သည် သတိထားရမည့် ပြသနာများစွာ ရှိပါသည်။

၎င်းတို့ထဲမှ တစ်ခုမှာ AppArmor နှင့် SELinux ကဲ့သို့သော LSMs (Linux လုံခြုံရေး မော်ဂျူးများ) နှင့် သက်ဆိုင်သည်- ကွန်တိန်နာတစ်ခုအား လုပ်ဆောင်သည့်အခါ၊ "internal Docker" သည် "ပြင်ပ Docker" ကို ဆန့်ကျင် သို့မဟုတ် ရှုပ်ထွေးစေမည့် လုံခြုံရေးပရိုဖိုင်များကို အသုံးပြုရန် ကြိုးစားပေမည်။ ဤသည်မှာ -privileged အလံ၏မူလအကောင်အထည်ဖော်မှုကို ပေါင်းစည်းရန် ကြိုးပမ်းရာတွင် ဖြေရှင်းရန် အခက်ခဲဆုံးပြဿနာဖြစ်သည်။ ကျွန်ုပ်၏ပြောင်းလဲမှုများသည် အလုပ်ဖြစ်ခဲ့ပြီး စမ်းသပ်မှုများအားလုံးသည် ကျွန်ုပ်၏ Debian စက်နှင့် Ubuntu စမ်းသပ်မှု VM များတွင် အောင်မြင်သွားသော်လည်း ၎င်းတို့သည် Michael Crosby ၏စက်တွင် ပျက်ကျကာ လောင်ကျွမ်းသွားလိမ့်မည် (ကျွန်တော်မှတ်မိသလောက် သူ့တွင် Fedora ရှိသည်)။ ပြဿနာ၏အကြောင်းရင်းအတိအကျကို ကျွန်ုပ်မမှတ်မိနိုင်သော်လည်း Mike သည် SELINUX=enforce (ကျွန်တော် AppArmor ကိုအသုံးပြုသည်) နှင့်အလုပ်လုပ်သော ပညာရှိတစ်ဦးဖြစ်ပြီး၊ ကျွန်ုပ်၏ပြောင်းလဲမှုများသည် SELinux ပရိုဖိုင်များကို ထည့်သွင်းစဉ်းစားခြင်းမရှိသောကြောင့် ဖြစ်နိုင်ပါသည်။

Docker-in-Docker- "အဆိုး"

ဒုတိယပြဿနာမှာ Docker storage drivers ဖြစ်သည်။ သင် Docker-in-Docker ကိုဖွင့်သောအခါ၊ ပြင်ပ Docker သည် ပုံမှန်ဖိုင်စနစ် (EXT4၊ BTRFS သို့မဟုတ် သင့်တွင်ရှိသမျှ) ၏ထိပ်တွင်အလုပ်လုပ်ပြီး internal Docker သည် ကော်ပီ-ရေးသည့်စနစ်၏ထိပ်တွင်အလုပ်လုပ်သည် (AUFS၊ BTRFS၊ Device Mapper၊ စသည်တို့))၊ ပြင်ပ Docker ကို အသုံးပြုရန် ပြင်ဆင်ထားသည့်အရာပေါ်မူတည်၍)။ ၎င်းသည် အလုပ်မဖြစ်နိုင်သော ပေါင်းစပ်မှုများစွာကို ဖန်တီးပေးသည်။ ဥပမာအားဖြင့်၊ သင်သည် AUFS ၏ထိပ်တွင် AUFS ကို run နိုင်မည်မဟုတ်ပါ။

BTRFS ၏ထိပ်တွင် BTRFS ကို run ပါက၊ ၎င်းသည် အစပိုင်းတွင် အလုပ်လုပ်သင့်သည်၊ သို့သော် nested subvolumes များရှိနေသည်နှင့်၊ parent subvolume ကို ဖျက်ခြင်းမှာ မအောင်မြင်ပါ။ Device Mapper မော်ဂျူးတွင် namespace မရှိသောကြောင့် Docker ဖြစ်ရပ်များစွာသည် ၎င်းကို စက်တစ်ခုတည်းတွင် လုပ်ဆောင်နေပါက၊ ၎င်းတို့အားလုံးသည် ပုံများကို အချင်းချင်းနှင့် ကွန်တိန်နာ အရန်သိမ်းဆည်းသည့် စက်များတွင် မြင်နိုင် (လွှမ်းမိုးနိုင်) နိုင်မည်ဖြစ်သည်။ ဒါက မကောင်းဘူး။

ဤပြဿနာများကို ဖြေရှင်းရန် နည်းလမ်းများစွာရှိသည်။ ဥပမာအားဖြင့်၊ သင်သည် internal Docker တွင် AUFS ကိုအသုံးပြုလိုပါက /var/lib/docker ဖိုဒါကို volume တစ်ခုအဖြစ်ပြောင်းလိုက်ရုံဖြင့် သင်အဆင်ပြေမည်ဖြစ်သည်။ Docker သည် Device Mapper ပစ်မှတ်အမည်များသို့ အခြေခံအမည်နေရာအချို့ကို ထည့်သွင်းထားသောကြောင့် Docker ခေါ်ဆိုမှုအများအပြားသည် စက်တစ်ခုတည်းတွင် လုပ်ဆောင်နေပါက၊ ၎င်းတို့သည် တစ်ခုနှင့်တစ်ခု မတက်လှမ်းနိုင်အောင် ပြုလုပ်ထားသည်။

သို့သော်၊ ဤကဲ့သို့ထည့်သွင်းခြင်းသည် လုံးဝရိုးရှင်းသည်မဟုတ်ပါ၊ ဤအရာများမှ မြင်တွေ့နိုင်သည် ဆောင်းပါးများ GitHub ရှိ dind repository တွင်။

Docker-in-Docker- ပိုဆိုးလာပါတယ်။

build cache ကော ဘယ်လိုလဲ။ ဒါကလည်း တော်တော်ခက်ခဲနိုင်ပါတယ်။ လူတွေက "ငါ Docker-in-Docker ကို အသုံးပြုနေတယ်ဆိုရင် အရာအားလုံးကို ငါ့ရဲ့ Docker ထဲကို ပြန်ဆွဲထုတ်မယ့်အစား ငါ့ရဲ့ host မှာ တင်ထားတဲ့ ပုံတွေကို ဘယ်လိုသုံးရမလဲ" လို့ မေးလေ့ရှိတယ်။

အချို့သော စွန့်ဦးတီထွင်သူများသည် /var/lib/docker ကို host မှ Docker-in-Docker ကွန်တိန်နာတစ်ခုသို့ ချိတ်ဆက်ရန် ကြိုးစားခဲ့ကြသည်။ တစ်ခါတစ်ရံတွင် ၎င်းတို့သည် /var/lib/docker ကို ကွန်တိန်နာများစွာဖြင့် မျှဝေသည်။

CI သို့မဟုတ် စမ်းသပ်ပတ်ဝန်းကျင်အတွက် Docker-in-Docker အသုံးမပြုမီ သေချာစဉ်းစားပါ။
သင့်ဒေတာကို ပျက်စီးစေလိုပါသလား။ ဘာကြောင့်လဲဆိုတော့ ဒါက မင်းရဲ့ဒေတာကို ပျက်စီးစေမယ့်အရာပဲ။

Docker daemon သည် /var/lib/docker သို့ သီးသန့်ဝင်ရောက်ခွင့်ရှိရန် ရှင်းရှင်းလင်းလင်း ဒီဇိုင်းထုတ်ထားသည်။ ဤဖိုင်တွဲတွင်ရှိသော Docker ဖိုင်များကို "ထိ၊ ပုတ်ခြင်း သို့မဟုတ် ထုတ်ကုန်" အခြားမည်သည့်အရာမှ မဖြစ်သင့်ပါ။

ဘာကြောင့် ဒီလိုဖြစ်ရတာလဲ? အဘယ်ကြောင့်ဆိုသော်၎င်းသည် dotCloud ကိုတီထွင်နေစဉ်တွင်သင်ယူခဲ့သောအခက်ခဲဆုံးသင်ခန်းစာများထဲမှတစ်ခုဖြစ်သောကြောင့်ဖြစ်သည်။ dotCloud ကွန်တိန်နာအင်ဂျင်သည် /var/lib/dotcloud ကို တစ်ပြိုင်နက် ဝင်ရောက်အသုံးပြုသည့် လုပ်ငန်းစဉ်များစွာရှိခြင်းဖြင့် လည်ပတ်ခဲ့သည်။ အက်တမ်ဖိုင်ကို အစားထိုးခြင်း (နေရာတွင် တည်းဖြတ်ခြင်းအစား)၊ အကြံပေးချက်နှင့် မဖြစ်မနေသော့ခလောက်များပါသော ကုဒ်များကို ငြိမ့်ညောင်းအောင်ပြုလုပ်ခြင်းကဲ့သို့သော လိမ္မာပါးနပ်သောလှည့်ကွက်များ၊ SQLite နှင့် BDB ကဲ့သို့သော လုံခြုံသောစနစ်များနှင့် အခြားစမ်းသပ်မှုများသည် အမြဲတမ်း အလုပ်မဖြစ်ပါ။ နောက်ဆုံးတွင် Docker ဖြစ်လာသည့် ကျွန်ုပ်တို့၏ကွန်တိန်နာအင်ဂျင်ကို ပြန်လည်ဒီဇိုင်းဆွဲသည့်အခါ၊ ကြီးမားသော ဒီဇိုင်းဆုံးဖြတ်ချက်များထဲမှ တစ်ခုသည် container operations အားလုံးကို daemon တစ်ခုတည်းအောက်တွင် စုစည်းရန်ဖြစ်သည်။

ဖြစ်စဉ်များစွာနှင့် ခေတ်မီအပြိုင် ထိန်းချုပ်မှုများပါ၀င်သော ကောင်းမွန်သော၊ ယုံကြည်စိတ်ချရပြီး မြန်ဆန်သော အရာတစ်ခုကို ဖန်တီးရန် ကျွန်ုပ်ကို မမှားပါစေနှင့်။ သို့သော် Docker ကို တစ်ဦးတည်းသောကစားသမားအဖြစ် အသုံးပြု၍ ကုဒ်ရေးရန်နှင့် ထိန်းသိမ်းရန်မှာ ပိုမိုလွယ်ကူပြီး လွယ်ကူသည်ဟု ကျွန်ုပ်တို့ယူဆပါသည်။

ဆိုလိုသည်မှာ သင်သည် Docker instances အများအပြားကြား /var/lib/docker directory ကို မျှဝေပါက၊ သင်သည် ပြဿနာများရှိလိမ့်မည်ဖြစ်သည်။ ဟုတ်ပါတယ်၊ အထူးသဖြင့် စမ်းသပ်မှုရဲ့ အစောပိုင်းအဆင့်တွေမှာ ဒါက အလုပ်လုပ်နိုင်ပါတယ်။ "နားထောင်ပါ မေမေ၊ ကျွန်တော် ubuntu ကို docker တစ်ခုအနေနဲ့ run နိုင်တယ်!" ဒါပေမယ့် မတူညီတဲ့ပုံနှစ်ခုကနေ တူညီတဲ့ပုံတစ်ပုံကို ဆွဲထုတ်တာလိုမျိုး ပိုရှုပ်ထွေးတဲ့အရာတစ်ခုကို ကြိုးစားကြည့်ပါ၊ ကမ္ဘာကြီး ပူလောင်နေတာကို သင်တွေ့ရမှာပါ။

ဆိုလိုသည်မှာ သင်၏ CI စနစ်သည် တည်ဆောက်ပြီး ပြန်လည်တည်ဆောက်ပါက၊ သင်၏ Docker-in-Docker ကွန်တိန်နာကို ပြန်လည်စတင်သည့်အခါတိုင်း၊ သင်သည် ၎င်း၏ cache ထဲသို့ နူကေးတစ်စက်ကို စွန့်ပစ်ရန် အန္တရာယ်ရှိသည်။ ဒါ လုံးဝ မမိုက်ဘူး!

addressing

ခြေတစ်လှမ်းဆုတ်ကြရအောင်။ Docker-in-Docker ကို အမှန်တကယ် လိုအပ်ပါသလား သို့မဟုတ် Docker ကို လည်ပတ်စေပြီး CI စနစ်ကိုယ်တိုင် ကွန်တိန်နာတစ်ခုထဲတွင် ရှိနေစဉ် သင့် CI စနစ်မှ ကွန်တိန်နာများနှင့် ပုံများကို တည်ဆောက်ကာ လုပ်ဆောင်နိုင်လိုပါသလား။

လူအများစုသည် နောက်ဆုံးရွေးချယ်မှုကို လိုချင်ကြသည်၊ ဆိုလိုသည်မှာ Jenkins ကဲ့သို့သော CI စနစ်တစ်ခုကို ကွန်တိန်နာများလည်ပတ်နိုင်စေရန် လိုလားပါသည်။ ၎င်းကိုပြုလုပ်ရန် အလွယ်ကူဆုံးနည်းလမ်းမှာ သင်၏ CI ကွန်တိန်နာထဲသို့ Docker socket တစ်ခုကို ထည့်သွင်းပြီး -v အလံနှင့် ချိတ်ဆက်ရန်ဖြစ်သည်။

ရိုးရှင်းစွာပြောရလျှင်၊ သင်သည်သင်၏ CI ကွန်တိန်နာ (Jenkins သို့မဟုတ် အခြား) ကိုအသုံးပြုသောအခါ Docker-in-Docker နှင့် တစ်စုံတစ်ခုကို ဟက်ခ်လုပ်မည့်အစား ၎င်းကို လိုင်းဖြင့်စတင်ပါ။

docker run -v /var/run/docker.sock:/var/run/docker.sock ...

ဤကွန်တိန်နာသည် ယခု Docker socket သို့ ဝင်ရောက်နိုင်ပြီဖြစ်သောကြောင့် ကွန်တိန်နာများကို ဖွင့်နိုင်မည်ဖြစ်သည်။ "ကလေး" ကွန်တိန်နာများကိုဖွင့်မည့်အစား၊ ၎င်းသည် "ညီအကို" ကွန်တိန်နာများကိုဖွင့်လိမ့်မည်။

တရားဝင် docker ပုံ (Docker binary ပါ ၀ င်သောတရားဝင် docker ပုံကို အသုံးပြု၍ စမ်းကြည့်ပါ)

docker run -v /var/run/docker.sock:/var/run/docker.sock 
           -ti docker

၎င်းသည် Docker-in-Docker နှင့်တူသော်လည်း ၎င်းသည် Docker-in-Docker မဟုတ်ပါ။ ဤကွန်တိန်နာသည် နောက်ထပ်ကွန်တိန်နာများကို ဖန်တီးသည့်အခါ ၎င်းတို့ကို ထိပ်တန်းအဆင့် Docker တွင် ဖန်တီးမည်ဖြစ်သည်။ nesting ၏ ဘေးထွက်ဆိုးကျိုးများကို သင်ခံစားရမည်မဟုတ်ပါ၊ ခေါ်ဆိုမှုများစွာတွင် တပ်ဆင်ရေးကက်ရှ်ကို မျှဝေပါမည်။

မှတ်ချက်- ဤဆောင်းပါး၏ ယခင်ဗားရှင်းများသည် Docker binary ကို host မှ container သို့ ချိတ်ဆက်ရန် အကြံပြုထားသည်။ Docker အင်ဂျင်သည် static သို့မဟုတ် static libraries များကို မဖုံးလွှမ်းတော့ဘဲ ယခုအခါ ၎င်းသည် စိတ်မချရဖြစ်လာသည်။

ထို့ကြောင့် သင်သည် Jenkins CI မှ Docker ကိုအသုံးပြုလိုပါက၊ သင့်တွင် ရွေးချယ်စရာ 2 ခုရှိသည်။
အခြေခံရုပ်ပုံထုပ်ပိုးမှုစနစ် (ဆိုလိုသည်မှာ သင့်ပုံသည် Debian ကိုအခြေခံပါက Docker API ကိုအသုံးပြု၍ .deb ပက်ကေ့ဂျ်များကိုသုံးပါ) ကိုအသုံးပြု၍ Docker CLI ကိုထည့်သွင်းခြင်း။

ကြော်ငြာအချို့ 🙂

ကျွန်ုပ်တို့နှင့်အတူရှိနေသည့်အတွက် ကျေးဇူးတင်ပါသည်။ ကျွန်ုပ်တို့၏ဆောင်းပါးများကို သင်နှစ်သက်ပါသလား။ ပိုစိတ်ဝင်စားစရာကောင်းတဲ့ အကြောင်းအရာတွေကို ကြည့်ချင်ပါသလား။ မှာယူမှုတစ်ခုပြုလုပ်ခြင်း သို့မဟုတ် သူငယ်ချင်းများကို အကြံပြုခြင်းဖြင့် ကျွန်ုပ်တို့အား ပံ့ပိုးကူညီပါ၊ $4.99 မှ developer များအတွက် cloud VPS, မင်းအတွက် ငါတို့က တီထွင်ထားတဲ့ entry-level server တွေရဲ့ ထူးခြားတဲ့ analogue တစ်ခု။ VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps သို့မဟုတ် $19 မှ ဆာဗာတစ်ခုမျှဝေပုံနှင့်ပတ်သက်သော အမှန်တရားတစ်ခုလုံး။ (RAID1 နှင့် RAID10၊ 24 cores အထိနှင့် 40GB DDR4 အထိ)။

အမ်စတာဒမ်ရှိ Equinix Tier IV ဒေတာစင်တာတွင် Dell R730xd သည် ၂ ဆ စျေးသက်သာသည်။ ဒီမှာသာ 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV ကို $199 မှ နယ်သာလန်မှာ Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - $99 မှ။ အကြောင်းဖတ်ပါ။ Infrastructure Corp ကို ဘယ်လိုတည်ဆောက်မလဲ။ တစ်ပြားတစ်ချပ်အတွက် ယူရို ၉၀၀၀ တန် Dell R730xd E5-2650 v4 ဆာဗာများကို အသုံးပြုခြင်း။

source: www.habr.com

မှတ်ချက် Add