شبکه در docker

مقدمهدر ادامه سری مطالب داکر قرار بود که شبکه‌ی داکر رو هم مورد بررسی قرار بدیم. فهمیدن نحوه کار شبکه‌ی داکر به ما کمک می‌کنه تا بدونیم که حامل‌ها(container) چطور با هم ارتباط می‌گیرند. تو این مطلب سعی می‌کنیم این موضوع رو بررسی و نحوه کار اون رو بفهمیم.اگر مطالب قبلی رو نخوندین، بد نیست یک نگاهی به اون‌ها هم بندازید(البته پیش نیاز این مطلب نیستند). https://vrgl.ir/n3zr0 https://vrgl.ir/srZqV به طور کلی داکر ۵ نوع(یا به تفسیر دیگه ۶ نوع) شبکه رو می‌تونه داشته باشد، که عبارت‌اند از:bridge(پیشفرض)hostoverlaymacvlannonePlugin(اون به عبارتی که گفتم این مورده)اینکه هر کدوم از این موارد کی استفاده ‌می‌شوند و چه کاربردی دارند، موضوعیه که تو ادامه با هم بررسی می‌کنیم.Bridgeاگر با تکنولوژی‌های مجازی‌ساز(vmware, kvm, ...) کار کرده باشید، باید بهتون بگم شبکه داکر تو حالت bridge با مجازی‌سازها متفاوته! ما تو مجازی‌سازها وقتی از bridge استفاده می‌کنیم، یک IP در رنج همون IP ماشین میزبان(Host) بهمون داده میشه(شاید یک تکنولوژی وجود داشته باشه که این‌طوری نباشه، اولا اینکه موارد معروف رو مدنظرم بود و دوما اینکه سواد من در این حده :) ). به عنوان مثال اگر ماشین میزبان ما تو رنج 172.19.0.0/16 باشه، ماشین مجازی(vm) ما هم تو همون رنج یک ‌IP رو می‌گیره و تو شبکه هم قابل دسترسیه، در واقع مستقیم از interface شبکه‌مون استفاده می‌کنه. اما داکر این طوری نیست! داکر میاد یک شبکه با رنجی که خودش مشخص می‌کنه، می‌سازه و حامل‌های مارو تو اون رنج IPدهی می‌کنه. دلیل این تفاوت هم تو اینه که داکر، برای ساخت bridge از software device استفاده می‌کنه. این مورد باعث ایزوله سازی این شبکه میشه. برای اینکه لیست شبکه‌های داکر رو ببینیم کافیه دستور زیر رو اجرا کنیم:docker network lsکه خروجی اون یک همچین چیزی میشه:خروجی دستور بالاداکر این سه مورد به صورت پیشفرض خودش می‌سازه.حالا اگر بخوایم دامنه IPهای خودمون رو بدونیم کافیه دستور زیر رو اجرا کنیم:docker network inspect <ID_OF_NETWORD___OR___NAME_OF_NETWORK>توی خروجی این دستور تو بخش IPAM و داخل اون بخش Config می‌تونیم دامنه رو ببینیم:بخشی از خروجی دستور بالااما bridge کی استفاده میشه؟ طبق گفته خود داکر اکثر مواقعی چندتا حامل standalone داریم و این‌ حامل‌ها با هم دیگه ارتباط دارند از bridge استفاده می‌کنیم. مثلا docker-compse یک مثال بسیار خوب برای این مورده. میایم یک شبکه برای اون چندتا حاملی که می‌خوایم با docker-compose بیاریم بالا می‌سازیم(حتی می‌تونیم شبکه جدا نسازیم) و این حامل‌ها می‌تونند با اسم با هم‌دیگه در ارتباط باشند.نکته خوب ماجرا اینکه ما می‌تونیم شبکه bridge خودمون رو بسازیم(حتی با دامنه مدنظر خودمون). چرا این خوبه؟ فرض کنید که چند دسته حامل داریم(هر کدوم متعلق به یک سرویس) و نمی‌خوایم این دسته‌ها بتونند با هم دیگه ارتباط داشته باشند. داکر به حامل‌هایی که تو یک شبکه نباشند& اجازه ارتباط با همدیگه رو نمیده.برای اینکه موضوع شفاف‌تر بشه. بیاین یک شبکه bridge رو بسازیم:docker network create <NAME_OF_NETWORK>نکته: از اونجایی که دایور پیشفرض داکر bridge هستش، دیگه نگفتیم که bridge می‌خوایم. دامنه IP رو هم می‌تونستیم مشخص کنیم و ... . برای اینکه بدونیم دستور create چه گزینه‌هایی داره از این دستور استفاده می‌کنیم:docker network create --helpساخت یک شبکه bridgeحالا اگر بخوایم که یک حامل توی این شبکه باشه کافیه:docker create --network vahid -p 8080:80 --name my-container nginx:latestاگر هم یک حامل در حال اجرا داریم می‌تونیم به این شکل عمل کنیم:docker network connect vahid my_containerقطع ارتباط(disconnect) هم داریم:docker network disconnect vahid my_containerتفاوت شبکه ایجاد شده توسط کاربرگفتیم که به صورت پیشفرض داکر یک شبکه bridge رو اول کار میسازه که این شبکه با شبکه bridge که ما بعدا می‌سازیم، تفاوت‌هایی داره. این تفاوت‌ها عبارت‌اند از:امکان وصل شدن و یا قطع ارتباط در لحظه(on the fly) به شبکه غیرپیشفرض همون طور که مثالش رو بالا داشتیم، خیلی راحت می‌تونیم به یک شبکه که خودمون ساختیم، وصل و یا از اون قطع بشیم. در حالی که در شبکه پیشفرض برای خارج شدن، نیازه تا حامل stop بشه.به اشتراک گذاشتن env variablesشبکه پیشفرض امکان به اشتراک گذاری این مقادیر بین دوتا حامل رو به ما میده(استفاده از فلگ --link)، در حالی که برای شبکه‌هایی که خودمون ساختیم این طوری نیست. هرچند که میشه برای این موضوع روش‌های بهتری نسبت به --link رو استفاده کرد.امکان تعریف دامنهدامنه IP که به ما اختصاص داده میشه توی شبکه پیشفرض دست ما نیست و خود داکر مشخص می‌کنه در حالی که می‌تونیم یک شبکه بسازیم و دامنه IP مدنظر خودمون رو بهش اختصاص بدیم. البته این مورد رو هم میشه با فایل daemon.json حل کرد. برای این کار:$ sudo vim /etc/docker/daemon.jsonبعد محتویات زیر رو میزاریم(طبیعتا اگر تنظیمات دیگه‌ای هم داشته باشیم، این موارد میان بغل اونا):{ &quotbip&quot: &quot192.168.1.5/24&quot, &quotfixed-cidr&quot: &quot192.168.1.5/25&quot, &quotfixed-cidr-v6&quot: &quot2001:db8::/64&quot, &quotmtu&quot: 1500, &quotdefault-gateway&quot: &quot10.20.1.1&quot, &quotdefault-gateway-v6&quot: &quot2001:db8:abcd::89&quot, &quotdns&quot: [&quot10.20.1.2&quot,&quot10.20.1.3&quot] }در نهایت سرویس داکر رو ریستارت کنید.یک نکته دیگه هم اینکه داکر میگه شبکه غیرپیشفرض(شبکه‌ای که کاربر می‌سازه) باعث ایزوله سازی بهتری میشه.چطور؟ اگر برای یک حامل شبکه رو مشخص نکنیم، از شبکه پیشفرض استفاده خواهد کرد. این موضوع می‌تونه باعث بشه، حامل‌هایی که نمی‌خوایم همدیگه رو ببینند، این امکان رو داشته باشند. پس روش مهندسی‌تر اینکه شبکه خودمون رو بسازیم و حامل رو موقع ساخت با اون شبکه بیاریم بالا تا دسترسی ناخواسته بهش وجود نداشته باشه.https://memegenerator.net/img/instances/81395542/users-cant-submit-jira-tickets-if-the-network-is-down.jpgHostتو این مورد خیلی ساده ایزوله‌سازی‌ای وجود نداره و حامل مستقیم از به طور مستقیم از شبکه ماشین میزبان استفاده می‌کنه. در واقع حامل از خودش IP نداره و فلگ --publish یا -p هم درنظر گرفته نمیشه. مثلا یک حامل nginx داشته باشیم که شبکه ش از نوع Host باشه تنها کافیه آدرس اون ماشین رو در شبکه بزنیم تا درخواست برسه به دست حامل ما.این نوع شبکه در ماشین‌های میزبان با سیستم‌عامل مک و ویندوز کار نمی‌کند.شبکه Host برای مواقعی بخوایم یک طیف وسیعی از درگاه‌ها(port) رو داشته باشه ایده‌ی خوبیه(از لحاظ پرفورمنسی).Overlayاین نوع شبکه چیز باحالیه! ما می‌تونیم به کمک overlay چندتا docker daemon رو بهم دیگه وصل کنیم. این شبکه باعث میشه بتونیم دو حامل داشته باشیم که توی دوتا docker daemon جدا با همدیگه ارتباط داشته باشند یا سرویس‌های swarm بتونند با هم حرف بزنند یا یک حامل با swarm حرف بزنه. حتی این ارتباط میتونه به کمک رمزنگاری امن هم بشه.با یک مثال موضوع رو ادامه بدیم. یک شبکه از نوع overlay می‌سازیم:docker network create -d overlay vahidالبته فلگ‌های --encrypted و --attachable هم زیاد استفاده می‌شوند. یکی برای فعال‌سازی رمز نگاری ارتباطات و یکی هم برای امکان ارتباط یک حامل با سرویس swarm.اگر بخوایم یک عکس کلی از این شبکه داشته باشیم، این رو خواهیم داشت:https://medium.com/@tukai.anirban/container-networking-overlay-networks-b712d6ddfb67اینکه این شبکه چطوری کار میکنه، بحث مسیریابی(routing) چطوریه و کلا جنبه‌های مختلف اون، علاوه بر اینکه برای توضیحش سواد فنی خوبی می‌خواد(که من ندارمش)، باعث طولانی‌تر شدن مطلب میشه(مطلب طولانی مخاطب رو پس می‌زنه). ولی به واقع ارزش خوندن و فهمیدنش رو داره، مخصوصا اگر با swarm کار می‌کنید. طبیعتا گوگل بهترین گزینه ممکن هستش ولی منم دوتا لینک میزارم.لینک ۱(مستندات خود داکر درباره شبکه overlay) و لینک ۲. اگر کسی لینک خوبی سراغ داشت لطفا به اشتراک بزاره. :)macvlanتو این مورد، ما به حامل‌های خودمون یک MAC Address رو اختصاص می‌دیم که باعث میشه حامل توی شبکه به عنوان یک دستگاه شناخته بشه. سرویس داکر هم عملیات مسیریابی(routing) رو بر اساس مک آدرس انجام میده. به گفته خود داکر این نوع شبکه، گاها می‌تونه به عنوان بهترین انتخاب برای نرم‌افزارهای قدیمی که انتظار دارند، مستقیم به شبکه فیزیکی(physical network) وصل شوند، باشد.نکته اینکه برای این شبکه، تجهیزات شبکه ما باید توانایی تخصیص چندین مک آدرس رو داشته باشد(اصطلاحا بهش promiscuous mode میگن).نکته دوم هم اینکه این مورد می‌تونه باعث مشکلاتی(VLAN spread, ip exhaustion) توی شبکه‌هایی بشه که تعداد زیادی مک آدرس یکتا(unique) تو خودشون دارند.باز هم به خاطر اینکه مطلب طولانی نشه توضیح بیشتری نمیدم و شما رو به این لینک(از مستندات خود داکر) ارجاع میدم. توصیه می‌کنم یک نگاهی بندازین چیزای جالبی دارد.noneبحث شبکه رو برای حامل‌مون کلا غیرفعال می‌کنه(تامام). برای اینکه این مورد رو فعال کنیم این طوری می‌تونیم عمل کنیم:docker run --network none --name my-container nginx:latestPluginمی‌تونیم یک افزونه(plugin) third-party رو نصب و استفاده کنیم. برای دیدن نمونه هم می‌تونین که اینجا(داکر هاب) رو یک نگاه بندازید. شاید برای جاهایی که شبکه‌شون رو به صورت خاصی پیاده‌سازی کردند، استفاده بشه.جمع‌بندیاگر بخواهیم به صورت خیلی خلاصه این موارد رو جمع‌بندی کنیم، خود مستندات داکر خیلی خوب گفته این موارد رو، پس این شما و این خلاصه چیزهای گفته شده:User-defined bridge networks are best when you need multiple containers to communicate on the same Docker host.Host networks are best when the network stack should not be isolated from the Docker host, but you want other aspects of the container to be isolated.Overlay networks are best when you need containers running on different Docker hosts to communicate, or when multiple applications work together using swarm services.Macvlan networks are best when you are migrating from a VM setup or need your containers to look like physical hosts on your network, each with a unique MAC address.Third-party network plugins allow you to integrate Docker with specialized network stacks.میدونم که خیلی سریع و سطحی گفته شد، سوای بحث اینکه مطلب خیلی طولانی میشد(همین مطلب ۸ دقیقه اینا شد!)، توضیح در همین حد هم، کار خیلی‌ها(اون‌هایی که کار زیرساختی انجام نمیدن) رو راه میندازه!همین! لبخند بزنین لطفا :)منابع:https://docs.docker.com/network/