همانطور که در مقالههای پیشین نیز گفتیم Docker Engine یک ساختار Client-Server دارد که وظیفۀ آن مدیریت ایمیجها، کانتینرها، فضاهای ذخیرهسازی و همچنین شبکهها را بر عهده دارد.
نگاهی به ورژنهای قدیمی:
در روزهای اول داکر این پلتفورم برروی ساختاری monolithic پیادهسازی شده بود. اما بعدها داکر به سمت ساختار microservice میل کرد و بخش های دیگری از درون Docker Daemon بوجود آمدند. که در این مقاله با تمامی آنها آشنا میشویم. در قدیم اجزای docker engine شامل Docker Daemon و LXC بودند و همچنین داکر دیمن از ساختار Monolithic برخوردار بود. در اوایل داکر به تنهایی قابلیت ارتباط مستقیم با کرنل لینوکس را نداشت و اگر یک کانتینر ایجاد میشد از LXC کمک گرفته میشد. به شکلی که:
Docker Daemon درخواستی را به سمت LXC میفرستاد که تکنولوژی کانتینریشن خود لینوکس بود و قاعدتاً تعامل با کرنل را بلد بود. در واقع درخواستهای dockerd به LXC داده میشود و به کمک LXC درخواستها به کرنل داده شده. سپس کرنل پاسخ را به LXC داده و در نهایت جواب به دست داکر میرسد و کانتینر ساخته میشد.
آشنایی با Cgroups:
هنگامی که ما یک عملیات را در لینوکس اجرا میکنیم با استفاده از مکانیزم Cgroups میتوانیم بر روی منایع استفاده شده توسط یک عملیات(process) محدودیتگذاری کنیم. در واقع هنگامی که یک کانتینر ساخته میشود وظیفۀ اختصاص منابع به کانتینر به دست Cgroups انجام میشود. داکر از Cgroups که در داخل کرنل لینوکس است درخواست میکند که مقدار منابعی مثل CPU و Memory را به کانتینر اختصاص دهد.
آشنایی با Namespace:
یک مکانیزم در کرنل لینوکس میباشد که تعیین میکند هر گروه چه میزان دید و دسترسی به سیستم داشته باشند. برای مثال عملیات مورد نظر شما آیا بتواند یکی از انیترفیسهای شبکۀ شما را ببیند یا خیر. در داکر نیز هنگامی که شما یک کانتینر را بالا میآورید؛ به Namespace درخواستی داده میشود که کانتینر مورد نظر باید چه بخشی از سیستم را ببیند و چه بخشی را اجازۀ دسترسی به آن را نخواهد داشت. پس میتوان گفت یکی از عوامل مؤثر در بحث Isolation کانتینرهای داکر، Namespace است.
پروژۀ Libcontainer:
بعدها به دلیل میل شدید داکر به گسترش قلمروی خود تا به سیستمعاملهای دیگر و همچنین محدود بودن LXC به لینوکس. بدین شکل Docker.Inc پروژۀ بزرگی تحت عنوان Libcontainer را آغاز کرد تا به جای استفاده از LXC جهت ارتباط با کرنل، از جایگزینی به نام Libcontainer استفاده شود.
تغییر ساختار معماری داکر از monolithic به microservice:
داکر به دلیل معایب یک معماری Monolithic تصمیم گرفت که معماری خود را به معماری microservice تغییر دهد. در داکر کلاینت ما کامندها را وارد میکنیم و این درخواستها از طریق REST API به دست Docker Daemon میرسند. در قدیم، به دلیل ساختار monolithic تمام فرآیندهای کانتینرسازی به دست خود داکر دیمن انجام میشد. بعد از تصمیم برای ساخت یک معماری microservice یک سری از اجزای داکر دیمن از این بخش بیرون آمدند و موجودیتی مستقل به خود گرفتند. از اینجا به بعد داکر دیمن درخواست خود را بهسمت بخشی جدید به نام Containerd میفرستد.
آشنایی با Containerd:
وظیفۀ این بخش مدیریت وضعیت (state) و چرخۀ زندگی کانتینر است. اما باز هم ما از ساخت داکر صحبتی نکردیم! به این دلیل که وظیفۀ ساختن کانتینر به عهدۀ بخش دیگری است.
آشنایی با runc:
وظیفۀ ساخت کانتینرها به دست این بخش یعنی runc رقم میخورد. نکتهای که باید مدنظر داشته باشید این است که از لحظۀ شروع ساخت کانتینر تا هنگامی که کانتینر آماده شود؛ این بخش (runc) والد (parent) کانتینر شما میباشد. بعد از ساخت کانتینر و اتمام فرآیند کانتینرسازی، runc به عنوان والد کانتینر تازه ساخته شده، خارج میشود و موجود دیگری به نام shim والد کانتینر شما تا زمان مرگ این کانتینر خواهد بود.
آشنایی با shim:
این بخش به غیر از اینکه والد کانتینر شما است وظایف دیگری مانند مدیریت STDIN و STDOUT شما و تحویل گزارشاتی از وضعیت کانتینر شما به داکر دیمن را بر عهده دارد. بدین طریق داکر دیمن از وضعیت کانتینر شما همیشه با خبر و آگاه خواهد بود.
امیدوارم که از این مقاله لذت برده باشید. برای دسترسی به مقالههای قبلی برروی این قسمت <<کلیک>> کنید. همچنین میتوانید از این قسمت برای دسترسی به ویکی داکر استفاده کنید.