در ادامه سری مطالب داکر قرار بود که شبکهی داکر رو هم مورد بررسی قرار بدیم. فهمیدن نحوه کار شبکهی داکر به ما کمک میکنه تا بدونیم که حاملها(container) چطور با هم ارتباط میگیرند. تو این مطلب سعی میکنیم این موضوع رو بررسی و نحوه کار اون رو بفهمیم.
اگر مطالب قبلی رو نخوندین، بد نیست یک نگاهی به اونها هم بندازید(البته پیش نیاز این مطلب نیستند).
به طور کلی داکر ۵ نوع(یا به تفسیر دیگه ۶ نوع) شبکه رو میتونه داشته باشد، که عبارتاند از:
اینکه هر کدوم از این موارد کی استفاده میشوند و چه کاربردی دارند، موضوعیه که تو ادامه با هم بررسی میکنیم.
اگر با تکنولوژیهای مجازیساز(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
حالا اگر بخوایم که یک حامل توی این شبکه باشه کافیه:
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 که ما بعدا میسازیم، تفاوتهایی داره. این تفاوتها عبارتاند از:
همون طور که مثالش رو بالا داشتیم، خیلی راحت میتونیم به یک شبکه که خودمون ساختیم، وصل و یا از اون قطع بشیم. در حالی که در شبکه پیشفرض برای خارج شدن، نیازه تا حامل stop بشه.
شبکه پیشفرض امکان به اشتراک گذاری این مقادیر بین دوتا حامل رو به ما میده(استفاده از فلگ --link)، در حالی که برای شبکههایی که خودمون ساختیم این طوری نیست. هرچند که میشه برای این موضوع روشهای بهتری نسبت به --link رو استفاده کرد.
$ sudo vim /etc/docker/daemon.json
بعد محتویات زیر رو میزاریم(طبیعتا اگر تنظیمات دیگهای هم داشته باشیم، این موارد میان بغل اونا):
{ "bip": "192.168.1.5/24", "fixed-cidr": "192.168.1.5/25", "fixed-cidr-v6": "2001:db8::/64", "mtu": 1500, "default-gateway": "10.20.1.1", "default-gateway-v6": "2001:db8:abcd::89", "dns": ["10.20.1.2","10.20.1.3"] }
در نهایت سرویس داکر رو ریستارت کنید.
یک نکته دیگه هم اینکه داکر میگه شبکه غیرپیشفرض(شبکهای که کاربر میسازه) باعث ایزوله سازی بهتری میشه.چطور؟ اگر برای یک حامل شبکه رو مشخص نکنیم، از شبکه پیشفرض استفاده خواهد کرد. این موضوع میتونه باعث بشه، حاملهایی که نمیخوایم همدیگه رو ببینند، این امکان رو داشته باشند. پس روش مهندسیتر اینکه شبکه خودمون رو بسازیم و حامل رو موقع ساخت با اون شبکه بیاریم بالا تا دسترسی ناخواسته بهش وجود نداشته باشه.
تو این مورد خیلی ساده ایزولهسازیای وجود نداره و حامل مستقیم از به طور مستقیم از شبکه ماشین میزبان استفاده میکنه. در واقع حامل از خودش IP نداره و فلگ --publish یا -p هم درنظر گرفته نمیشه. مثلا یک حامل nginx داشته باشیم که شبکه ش از نوع Host باشه تنها کافیه آدرس اون ماشین رو در شبکه بزنیم تا درخواست برسه به دست حامل ما.
این نوع شبکه در ماشینهای میزبان با سیستمعامل مک و ویندوز کار نمیکند.
شبکه Host برای مواقعی بخوایم یک طیف وسیعی از درگاهها(port) رو داشته باشه ایدهی خوبیه(از لحاظ پرفورمنسی).
این نوع شبکه چیز باحالیه! ما میتونیم به کمک overlay چندتا docker daemon رو بهم دیگه وصل کنیم. این شبکه باعث میشه بتونیم دو حامل داشته باشیم که توی دوتا docker daemon جدا با همدیگه ارتباط داشته باشند یا سرویسهای swarm بتونند با هم حرف بزنند یا یک حامل با swarm حرف بزنه. حتی این ارتباط میتونه به کمک رمزنگاری امن هم بشه.
با یک مثال موضوع رو ادامه بدیم. یک شبکه از نوع overlay میسازیم:
docker network create -d overlay vahid
البته فلگهای --encrypted و --attachable هم زیاد استفاده میشوند. یکی برای فعالسازی رمز نگاری ارتباطات و یکی هم برای امکان ارتباط یک حامل با سرویس swarm.
اگر بخوایم یک عکس کلی از این شبکه داشته باشیم، این رو خواهیم داشت:
اینکه این شبکه چطوری کار میکنه، بحث مسیریابی(routing) چطوریه و کلا جنبههای مختلف اون، علاوه بر اینکه برای توضیحش سواد فنی خوبی میخواد(که من ندارمش)، باعث طولانیتر شدن مطلب میشه(مطلب طولانی مخاطب رو پس میزنه). ولی به واقع ارزش خوندن و فهمیدنش رو داره، مخصوصا اگر با swarm کار میکنید. طبیعتا گوگل بهترین گزینه ممکن هستش ولی منم دوتا لینک میزارم.
لینک ۱(مستندات خود داکر درباره شبکه overlay) و لینک ۲. اگر کسی لینک خوبی سراغ داشت لطفا به اشتراک بزاره. :)
تو این مورد، ما به حاملهای خودمون یک MAC Address رو اختصاص میدیم که باعث میشه حامل توی شبکه به عنوان یک دستگاه شناخته بشه. سرویس داکر هم عملیات مسیریابی(routing) رو بر اساس مک آدرس انجام میده. به گفته خود داکر این نوع شبکه، گاها میتونه به عنوان بهترین انتخاب برای نرمافزارهای قدیمی که انتظار دارند، مستقیم به شبکه فیزیکی(physical network) وصل شوند، باشد.
نکته اینکه برای این شبکه، تجهیزات شبکه ما باید توانایی تخصیص چندین مک آدرس رو داشته باشد(اصطلاحا بهش promiscuous mode میگن).
نکته دوم هم اینکه این مورد میتونه باعث مشکلاتی(VLAN spread, ip exhaustion) توی شبکههایی بشه که تعداد زیادی مک آدرس یکتا(unique) تو خودشون دارند.
باز هم به خاطر اینکه مطلب طولانی نشه توضیح بیشتری نمیدم و شما رو به این لینک(از مستندات خود داکر) ارجاع میدم. توصیه میکنم یک نگاهی بندازین چیزای جالبی دارد.
بحث شبکه رو برای حاملمون کلا غیرفعال میکنه(تامام).
برای اینکه این مورد رو فعال کنیم این طوری میتونیم عمل کنیم:
docker run --network none --name my-container nginx:latest
میتونیم یک افزونه(plugin) third-party رو نصب و استفاده کنیم. برای دیدن نمونه هم میتونین که اینجا(داکر هاب) رو یک نگاه بندازید. شاید برای جاهایی که شبکهشون رو به صورت خاصی پیادهسازی کردند، استفاده بشه.
اگر بخواهیم به صورت خیلی خلاصه این موارد رو جمعبندی کنیم، خود مستندات داکر خیلی خوب گفته این موارد رو، پس این شما و این خلاصه چیزهای گفته شده:
میدونم که خیلی سریع و سطحی گفته شد، سوای بحث اینکه مطلب خیلی طولانی میشد(همین مطلب ۸ دقیقه اینا شد!)، توضیح در همین حد هم، کار خیلیها(اونهایی که کار زیرساختی انجام نمیدن) رو راه میندازه!
همین! لبخند بزنین لطفا :)