داکر یک سکوی نرم افزاری است که با استفاده از آن فرآیند ساخت، اجرا، مدیریت و توزیع اپلیکیشنها آسان میشود. اخیراً به خصوص در حوزه DevOps فناوری داکر بسیار محبوب و پر استفاده شده است. این مقاله با هدف آموزش داکر (Docker) رایگان برای شروع به کار با آن ارائه شده است. علاوه بر پرداختن به چیستی داکر و مفاهیم مرتبط با کانتینرها و ایمیجها، برای کسب تجربه عملی کار با داکر، نحوه داکریزه کردن و استقرار وب اپلیکیشنهای سفارشی به صورت محلی و سپس در فضای ابری با استفاده از این فناوری «کانتینرسازی» (Containerization | محفظهبندی) نیز آموزش داده شده است. حتی در صورتی که افراد هیچ تجربه قبلی با استقرار نرم افزار به این شیوه نداشته باشند، تمام نیازمندیها برای شروع کار با داکر در این مقاله آموزشی تامین شدهاند. از این مقاله میتوان به عنوان نقطه شروعی برای آموزش پیشرفته داکر استفاده کرد.
داکر چیست ؟
داکر (Docker) یک پروژه منبع آزاد است که استقرار برنامههای نرم افزاری را در داخل کانتینرها (محفظهها | Container) به وسیله فراهم کردن یک لایه انتزاعی اضافی و خودکار کردن مجازی سازی سطح سیستم عامل در لینوکس به فرآیندی خودکار تبدیل میکند.
به بیان سادهتر، داکر ابزاری است که به برنامه نویسان، توسعه دهندگان، ادمینهای سیستم (Sys-Admins) و سایر افراد اجازه میدهد تا به راحتی برنامههای توسعه داده شده خود را در یک Sandbox (جعبه شنی) که به آن کانتینر گفته میشود، روی سیستم عامل میزبان (که همان لینوکس باشد) اجرا کنند.
Sandbox یک ناحیه آزمایشی روی یک سیستم کامپیوتری به حساب میآید که در آن میتوان بدون تاثیر بر سخت افزار یا نرم افزار دیگر، یک برنامه نرم افزاری را اجرا کرد. مزیت کلیدی داکر این است که به کاربران اجازه میدهد تا یک اپلیکیشن را به همراه تمام متعلقاتش (ضمایم | Dependancies) در یک واحد استانداردسازی شده برای توسعه نرم افزار بستهبندی کنند. بر خلاف ماشینهای مجازی (Virtual Machine | VM) کانتینرها سربار (Overhead) بالایی ندارند و از این رو امکان استفاده از سیستم زیربنایی و منابع را به صورت بهینهتر فراهم میکنند.
Docker Container چیست ؟
کانتینر یک واحد استاندارد نرم افزاری است که کدها را به همراه تمام متعلقاتش (وابستگیهایش) بستهبندی میکند تا امکان اجرای سریع و قابل اطمینان اپلیکیشن توسعه داده شده در محیطهای محاسباتی مختلف فراهم شود.
امروزه استاندارد صنعت برای اجرای برنامههای نرم افزاری به سمت استفاده از ماشینهای مجازی سوق پیدا کرده است. ماشینهای مجازی اپلیکیشنها را در داخل یک سیستم عامل مهمان اجرا میکنند. این سیستم عامل مهمان روی سخت افزار مجازی به وسیله سیستم عامل میزبان در سرور اجرا میشود. ماشینهای مجازی در فراهم کردن جداسازی (تفکیک | ایزولهسازی) پردازش برای اپلیکیشنها عملکرد بسیار خوبی دارند. با استفاده از ماشینهای مجازی احتمال بسیار اندکی وجود دارد که بروز یک مشکل در سیستم عامل میزبان منجر به تحت تاثیر قرار گرفتن نرم افزار در حال اجرا روی سیستم عامل مهمان شود.
اما این ایزولهسازی در ماشینهای مجازی هزینه گزافی را در پی دارد؛ زیرا محاسباتی که صرف مجازی سازی سخت افزار برای استفاده یک سیستم عامل مهمان میشوند، سربار بسیار قابل توجهی به همراه خواهند داشت. اما کانتینرها از رویکرد متفاوتی استفاده میکنند؛ با بهکارگیری قابلیتهای سطح پایین سیستم عامل میزبان، کانتینرها به میزان زیادی همان ایزولهسازی ماشینهای مجازی را با توان محاسباتی بسیار کمتری فراهم میسازند.
فناوری کانتینر داکر در سال ۱۳۹۲ (۲۰۱۳ میلادی) به عنوان یک موتور داکر متن باز منتشر شد. در این فناوری، مفاهیم محاسباتی موجود در زمینه کانتینرها و خصوصاً مفاهیم اولیهای در دنیای لینوکس، مثل cgroupها و فضای نام (Namespace) به کار گرفته شدهاند. فناوری داکر به این دلیل منحصر به فرد است که بر نیازمندیهای توسعه دهندگان و اپراتورهای سیستم برای جداسازی متعلقات سیستمی از زیرساختشان تمرکز دارد. موفقیت در دنیای لینوکس به همکاری دوجانبه با مایکروسافت برای انتقال کانتینرهای داکر و انتقال قابلیتهای آن به ویندوز سرور منجر شده است که گاهی آن را با عنوان «کانتینرهای داکر ویندوز» (Docker Windows Containers) یا همان «کانتینرهای ویندوز» خطاب میکنند.
ویژگی های کانتینر داکر چیست ؟
انواع کانتینرهای اجرا شده روی موتور داکر دارای ویژگیهای زیر هستند:
- استاندارد: داکر استاندارد صنعتی برای کانتینرها را ایجاد کرده است تا این کانتینرها در همه جا به صورت قابل حمل در دسترس باشند.
- حجم کم: کانتینرها کرنل سیستم عامل یک ماشین را به اشتراک میگذارند و بنابراین نیازی به یک سیستم عامل برای هر اپلیکیشن وجود ندارد. این رویکرد منجر به افزایش کارایی سرور و کاهش هزینههای سرور و صدور مجوز خواهد شد.
- امنیت: با کانتینربندی یک اپلیکیشن، امنیت آن افزایش پیدا میکند و داکر قابلیتهای پیشفرض ایزولهسازی را در صنعت فراهم ساخته است.
حال در ادامه به شرح مفهوم رایج دیگری در داکر به نام «ایمیج» (Image) یا «ایمیج کانتینر» (Container Image) پرداخته شده است.
Container Image در داکر چیست؟
Container image در داکر به یک بسته نرم افزاری اجرایی مستقل و کم حجم گفته میشود که حاوی تمام موارد مورد نیاز برای اجرای یک اپلیکیشن (برنامه نرم افزاری) است. این موارد مورد نیاز در ادامه فهرست شدهاند:
- کدها
- زمان اجرا (Runtime)
- ابزارهای سیستمی
- کتابخانههای سیستمی
- تنظیمات
کانتینر ایمیجها در زمان اجرا تبدیل به کانتینر میشوند و در خصوص کانتینرهای داکر، ایمیجها زمانی تبدیل به کانتینر میشوند که روی موتور داکر (Docker Engine) اجرا شوند. هم برای اپلیکیشنهای ویندوزی و هم لینوکسی یک نرم افزار کانتینربندی شده (محفظهبندی شده) جدا از زیرساختش همیشه به صورت یکسان اجرا خواهد شد. کانتینرها نرم افزار را از محیط خود جداسازی و اطمینان حاصل میکنند که برخلاف تفاوتها برای مثال بین مراحل توسعه و ناحیهبندی (Staging | در استقرار نرم افزار) برنامه به طور یکدست و یکنواخت کار میکند.
چرا از کانتینرها استفاده میشود؟
کانتینرها یک مکانیزم بستهبندی را فراهم میکنند که در آن امکان جداسازی انتزاعی اپلیکیشنها از محیط واقعی اجرای این برنامهها به وجود میآید . این جداسازی به اپلیکیشنهای مبتنی بر کانتینرها اجازه میدهد تا استقرار نرم افزار به راحتی و به طور پایدار جدا از ماهیت محیط میزبان انجام شود؛ چه این محیط یک مرکز داده خصوصی، چه یک محیط ابری عمومی ی ا حتی لپتاپ شخصی یک برنامه نویس باشد. بدین وسیله این امکان برای توسعه دهندگان به وجود میآيد تا محیطهای قابل پیشبینی ایجاد کنند که از سایر اپلیکیشنها تفکیک شدهاند و میتوانند در هر جایی اجرا شوند. از جایگاه عملیاتی، علاوه بر قابلیت حمل، کانتینرها امکان «کنترل دانهای» (Granular Control) بیشتری را روی منابع فراهم میکنند که باعث بهبود کارایی زیرساختها خواهد شد و میتواند منجر به استفاده بهتر از منابع محاسباتی شود.
به خاطر همه این مزیتها، عده زیادی به استفاده از کانتینرها (و داکر) روی آوردهاند. شرکتهای بزرگی مثل گوگل، فیسبوک، نتفلیکس و Salesforce از کانتینرها برای افزایش کارایی تیمهای مهندسی بزرگ و بهبود مصرف منابع محاسباتی استفاده میکنند. در واقع، گوگل به دلیل حذف نیاز به یک مرکز داده تمام عیار، اعتبار ویژهای برای کانتینرها قائل است. یک سوال بسیار مهم و رایج در خصوص کانتینرها این است که آنها دقیقاً چه تفاوتی با ماشینهای مجازی دارند که باعث شده است نسبت به VMها ترجیح داده شوند؟
تفاوت کانتینر با ماشین مجازی چیست؟
مزیتهای استفاده از ساز و کارهای ایزولهسازی و تخصیص منابع در کانتینرها و ماشینهای مجازی مشابه هستند، اما عملکرد این دو برای انجام چنین کاری متفاوت است؛ زیرا کانتینرها به جای مجازی سازی سخت افزار، سیستم عامل را مجازی سازی میکنند. کانتینرها قابلیت حمل بیشتری دارند و نسبت به ماشین مجازی بهینهتر عمل میکنند.
ماشینهای مجازی یا همان VMها انتزاعی از سخت افزار فیزیکی به حساب میآیند که یک سرور را به چندین سرور تبدیل میکنند. لایه نرم افزاری برای ایجاد محیط مجازی که به آن «Hypervisor» میگویند، به چندین ماشین مجازی امکان میدهد تا روی یک ماشین واحد اجرا شوند. هر ماشین مجازی شامل یک نسخه کامل از سیستم عامل، اپلیکیشن، عملیات باینری، کتابخانههای مورد نیاز و سایر موارد است که دهها گیگابایت فضا اشغال میکنند. علاوه بر این، بوت شدن ماشینهای مجازی معمولاً بسیار کند است.
از طرف دیگر، کانتینرها انتزاعی در لایه اپلیکیشن محسوب میشوند که کدها و وابستگیهای آنها را به همراه هم بستهبندی میکنند. چندین کانتینر قابلیت اجرا روی یک ماشین مشترک را دارند و این امکان وجود دارد که هسته یا همان کرنل سیستم عامل با سایر کانتینرها به اشتراک گذاشته شود و هر کدام از آنها در فضای کاربر به صورت پردازههای مجزا و مستقل اجرا شوند. کانتینرها فضای کمتری را نسبت به ماشینهای مجازی اشغال میکنند (ایمیجهای کانتینر به طور معمول تنها حجمی معادل چند ده مگابایت دارند). علاوه بر این، کانتینرها میتوانند اپلیکیشنهای بیشتری را تحمل کنند و با استفاده از آنها نیاز به ماشینهای مجازی و سیستم عاملهای کمتری وجود دارد.
پس از معرفی مفاهیم اصلی و پایه داکر، در ادامه این مقاله به برخی از سوالات مهم و مقدمات لازم در خصوص شروع آموزش داکر پرداخته شده است.
شروع آموزش داکر
این مقاله آموزش داکر بخشهای مختلفی دارد که در هر یک جنبه خاصی از داکر شرح داده شدهاند. در هر بخش دستوراتی اجرا یا کدنویسیهایی انجام شدهاند. باید در نظر داشت که در این مقاله آموزش داکر با استفاده از نسخه «18.05.0-ce» ارائه شده است. پیش از شروع آموزش داکر و ورود به مباحث کدنویسی، بهتر است ابتدا به پیش نیازهای لازم در خصوص آموزش داکر پرداخته شود.
پیش نیاز های آموزش داکر برای این مقاله چه هستند؟
برای یادگیری داکر با استفاده از این مقاله، لزومی به مهارت خاصی به عنوان پیش نیاز به جز داشتن آشنایی کافی با محیط خط فرمان و همچنین آشنایی با نحوه استفاده از یک ویرایشگر متن وجود ندارد. برای آموزش داکر در این مقاله از «git clone» جهت شبیهسازی محلی مخزن (Repository) استفاده شده است.
در صورتی که فردی گیت را روی سیستمش نصب نداشته باشد، یا باید آن را نصب کند یا اینکه به یاد داشته باشد تا فایل فشرده با فرمت Zip را به صورت دستی از گیتهاب دانلود کند. همچنین، داشتن تجربه توسعه وب اپلیکیشنها نیز برای آموزش داکر در این مقاله به عنوان پیش نیاز مفید خواهد بود، اما الزامی نیست. یکی دیگر از پیش نیازهای یادگیری داکر با استفاده از این مقاله آموزشی، ایجاد حساب کاربری در هر یک از سایتهای وب سرویسهای آمازون و داکر هاب است.
پیش نیازهای آموزش داکر به طور کلی کدامند؟
در پاسخ به این سوال که به طور کلی برای آموزش داکر چه مهارتهایی به عنوان پیش نیاز ضروری هستند، باید گفته که پیش از هر چیز با توجه به اینکه داکر ماهیتی لینوکسی دارد و در اصل برای اجرا در محیط لینوکس ارائه شده است، باید آشنایی کافی با این سیستم عامل وجود داشته باشد. در واقع باید درک مطلوبی از اقدامات مربوط به کرنل لینوکس شامل تخصیص منابع، CPU، حافظه، مدیریت شبکه، سازماندهی انباره، زمانبندی برنامهها و ارتباط برنامهها وجود داشته باشد.
دلیل نیاز به آشنایی با لینوکس پیش از شروع آموزش داکر چیست ؟
هز یک از دلایل آشنایی با لینوکس به عنوان پیش نیاز آموزش داکر در ادامه فهرست شدهاند:
- Cgroups : یک روش ایزولهسازی پردازش برای گروهبندی پردازهها با یکدیگر است و در جلوگیری از تداخل بین کانتینرها کاربرد دارد.
- فضای نام (Namespaces): فضای نام برای قسمتبندی پشته شبکه بین کانتینرها به کار گرفته میشود.
- COW یا Copy on Write : یک روش مدیریت منابع برای کنترل ایمیجها به حساب میآيد (ایمیجها فقط خواندنی هستند).
- حجمها و اتصال پیوند (Volumes and Bind Mounting): برای مدیریت دادهها در کانتینرها (مثلاً برای اتصال فایلهای سیستمی میزبان به عنوان حجم دادهها) استفاده میشود.
دلیل نیاز به آشنایی با شبکههای کامپیوتری پیش از شروع آموزش داکر چیست ؟
بهتر است درک مطلوبی از مفاهیم شبکههای کامپیوتری از جمله مفهوم سوکت، مسیریابی، پروتکل IP، بریجها، شبکههای مجازی، Iptables، پورتها، معماری کلاینت-سروری و سایر موارد نیز پیش از شروع آموزش داکر وجود داشته باشد.
از جمله دلایل نیاز به آشنایی با شبکههای کامپیوتری پیش از شروع آموزش داکر میتوان به موارد زیر اشاره کرد:
- داکر به دو بخش مختلف تقسیم میشود. یک کلاینت و یک سرور که از طریق یک سوکت (یا از طریق یک شبکه و یا از طریق یک فایل) ارتباط برقرار میکند.
- علاوه بر این، داکر از بریجها و NAT برای ایجاد شبکههای مجازی در داخل کامپیوتر استفاده میکند.
- همچنین داکر فایروالی (به نام iptables) را برای انتقال بستهها بین کانتینرها و اینترنت به کار میگیرد.
علاوه بر آشنایی با لینوکس و شبکههای کامپیوتری بهتر است پیش از آغاز آموزش داکر در صورتی که قصد استفاده از آن در محیط ویندوز وجود دارد، آشنایی کافی با مدیریت سرورهای ویندوز هم وجود داشته باشد. همچنین، آشنایی با مفاهیم مجازی سازی هم میتواند به یادگیری بهتر داکر کمک کند.
- مقاله پیشنهادی: مسیریابی لایه شبکه — راهنمای جامع
انجام تنظیمات مورد نیاز در کامپیوتر پیش از شروع آموزش داکر
آمادهسازی و راهاندازی تمام ابزارهای لازم روی کامپیوتر شخصی میتواند کار دشواری باشد. اما خوشبختانه با توجه به اینکه داکر ثُبات لازم را پیدا کرده، راهاندازی و اجرای آن روی هر سیستم عامل دلخواه به کاری ساده و آسان تبدیل شده است. تا پیش از چند نسخه قبلی، اجرای داکر روی مک OS و ویندوز دردسرهای زیادی داشت. اما اخیراً داکر پیشرفتهای قابل ملاحظهای را در خصوص تجربه کاربری مطلوب در سیستم عاملهای مختلف برای کاربران به ارمغان آورده است.
راهنمای شروع به کار در سایت داکر دارای دستورالعملهای دقیقی برای راهاندازی داکر روی سیستم عاملهای مک، لینوکس و ویندوز است. همچنین در مقاله دیگری هم به نحوه شروع به کار با داکر در ویندوز و لینوکس پرداخته شده است که مطالعه بخشهای مربوط به «آموزش شروع به کار با Docker» در این مقاله پیش از ادامه مطالعه مقاله آموزش داکر میتواند مفید واقع شود.
- برای مطالعه مقاله «داکر چیست ؟ | راهنمای شروع به کار با Docker — رایگان و به زبان ساده» + کلیک کنید.
پس از پایان نصب داکر میتوان به وسیله وارد کردن دستور زیر در خط فرمان از صحت نصب آن اطمینان حاصل کرد:
$ docker run hello-world
در صورتی که داکر به درستی روی سیستم نصب شده باشد، پیام زیر در خروجی نمایش داده خواهد شد:
Hello from Docker. This message shows that your installation appears to be working correctly. ...
برنامه Hello World برای شروع آموزش داکر
پس از آنکه همه چیز راهاندازی و آماده شد، زمان شروع آموزش داکر فرا میرسد. در این بخش، یک کانتینر Busybox روی سیستم اجرا و آشنایی با دستور «docker run» حاصل خواهد شد. Busybox یک بسته نرم افزاری به حساب میآید که چندین ابزار تحت یونیکس را به صورت ابتدایی و تقلیل داده شده در قالب یک فایل اجرایی فراهم میسازد. برای شروع، باید دستور زیر را در ترمینال (خط فرمان) اجرا کرد:
$ docker pull busybox
لازم است به این مسئله توجه شود که بسته به اینکه داکر چگونه روی سیستم نصب شده ، ممکن است یک خطای عدم صدور مجوز (Permission Denied) پس از اجرای دستور فوق صادر شود. در صورتی که از سیستم عامل مک OS استفاده میشود، باید اطمینان یافت که موتور داکر یا همان Docker Engine در حال اجرا باشد. در صورت استفاده از لینوکس و مشاهده این خطا، باید قبل از دستور فوق از کلمه کلیدی «Sudo» استفاده کرد. علاوه بر آن، میتوان یک گروه داکر (Docker Group) ایجاد کرد تا بلاخره بتوان از شر این مشکل خلاص شد.
دستور «pull» ایمیج Busybox را از رجیستری داکر دریافت و آن را در سیستم ذخیره میکند. میتوان از دستور «docker images» برای مشاهده فهرستی از ایمیجهای روی سیستم استفاده کرد:
$ docker images
با توجه به اینکه ایمیج Busybox دریافت شده است، خروجی به صورت زیر خواهد بود:
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
busybox latest c51f86c28340 4 weeks ago 1.109 MB
اجرای یک کانتینر در داکر برای مثال Hello World
اکنون در این بخش از آموزش داکر یک کانتینر داکر بر اساس ایمیج busybox اجرا میشود. برای انجام این کار باید از دستور «docker run» استفاده کرد:
$ docker run busybox
با اجرای دستور فوق، اتفاق خاصی رخ نمیدهد. این دلیل بر وجود یک مشکل نیست، چرا که در پشت صحنه اتفاقات زیادی رخ میدهد. وقتی که از دستور «run» استفاده میشود، کلاینت، داکر ایمیج را (که در این مورد Busybox باشد) پیدا میکند، کانتینر را بارگذاری میکند و سپس یک دستور را در آن کانتینر اجرا میکند. وقتی که دستور «docker run busybox» اجرا میشود، هیچ دستوری ارجاع داده نشده است. بنابراین، کانتینر پس از بارگذاری، یک دستور خالی را اجرا میکند و سپس خروج انجام میشود. به همین دلیل است که با اجرای دستور فوق هیچ اتفاقی نمیافتد. حال در ادامه یک دستور هم برای اجرا به کانتینر فرستاده شده است:
$ docker run busybox echo "hello from busybox"
این بار یک خروجی به صورت زیر وجود دارد:
hello from busybox
به این ترتیب با اجرای دستور «docker run» خروجی هم مشاهده میشود. در این حالت، کلاینت داکر طبق وظیفه خود دستور «echo» را در کانتینر Busybox اجرا میکند و سپس خروج انجام میشود. همانطور که ملاحظه میشود، همه چیز به سرعت انجام میشود. اکنون زمان آن فرا رسیده است تا دستور «docker ps» آموزش داده شود.
دستور docker ps در آموزش داکر
این دستور تمام کانتینرهایی را نشان میدهد که اکنون در حال اجرا هستند:
$ docker ps
خروجی دستور فوق به صورت زیر است:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
به این دلیل که هیچ کانتینری در حال اجرا نیست، هیچ فیلدی در جدول خروجی مشاهده نمیشود و تنها عناوین ستونهای جدول در خروجی چاپ شدهاند.
آموزش دستور docker ps : استفاده از پرچم -a
حال در ادامه، دستور فوق به گونهای کاربردیتر به کار گرفته شده است:
$ docker ps -a
خروجی به صورت زیر خواهد بود:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
305297d7a235 busybox "uptime" 11 minutes ago Exited (0) 11 minutes ago distracted_goldstine
ff0a5c3750b9 busybox "sh" 12 minutes ago Exited (0) 12 minutes ago elated_ramanujan
14e5bd11d164 hello-world "/hello" 2 minutes ago Exited (0) 2 minutes ago thirsty_euclid
چیزی که در اطلاعات خروجی دستور فوق ملاحظه میشود، فهرستی از تمام کانتینرهایی است که تا کنون اجرا شدهاند. باید دقت کرد که ستون وضعیت (STATUS) نشان میدهد که این کانتینرها چند دقیقه پیش وجود داشتهاند. ممکن است این سوال وجود داشته باشد که آیا راهی برای اجرای بیش از یک دستور در یک کانتینر وجود دارد؟ در ادامه به این مسئله پرداخته شده است که چطور میتوان این کار را انجام داد؟
اجرای چند دستور با docker run در آموزش داکر
اجرای چند دستور با استفاده از docker run به صورت زیر انجام میشود:
$ docker run -it busybox sh
/ # ls
bin dev etc home proc root sys tmp usr var
/ # uptime
05:45:21 up 5:58, 0 users, load average: 0.00, 0.01, 0.04
اجرای دستور «run» با پرچمهای «-it» پیوند لازم را با یک کانتینر «tty» برقرار میکند. اکنون میتوان دستورات لازم را به تعداد دلخواه اجرا کرد. به این ترتیب، نحوه استفاده از دستور «docker run» که دستوری پر استفاده به حساب میآید در این بخش از مقاله آموزش داکر شرح داده شد. بهتر است کمی زمان برای یادگیری بهتر این دستور صرف شود. برای یادگیری بیشتر دستور «run»، میتوان از دستور «docker run –help» برای مشاهده فهرستی از تمام پرچمهایی (Flagهایی) استفاده کرد که این دستور از آنها پشتیبانی میکند. در ادامه آموزش داکر نیز از چند نوع دستور دیگر «docker run» استفاده خواهد شد.
پیش از پرداختن به ادامه آموزش داکر ، بهتر است چگونگی حذف کانتینرها به سرعت بررسی شود.
حذف کانتینرها در Docker چگونه انجام میشود؟
پیشتر ملاحظه شد که همچنان میتوان بقایای کانتینر را حتی پس از خروج از آن به وسیله دستور «docker ps -a» مشاهده کرد. در طول آموزش داکر در این مقاله چندین بار از دستور «docker run» استفاده خواهد شد و رها کردن کانتینرهای سرگردان فضای دیسک را به میزان زیادی اشغال خواهد کرد. بنابراین، به عنوان یک قاعده کلی، بهتر است پس از اتمام کار با یک کانتینر، آن را پاکسازی کرد. برای انجام این کار میتوان دستور «docker rm» را اجرا کرد.
تنها باید شناسههای (ID) کانتینرها را کپی و آنها را در ادامه دستور Paste کرد:
$ docker rm 305297d7a235 ff0a5c3750b9
خروجی به صورت زیر است:
305297d7a235
ff0a5c3750b9
همانطور که در بالا ملاحظه میشود، در هنگام حذف کانتینرها، شناسههای آنها در خروجی بازتاب داده میشوند.
حذف چندین کانتینر Docker به صورت یکجا برای آموزش حذف کانتینرهای داکر
در صورتی که چندین کانتینر برای حذف کردن به صورت یکجا وجود داشته باشد، کپی و الصاق مجدد شناسههای هر کانتینر میتواند کار دشواری باشد. در چنین حالتی، میتوان به سادگی دستور زیر را اجرا کرد:
$ docker rm $(docker ps -a -q -f status=exited)
دستور فوق تمام کانتینرهایی را حذف خواهد کرد که دارای وضعیتی (Status) به صورت «exited» یا همان «خارج شده» هستند. پرچم «-q» تنها شناسههای عددی را باز میگرداند و «-f» خروجی را بر اساس شرایط تعیین شده ارائه میدهد. یک مورد دیگری هم که کاربردی خواهد بود، پرچم «–rm» است. این پرچم را میتوان در دستور «docker run» استفاده کرد و کاربرد آن به این صورت است که کانتینر را به شکل خودکار در زمان خروج حذف میکند. استفاده از این پرچم برای کانتینرهایی که فقط برای یک بار اجرا میشوند بسیار مفید و کاربردی است. در نسخههای جدیدتر داکر میتوان از دستور «docker container prune» نیز برای پاک کردن تمام کانتینرهای متوقف شده استفاده کرد:
$ docker container prune
خروجی دستور فوق در ادامه آمده است:
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
4a7f7eebae0f63178aff7eb0aa39f0627a203ab2df258c1a00b456cf20063
f98f9c2aa1eaf727e4ec9c0283bcaa4762fbdba7f26191f26c97f64090360
Total reclaimed space: 212 B
در نهایت میتوان ایمیجهایی را که دیگر نیازی به آنها وجود ندارد را نیز با اجرای دستور «docker rmi» حذف کرد.
واژه شناسی در آموزش داکر
در بخشهای قبلی از تعداد زیادی اصلاحات تخصصی داکر استفاده شد که ممکن است برای برخی از افراد گیج کننده باشند.
بنابراین، پیش از ادامه آموزش داکر ، بهتر است در این بخش برخی از واژهها و اصطلاحاتی شرح داده شوند که به طور معمول در زیستبوم داکر به کار گرفته میشوند.
ایمیج در داکر چه چیست؟
پیشتر و در ابتدای آموزش داکر نیز به مفهوم ایمیج (Image) پرداخته شده است. ایمیجها در داکر نقشه ساخت اپلیکیشن به حساب میآیند و پایه و اساس کانتینرها را تشکیل میدهند. پیشتر در آموزش مقدماتی داکر در همین مقاله از دستور «docker pull» برای دانلود کردن ایمیج Busybox استفاده شد.
کانتینرها در داکر چه هستند؟
پیشتر در این مقاله توضیحات لازم به طور جامع پیرامون چیستی کانتینرها ارائه شدهاند. این موجودیتها از ایمیجهای داکر تولید میشوند و مسئولیت اجرای اپلیکیشن را بر عهده دارند. یک کانتینر با استفاده از دستور «docker run» ایجاد میشود. پیشتر با استفاده از ایمیج Busybox که دانلود شده بود، یک کانتینر ایجاد و اجرا شد. میتوان فهرستی از کانتینرهای در حال اجرا را با استفاده از دستور «docker ps» مشاهده کرد.
Docker Daemon چیست ؟
Docker Daemon سرویس پس زمینهای است که روی میزبان (هاست) اجرا میشود و ساخت، اجرا و توزیع کانتینرها را مدیریت میکند. Daemon پردازهای است که در سیستم عاملی اجرا میشود که کلاینتها با آن در ارتباط هستند.
کلاینت داکر یا Docker Client چیست ؟
کلاینت داکر به ابزار خط فرمانی گفته میشود که به کاربر امکان میدهد تا با Daemon تعامل داشته باشد. به طور کلیتر، اشکال دیگری از کلاینت هم میتواند وجود داشته باشد؛ مثلاً Kitematic که یک رابط کاربری گرافیکی (GUI) را برای کاربران فراهم میسازد.
داکر هاب یا Docker Hub چیست ؟
داکر هاب به عنوان یک رجیستری از ایمیجهای داکر شناخته میشود. میتوان رجیستری را شاخهای (دایرکتوری) از تمام ایمیجهای داکر موجود در نظر گرفت. در صورت لزوم، یک فرد میتواند رجیستری داکر خودش را میزبانی و از آنها برای بیرون کشیدن ایمیجها استفاده کند.
موتور داکر یا Docker Engine چیست ؟
Docker Engine یک فناوری کانتینرسازی متن باز برای ساخت و کانتینربندی اپلیکیشنها به حساب میآید. Docker Engine به عنوان یک اپلیکیشن کلاینت-سرور عمل میکند که دارای سروری با یک پردازه Daemon دائم الاجرا است. همچنین موتور داکر APIهایی هم دارد. این APIها رابطهایی را تعیین میکنند که برنامهها میتوانند از آنها برای ارتباط با Docker Daemon و دستور دادن به آن استفاده کنند.
نحوه استقرار وب اپلیکیشن با داکر در آموزش Docker
پس از آموزش دستور «docker run»، کار با کانتینر داکر و شرح برخی از اصطلاحات فنی داکر، اکنون زمان آن فرا رسیده است تا وارد مباحث اصلیتر و فنیتر آموزش داکر شده و به شرح نحوه استقرار وب اپلیکیشنها با داکر پرداخته شود. ابتدا بهتر است کار استقرار روی سرور را با یک سایت ایستای ساده شروع کرد.
اجرای یک سایت ایستای ساده در Docker برای آموزش استقرار وب اپلیکیشن با داکر
بهتر است فرآیند آموزش با سادهترین حالت ممکن آغاز شود. بنابراین، در این بخش ابتدا آموزش اجرای یک وب سایت ایستا و بسیار ساده با داکر ارائه شده است. ابتدا یک ایمیج داکر از داکر هاب بیرون کشیده میشود؛ سپس این کانتینر اجرا و ملاحظه خواهد شد که اجرای یک وب سرور با داکر چقدر ساده است.
برای شروع، لازم به توضیح است که ایمیج مورد استفاده در این مثال یک وب سایت تک صفحهای است که از قبل با هدف استفاده در این آموزش ایجاد شده است و در رجیستری «prakhar1989/static-site» [+] میزبانی میشود. میتوان این ایمیج را با استفاده از دستور «docker run» دانلود و اجرا کرد. همانطور که پیشتر اشاره شد، پرچم «–rm» به طور خودکار کانتینر را در هنگام خروج حذف میکند:
$ docker run --rm prakhar1989/static-site
به دلیل اینکه این ایمیج به صورت محلی وجود ندارد، کلاینت ابتدا ایمیج را از رجیستری دریافت و سپس آن را اجرا میکند. در صورتی که همه چیز به خوبی پیش برود، باید پیامی به صورت «Nginx is running…» در خط فرمان مشاهده شود. اکنون که سرور اجرا شده است، چطور میتوان وب سایت خود را دید؟ وب سایت روی چه پورتی در حال اجراست؟ مهمتر از همه، چطور میتوان مستقیماً از ماشین میزبان به کانتینر دسترسی داشت؟ حالا باید با استفاده از کلیدهای «Ctrl + C» کانتینر را متوقف کرد.
در این مورد به خصوص، کلاینت هیچ پورتی را در معرض نمایش قرار نمیدهد یا اصطلاحاً اکسپوز نمیکند؛ بنابراین باید دستور «docker run» را برای انتشار پورتها دوباره اجرا کرد. همچنین باید برای اینکه خط فرمان به کانتینر در حال اجرا متصل نباشد نیز راهی پیدا کرد. به این صورت میتوان در حالی به راحتی از ترمینال خارج شد و آن را بست که کانتینر همچنان در حال اجرا باقی بماند. به این روش «حالت منفصل» یا حالت جدا شده گفته میشود.
$ docker run -d -P --name static-site prakhar1989/static-site
e61d12292d69556eabe2a44c16cbd54486b2527e2ce4f95438e504afb7b02810
در دستور فوق، پرچم ««-d ترمینال را از کانتینر جداسازی میکند، پرچم «-P» تمام پورتهای در معرض دسترس را منتشر خواهد کرد و در نهایت پرچم «–name» برای نامگذاری استفاده شده است. اکنون میتوان پورتهای در معرض دسترس را با اجرای دستور «docker port [CONTAINER]» مشاهده کرد:
$ docker port static-site
خروجی دستور فوق به صورت زیر است:
80/tcp -> 0.0.0.0:32769
443/tcp -> 0.0.0.0:32768
مشاهده خروجی اجرای یک سایت ایستای ساده در Docker :
اکنون میتوان وب سایت ایستای اجرا شده را با وارد کردن آدرس «http://localhost:32769» در مرورگر ملاحظه کرد. باید به این نکته دقت داشت که در صورت استفاده از «docker-toolbox»، ممکن است نیاز به استفاده از دستور «docker-machine ip default» برای دریافت آدرس IP وجود داشته باشد. علاوه بر این، میتوان یک پورت سفارشی را هم تعیین کرد که کلاینت با استفاده از آن اتصالها را به کانتینر هدایت کند.
$ docker run -p 8888:80 prakhar1989/static-site
Nginx is running...
در نهایت، خروجی اجرای این وب سایت ایستای ساده روی کانتینرهای داکر به صورت تصویر زیر خواهد بود:
برای متوقف کردن یک کانتینر منفصل از دستور «docker stop» استفاده میشود که باید شناسه کانتینر مربوطه را هم در ادامه این دستور وارد کرد. در مورد این مثال، میتوان نام «static-site» را به عنوان شناسه وارد کرد. این نام پیشتر در زمان راهاندازی کانتینر هم استفاده شد.
$ docker stop static-site
آنچه در خروجی مشاهده خواهد شد، در ادامه آمده است:
static-site
برای استقرار چنین پروژهای روی یک سرور واقعی، تنها لازم است داکر نصب را نصب و دستور بالا را اجرا کرد. اکنون پس از آنکه نحوه اجرای یک وب سرور در داخل یک ایمیج داکر شرح داده شده است، ممکن است این سوال به وجود بیاید که چگونه میتوان ایمیج داکر سفارشی خود را ایجاد کرد؟ در ادامه آموزش داکر در این مقاله به این سوال مهم پاسخ داده شده است.
ایجاد Docker Image در آموزش داکر
پیش از این مفهوم ایمیج در ابتدای آموزش داکر شرح داده شد؛ اما در این بخش به شکل عمیقتری به چیستی ایمیجهای داکر و نحوه ساخت یک ایمیج سفارشی پرداخته شده است. همچنین در ادامه از ایمیج ساخته شده برای اجرای اپلیکیشن خود به صورت محلی و سپس استقرار آن روی وب سرویس آمازون یا همان AWS برای به اشتراکگذاری این ایمیج با سایر برنامه نویسان استفاده خواهد شد.
مشاهده فهرست ایمیجهای محلی و Pull کردن ایمیج در آموزش Docker Image
ایمیجهای داکر پایه و اساس کانتینرها به حساب میآیند.
در مثال قبلی، ایمیج Busybox از رجیستری بیرون کشیده شد و از طریق کلاینت داکر درخواست شد تا یک کانتینر بر اساس آن ایمیج اجرا شود. برای دیدن فهرست ایمیجهایی که به صورت محلی در دسترس هستند، میتوان از دستور «docker images» استفاده کرد:
$ docker images
پس از اجرای دستور فوق، خروجی به صورت زیر خواهد بود:
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
prakhar1989/catnip latest c7ffb5626a50 2 hours ago 697.9 MB
prakhar1989/static-site latest b270625a1631 21 hours ago 133.9 MB
python 3-onbuild cf4002b2c383 5 days ago 688.8 MB
martin/docker-cleanup-volumes latest b42990daaca2 7 weeks ago 22.14 MB
ubuntu latest e9ae3c220b23 7 weeks ago 187.9 MB
busybox latest c51f86c28340 9 weeks ago 1.109 MB
hello-world latest 0a6ba66e537a 11 weeks ago 960 B
همانطور که ملاحظه میشود، دستور فوق فهرستی از ایمیجهایی را در خروجی نمایش میدهد که از رجیستری بیرون کشیده شدهاند. ایمیجهایی که به صورت سفارشی توسط توسعه دهنده ایجاد شدهاند نیز در این فهرست وجود دارند. ستون «TAG» به یک نمود (Snapshot) خاصی از ایمیج مربوطه اشاره دارد و ستون «IMAGE ID» هم شناسه منحصربهفرد متناظر برای آن ایمیج به حساب میآید.
برای درک بهتر چیستی ایمیج، میتوان آن را درست مثل یک مخزن گیت در نظر گرفت. میتوان تغییراتی را در ایمیجها اِعمال کرد (مشابه Commit کردن در گیت) و همچنین چندین نسخه مختلف از آن در اختیار داشت. در صورتی که یک شماره نسخه مشخص تعیین نشود، کلاینت به طور پیشفرض آخرین نسخه را استفاده خواهد کرد. برای مثال، میتوان یک نسخه خاص از ایمیج ubuntu را به صورت زیر بیرون کشید:
$ docker pull ubuntu:18.04
برای دریافت یک ایمیج داکر جدید یا میتوان آن را از یک رجیستری (مثلاً داکر هاب) دریافت کرد یا اینکه فرد میتواند ایمیج سفارشی مختص به خودش را بسازد.
واژه شناسی و انواع مختلف ایمیج در آموزش Docker Image :
در حال حاضر هزاران ایمیج مختلف روی داکر هاب در دسترس است. میتوان به صورت مستقیم از طریق خط فرمان با استفاده از دستور «docker search» ایمیجها را جستجو کرد.
یک وجه تمایز مهمی که باید در مورد ایمیجها از آن آگاه بود، تفاوت میان ایمیجهای پایه و فرزند است:
- ایمیجهای پایه (Base Images): اینها ایمیجهایی هستند که هیچ ایمیج والدی ندارند و معمولاً ایمیجهایی دارای یک سیستم عامل از این نوع هستند. برای مثال میتوان ایمیجهای اوبونتو، busybox یا Debian را نام برد.
- ایمیجهای فرزند (Child Images): ایمیجهایی مبتنی بر ایمیجهای پایه هستند که قابلیتهای افزودهای به آنها اضافه شده است.
علاوه بر اینها، ایمیجهای رسمی و همچنین ایمیجهای کاربر هم وجود دارند که میتوانند هم از نوع ایمیج پایه و هم از نوع فرزند باشند:
- ایمیجهای رسمی (Official Images): اینها ایمیجهایی هستند که به طور رسمی توسط برنامه نویسان (کارمندان) داکر نگهداری و پشتیبانی میشوند. نام این ایمیجها معمولاً تک کلمهای است. ایمیجهای busybox ،ubuntu ،python و hello-world از جمله ایمیجهای رسمی به حساب میآیند که پیشتر در فهرست ایمیجهای خروجی خط فرمان مشاهده شدند.
- ایمیجهای کاربر (User Images): اینها ایمیجهایی هستند که توسط کاربران مختلف ایجاد و به اشتراک گذاشته شدهاند. ایمیجهای کاربران مبتنی بر ایمیجهای پایه هستند و قابلیتهایی به آنها اضافه شده است. معمولاً نام این نوع ایمیجها به صورت «user/image-name» است که به جای کلمه «image-name» از نام انتخابی برای آن ایمیج استفاده میشود.
ایجاد اولین ایمیج در آموزش Docker Image
اکنون که درک بهتری از ایمیجها به دست آمده، زمان آن فرا رسیده است تا یک ایمیج سفارشی و شخصی ساخته شود. هدف اصلی در این بخش، ایجاد ایمیجی است که یک اپلیکیشن ساده ساخته شده با Flask را کانتینربندی یا به اصطلاح سندباکس میکند.
برای این بخش از آموزش داکر ، یک اپلیکیشن نمونه با فلسک از قبل ایجاد شده است. کارکرد این اپلیکیشن به این صورت است که هر بار تصویری متحرک (با فرمت gif) از یک گربه را به طور تصادفی نمایش میدهد. باید یک نسخه همسان (Clone) از مخزن مربوطه را به صورت محلی و به شکل زیر ایجاد کرد:
$ git clone https://github.com/prakhar1989/docker-curriculum.git
$ cd docker-curriculum/flask-app
ایجاد نسخه همسان نه در داخل کانتینر بلکه باید روی ماشینی انجام شود که دستورات داکر در آن قرار است اجرا شوند. اکنون گام بعدی، ایجاد یک ایمیج با این وب اپلیکیشن است. همانطور که پیشتر اشاره شد، تمام ایمیجهای کاربر مبتنی بر یک ایمیج پایه هستند. به این دلیل که اپلیکیشن مربوطه به زبان پایتون (زبان فریمورک فلسک) نوشته شده است، ایمیج پایهای که از آن استفاده میشود، «Python 3» خواهد بود.
- مقاله پیشنهادی: آموزش فلسک رایگان | راهنمای شروع با Flask — به زبان ساده
در ادامه مقاله آموزش داکر به شرح چیستی فایلهای داکر پرداخته میشود. پیش از آن، مجموعه دورههای آموزش لینوکس تم آف با هدف تقویت مهارتهای پیش نیاز آموزش داکر به علاقهمندان معرفی شده است.
معرفی فیلم های آموزش لینوکس تم آف
یکی از پیش نیازهای اساسی آموزش داکر آشنایی با سیستم عامل لینوکس به حساب میآید؛ زیرا داکر ماهیتی لینوکسی دارد و در اصل مبتنی بر این سیستم عامل توسعه داده شده است. در وب سایت تم آف دورههای آموزشی مرتبط در قالب مجموعههای آموزشی مختلفی دستهبندی شدهاند که یکی از این مجموعهها مربوط به آموزش لینوکس میشود. مجموعه آموزش Linux — مقدماتی تا پیشرفته فرادس در زمان تدوین این مقاله دارای ۱۶ دوره مختلف و در مجموع حاوی ۷۰ ساعت محتوای آموزش ویدیویی است. دورههای آموزشی مختلفی به ویژه در سطح مقدماتی و با بیان ساده در این مجموعه قابل دسترسی هستند.
- برای مشاهده فیلم های آموزش لینوکس تم آف + اینجا کلیک کنید.
Docker File در آموزش داکر :چیست ؟
«فایل داکر» یا «Docker File» یک فایل متنی ساده است که فهرستی از دستوراتی را شامل میشود که کلاینت داکر در زمان ایجاد یک ایمیج آن را فراخوانی میکند. این یک روش ساده برای خودکارسازی فرآیند ایجاد ایمیج به حساب میآید.
نکته مثبت این است که دستورات نوشته شده در یک فایل داکر تقریباً با دستوراتی یکسان هستند که در خط فرمان لینوکس استفاده میشوند. این یعنی دیگر نیازی به یادگیری سینتکس (نحو) جدیدی برای ایجاد فایلهای داکر وجود ندارد. شاخه پروژه برنامه مربوطه حاوی هیچ فایل داکری نیست، اما چون این اولین باری است که این کار انجام میشود، یک فایل داکر از صفر ایجاد خواهد شد.
آموزش Docker File : ایجاد یک داکر فایل از صفر
برای شروع باید یک فایل خالی جدید را در ویرایشگر متن دلخواه خود ایجاد و آن را در همان پوشهای ذخیره کرد که مربوط به اپلیکیشن فلسک میشود. نام این فایل هم باید Dockerfile باشد. ابتدا کار با مشخص کردن ایمیج پایه آغاز میشود. برای انجام این کار از کلمه کلیدی «FROM» به صورت زیر استفاده میشود:
FROM python:3
معمولاً گام بعدی این است که دستورات کپی کردن فایلها و نصب متعلقات مربوطه انجام شود. ابتدا باید یک شاخه کاری را تنظیم کرد و سپس تمام فایلهای مربوط به اپلیکیشن مربوطه باید کپی شوند:
# تنظیم یک شاخه برای اپلیکیشن
WORKDIR /usr/src/app
# کپی کردن تمام فایلها در کانتینر
COPY . .
اکنون که فایلها آماده هستند، میتوان متعلقات مربوطه را نصب کرد.
# نصب متعلقات
RUN pip install --no-cache-dir -r requirements.txt
مورد بعدی که باید مشخص شود، شماره پورتی است که باید در معرض دسترسی قرار بگیرد. با توجه به اینکه اپلیکیشن فلسک در این مثال روی پورت 5000 اجرا میشود، باید این پورت را برای Expose کردن تعیین کرد:
EXPOSE 5000
آخرین گام، نوشتن دستور مربوطه برای اجرای اپلیکیشن یعنی دستور «python ./app.py» است. برای انجام این کار از دستور «CMD» استفاده میشود:
CMD ["python", "./app.py"]
هدف اصلی «CMD» این است که به کانتینر بگوییم چه دستوری را باید در زمان راهاندازی اجرا کند.
به این ترتیب، اکنون Dockerfile مورد نیاز آماده شده است و تمام محتوای این فایل به صورت زیر در میآید:
FROM python:3
# تنظیم یک شاخه برای اپلیکیشن
WORKDIR /usr/src/app
# کپی کردن تمام فایلها در کانتینر
COPY . .
# نصب متعلقات مربوطه
RUN pip install --no-cache-dir -r requirements.txt
# تعریف شماره پورتی که کانتینر باید Expose کند
EXPOSE 5000
# اجرای دستور
CMD ["python", "./app.py"]
اکنون که Dockerfile مورد نیاز آماده شده است، میتوان ایمیج مربوطه را ساخت.
آموزش Docker File : ایجاد ایمیج از داکر فایل
دستور «docker build» سنگینی بار ایجاد ایمیج داکر را از یک «Dockerfile» بر دوش میکشد. قطعه کد زیر حاوی خروجی مربوط به اجرای این دستور به همراه خود دستور در خط آغازین است. پیش از اجرای این دستور (نقطه در انتهای دستور فراموش نشود)، باید نام کاربری catnip را به نام کاربری خود تغییر داد.
این نام کاربری باید همان نام کاربری باشد که در سایت داکر هاب ایجاد شده است. در صورتی که هنوز این کار انجام نشده باشد، باید همین حالا یک حساب کاربری ایجاد کرد. دستور «docker build» تقریباً ساده است. این دستور یک نام برچسب انتخابی با پرچم «-t» و موقعیت مربوط به محل شاخه حاوی فایل داکر را دریافت میکند.
$ docker build -t yourusername/catnip
خروجی دستور فوق به صورت زیر است:
Sending build context to Docker daemon 8.704 kB
Step 1 : FROM python:3
# Executing 3 build triggers...
Step 1 : COPY requirements.txt /usr/src/app/
---> Using cache
Step 1 : RUN pip install --no-cache-dir -r requirements.txt
---> Using cache
Step 1 : COPY . /usr/src/app
---> 1d61f639ef9e
Removing intermediate container 4de6ddf5528c
Step 2 : EXPOSE 5000
---> Running in 12cfcf6d67ee
---> f423c2f179d1
Removing intermediate container 12cfcf6d67ee
Step 3 : CMD python ./app.py
---> Running in f01401a5ace9
---> 13e87ed1fbc2
Removing intermediate container f01401a5ace9
Successfully built 13e87ed1fbc2
در صورتی که ایمیج python:3 موجود نباشد، کلاینت ابتدا ایمیج را بیرون میکشد و سپس ایمیجی که قصد ایجاد آن وجود دارد را خواهد ساخت. بنابراین، ممکن است خروجی با آنچه در بالا آمده است متفاوت باشد. اگر همه چیز به خوبی پیش برود، ایمیج سفارشی مربوطه آماده خواهد بود.
سپس میتوان دستور «docker images» را اجرا و بررسی کرد که آیا ایمیج مربوطه نمایش داده خواهد شد؟ اولین گام در این مرحله این است که ایمیج اجرا و بررسی شود که آیا به درستی کار میکند؟ (باید نام کاربری مربوطه را با نام کاربری که در اینجا استفاده شده است جایگزین کرد):
$ docker run -p 8888:5000 yourusername/catnip
خروجی دستور فوق به صورت زیر است:
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
در دستوری که در بالا اجرا شد، از پورت ۵۰۰۰ برای سرور داخل کانتینر استفاده شده و این پورت به صورت خارجی روی پورت ۸۸۸۸ در معرض استفاده قرار گرفته است. اکنون با مراجعه به آدرس URL با پورت ۸۸۸۸ اپلیکیشن مربوطه باید مطابق شکل زیر در حال اجرا و آماده باشد:
به این ترتیب اولین ایمیج داکر ایجاد و این مرحله از آموزش داکر تکمیل شده است.
استقرار اپلیکیشن داکریزه شده روی سرویس ابری AWS در آموزش Docker
اپلیکیشنی که قابل اشتراکگذاری با دوستان نباشد، چندان کارایی ندارد. بنابراین در این بخش به نحوه استقرار اپلیکیشن مربوطه در فضای ابری پرداخته شده است تا از این طریق بتوان آن را با دیگران به اشتراک گذاشت. در این آموزش برای بارگذاری و اجرای اپلیکیشن از «AWS Elastic Beanstalk» استفاده شده است که فرآیند سادهای دارد و تنها با چند کلیک قابل پیادهسازی است.
همچنین، ملاحظه خواهد شد که مقایسپذیر کردن اپلیکیشن و سازگاری آن با میزان تقاضا با استفاده از Beanstalk بسیار ساده است.
نحوه انتشار ایمیج در رجیستری
اولین کاری که لازم است پیش از استقرار اپلیکیشن در AWS انجام شود این است که باید ایمیج مربوط به آن اپلیکیشن را در یک رجیستری منتشر کرد تا امکان دسترسی به این رجیستری به وسیله AWS وجود داشته باشد. بنابراین در ادامه این بخش از آموزش داکر به شرح نحوه انجام این کار پرداخته شده است.
رجیستریهای داکر بسیاری وجود دارند که میتوان از آنها استفاده کرد. حتی میتوان رجیستری مخصوص به خود را میزبانی کرد. در این آموزش از داکر هاب برای انتشار ایمیج مربوطه استفاده شده است. اگر اولین باری باشد که فرد یک ایمیج منتشر میکند، کلاینت از کاربر درخواست ورود خواهد کرد. باید همان اطلاعاتی را وارد کرد که برای ورود به داکر هاب استفاده میشود.
$ docker login
Login in with your Docker ID to push and pull images from Docker Hub. If you do not have a Docker ID, head over to https://hub.docker.com to create one.
Username: yourusername
Password:
WARNING! Your password will be stored unencrypted in /Users/yourusername/.docker/config.json
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/credential-store
Login Succeeded
استفاده از دستور push برای انتشار ایمیج
برای انتشار، تنها باید دستور زیر را وارد کرد و باید به یاد داشت که نام برچسب ایمیج مربوطه نیز باید با نام ایمیج سفارشی خود جایگزین شود. بسیار اهمیت دارد که قالب «yourusername/image_name» حفظ شود تا محل انتشار برای کلاینت مشخص باشد.
$ docker push yourusername/catnip
پس از اتمام کار، میتوان ایمیج مربوطه را در داکر هاب مشاهده کرد. برای مثال، صفحه وب مربوطه برای ایمیجی که در این آموزش استفاده شده از این لینک [+] قابل دسترسی است.
نکته: یک موردی که باید پیش از ادامه آموزش داکر روشن شود این است که برای استقرار در AWS، میزبانی ایمیج روی یک رجیستری عمومی (یا هر نوع رجیستری دیگری) الزامی نیست. به غیر از زمانی که کدهای مربوطه برای یک استارتاپ میلیون دلاری یونیکورن نوشته میشوند، میتوان به طور کامل از این مرحله (انتشار ایمیج روی یک رجیستری) صرف نظر کرد. دلیل اینکه ایمیج مورد نظر در این آموزش به صورت عمومی Push میشود این است که این کار فرآیند استقرار را به وسیله چند گام پیکربندی اندک بسیار سادهتر میکند.
اکنون که ایمیج مربوطه آنلاین شده است، هر فردی که داکر را نصب کرده باشد میتواند تنها با وارد کردن یک دستور واحد از اپلیکیشن مربوطه استفاده کند:
$ docker run -p 8888:5000 yourusername/catnip
در صورتی که در گذشته نگرانیهایی بابت راهاندازی محیطهای توسعه محلی یا به اشتراکگذاری پیکربندی اپلیکیشن وجود داشته است، اکنون به خوبی میتوان دریافت که این قابلیت چقدر هیجانانگیز به نظر میرسد. به همین دلیل است که داکر یک ابزار بسیار مفید و کاربردی به حساب میآید. با توجه به اینکه برای آموزش استقرار اپلیکیشن روی AWS از «AWS Elastic Beanstalk» استفاده شده، بهتر است در ادامه به شرح چیستی آن پرداخته شود.
Beanstalk چیست؟
AWS Elastic Beanstalk یا EB یک سکو به عنوان خدمت (PaaS | Platform as a Service) به حساب میآید که توسط AWS ارائه شده است. در صورتی که پیش از این از Heroku، موتور Google App یا سایر موارد استفاده شده باشد، کار با Beanstalk هم بسیار ساده خواهد بود.
به عنوان یک توسعه دهنده، تنها کافی است برای EB مشخص شود که چگونه باید اپلیکیشن مربوطه را اجرا کرد و Beanstalk ترتیب بقیه کارها شامل مقیاسبندی، نظارت (مانیتورینگ) و حتی بهروزرسانیها را میدهد. در اردیبهشت ۱۳۹۳ (آوریل ۲۰۱۴)، پشتیبانی از اجرای استقرارهای تک کانتینری داکر در EB اضافه شده است که از آن برای استقرار اپلیکیشن در این بخش از آموزش داکر استفاده خواهد شد.
اگرچه Beanstalk دارای یک واسط خط فرمان (CLI) شهودی و بصری است، نیاز به کمی تنظیمات وجود دارد و برای سادگی کار جهت اجرای اپلیکیشن مورد نظر در این آموزش از رابط وب استفاده شده است. برای همراهی با این آموزش نیاز به یک حساب کاربری فعال AWS وجود دارد. در صورتی که تا کنون حساب کاربری ایجاد نشده است، باید در این مرحله از آموزش داکر حتماً این کار را انجام داد. در این مرحله نیاز به وارد کردن اطلاعات کارت اعتباری وجود دارد. اگرچه همه کارهایی که در این آموزش انجام میشوند، جز خدمات رایگان AWS به حساب میآیند. حال در ادامه این بخش از آموزش داکر هر یک از گامهای مورد نیاز برای استقرار اپلیکیشن داکرایز شده روی سرویس ابری AWS شرح داده شدهاند.
مراحل استقرار اپلیکیشن داکرایز شده روی سرویس ابری AWS
هر یک از گامهای مورد نیاز برای استقرار اپلیکیشن داکرایز شده مربوطه در ادامه فهرست شدهاند:
- ابتدا باید وارد کنسول AWS شد.
- سپس باید روی Elastic Beanstalk کلیک کرد. این گزینه در بخش Compute در قسمت بالا سمت چپ قرار دارد. به جای آن میتوان از کنسول Elastic Beanstalk هم استفاده کرد.
- مطابق تصویر فوق، باید روی گزینه ایجاد اپلیکیشن جدید (Create New Application) در قسمت بالا سمت راست کلیک کرد.
- در این گام باید یک نام مناسب و خاص به اپلیکیشن مربوطه نسبت داده شود و همچنین میتوان در صورت تمایل توضیحات لازم را هم اضافه کرد.
- حال در صفحه محیط جدید، باید یک «محیط جدید» (New Environment) ایجاد و گزینه «محیط وب سرور» (Web Server Environment) را انتخاب کرد.
- در این مرحله باید با انتخاب یک دامنه، اطلاعات محیط داکر مربوطه را وارد کرد. این نشانی URL همان نشانی خواهد بود که قرار است با سایر افراد به اشتراک گذاشته شود. بنابراین باید یک نشانی ساده انتخاب کرد تا به خاطر سپردن آن آسان باشد.
- در بخش تنظیمات پایه (Base Configuration) باید گزینه Docker را از پلتفرم از پیش تعریف شده مربوطه انتخاب کرد.
- اکنون باید کدهای اپلیکیشن را آپلود کرد. اما با توجه به اینکه اپلیکیشن مربوطه در یک کانتینر داکر بستهبندی شده، تنها کافی است تا اطلاعات لازم در خصوص کانتینر مربوطه برای EB مشخص شود. باید فایل «Dockerrun.aws.json» را که در پوشه «flask-app» قرار دارد باز و نام (Name) ایمیج را ویرایش کرد و به نام ایمیج خود تغییر داد. جای نگرانی نیست؛ در ادامه این بخش از آموزش داکر پیرامون محتوای این فایل توضیحات لازم ارائه خواهند شد. پس از آنکه کار به اتمام رسید، باید روی دکمه مربوط به آپلود کردن کدهای خود (Upload your Code) کلیک کرد و سپس گزینه «Upload» را زد.
- حالا باید گزینه «Create Environment» را کلیک کرد. آخرین پنجرهای که مشاهده میشود، دایرهای چرخان است که نشان میدهد محیط داکر مربوطه در حال راهاندازی است. اولین راهاندازی معمولاً در حدود ۵ دقیقه زمان میبرد.
در ادامه این بخش از آموزش داکر به چیستی محتویات فایل «Dockerrun.aws.json» پرداخته شده است. به بیان ساده، این فایل یک فایل مختص AWS است که جزئیاتی را پیرامون اپلیکیشن توسعه داده شده و پیکربندی داکر در اختیار EB قرار میدهد.
{
"AWSEBDockerrunVersion": "1",
"Image": {
"Name": "prakhar1989/catnip",
"Update": "true"
},
"Ports": [
{
"ContainerPort": 5000,
"HostPort": 8000
}
],
"Logging": "/var/log/nginx"
}
این فایل به میزان زیادی بدیهی و خود توضیح دهنده است؛ اما همیشه نمیتوان برای اطلاعات بیشتر به مستندات رسمی ارجاع داد. نام ایمیجی که EB باید از آن استفاده کند به همراه پورتی که کانتینر باید باز کند فراهم شده است. پس از اتمام آمادهسازی محیط داکر مربوطه باید به صفحه EB رفت. در این صفحه باید یک علامت تیک سبز رنگ مشاهده شود. این تیک سبز نشان میدهد که اپلیکیشن مربوطه بارگذاری و مستقر شده است.
حال در ادامه باید URL مربوطه را در صفحه مرورگر باز کرد و به این ترتیب وارد اپلیکیشن خود شد.
پاک سازی
پس از آنکه آزمایش و تست اپلیکیشن به اتمام رسید، باید محیط داکر ایجاد شده را ملغی کرد تا به خاطر استفاده بیشتر منابع، نیاز به پرداخت هزینه وجود نداشته باشد. به این ترتیب در این بخش از آموزش داکر استقرار اولین اپلیکیشن داکر روی محیط ابری انجام شد. ممکن است به نظر برسد که گامهای بسیاری طی شدهاند، اما با استفاده از ابزار خط فرمان EB میتوان تا حد زیادی تنها با چند کلیک به همان قابلیتهای Heroku رسید. به احتمال زیاد اکثر افراد میپذیرند که داکر بسیاری از دردسرهای ساخت و استقرار اپلیکیشنها را در محیط ابری کاهش داده است. توصیه میشود مستندات AWS مربوط به محیطهای داکر با یک کانتینر مطالعه شوند تا ایده کلی نسبت به ویژگیها و قابلیتهای موجود به دست آید.
در بخش بعدی و پایانی آموزش داکر در این مقاله به مباحث پیچیدهتری پرداخته شده و اپلیکیشنی استقرار داده خواهد شد که به دنیای واقعی نزدیکتر است. این اپلیکیشن دارای یک لایه ذخیرهسازی پایدار بکاند است.
محیطهای دارای چند کانتینر در آموزش داکر
در بخش قبلی ملاحظه شد که چقدر اجرای اپلیکیشنها با داکر ساده و جذاب است. ابتدا آموزش داکر با یک وب سایت ایستای ساده آغاز و سپس یک اپلیکیشن فلسک پیادهسازی شد. ملاحظه شد که هر دوی این موارد به صورت محلی و در فضای ابری تنها با چند دستور قابل اجرا هستند. هر دوی این اپلیکیشنها تنها روی یک کانتینر اجرا میشدند. آن دسته از افرادی که تجربه اجرای سرویسهایی را به صورت تولیدی و تجاری دارند، مطلع هستند که امروزه اپلیکیشنها چندان ساده نیستند.
معمولاً همیشه یک بانک اطلاعاتی (یا هر نوع دیگری از یک محل ذخیره ثابت) وجود دارد. سیستمهایی مثل Redis و Memcached به روشهای پیچیدهای در معماری اکثر وب اپلیکیشنها تبدیل شدهاند. به همین سبب در این بخش از آموزش داکر به آموزش نحوه «داکریزه» (Dockerize) کردن اپلیکیشنهایی پرداخته شده است که یهسرویسهای مختلفی برای اجرا وابسته هستند.
چرا در یک کاربرد تحت وب از چند کانتینر استفاده میشود؟
به طور خاص در این بخش از آموزش داکر به نحوه اجرا و مدیریت محیطهای داکر چند کانتینری پرداخته شده است. ممکن است این سوال به وجود بیاید که چرا از چند کانتینر استفاده میشود؟ در پاسخ باید گفت که یکی از اهداف کلیدی داکر فراهم کردن ایزولگی است. ایده ترکیب کردن یک پردازه با متعلقات و وابستگیهای آن در یک Sandbox که به آن کانتینر گفته میشود، آن چیزی است که داکر را به یک فناوری قدرتمند تبدیل کرده است.
درست همانطور که جداسازی لایههای اپلیکیشن راهبرد مطلوبی به حساب میآید، جداسازی کانتینرها برای هر یک از سرویسها نیز کار عاقلانهای است. هر لایه ممکن است نیاز به منابع متفاوتی داشته باشد و آن نیازها ممکن است در نرخهای متفاوتی رشد کنند. با جداسازی لایهها به کانتینرهای مختلف میتوان هر لایه را با استفاده از مناسبترین نوع نمونه بر اساس نیاز به منابع مختلف ایجاد کرد. این شیوه همچنین با سیر میکروسرویسها نیز سازگاری مطلوبی دارد. به همین دلیل است که داکر یا هر نوع فناوری کانتینر دیگری در خط مقدم معماری میکروسرویسهای مدرن قرار میگیرد.
آموزش استقرار اپلیکیشن در محیط چند کانتینری
اپلیکیشنی که قرار است در این بخش از آموزش داکر به اصطلاح «داکریزه» شود، «SF Food Trucks» نام دارد. هدف ساخت و استفاده از اپلیکیشن Food Trucks این است که پروژهای کاربردی (مشابه یک اپلیکیشن واقعی) ارائه شود، حداقل به یک سرویس وابستگی داشته باشد و در عین حال خیلی پیچیده هم نباشد. اپلیکیشن SF Food Trucks به همین دلیل انتخاب شده است.
بکاند این اپلیکیشن به زبان پایتون (فلسک) نوشته شده و برای جستجو از موتور جستجوی «Elasticsearch» یا همان «ES» استفاده شده است. درست مثل سایر بخشهای آموزش داکر در این مقاله، تمام کد منبع آن در گیتهاب [+] در دسترس است.
از این اپلیکیشن به عنوان نمونه برای آموزش نحوه ساخت، اجرا و استقرار یک محیط با چند کانتینر استفاده خواهد شد. اول از همه باید یک نسخه محلی همسان از شاخه مربوطه ایجاد و به اصطلاح آن را Clone کرد:
$ git clone https://github.com/prakhar1989/FoodTrucks
$ cd FoodTrucks
$ tree -L 2
.
├── Dockerfile
├── README.md
├── aws-compose.yml
├── docker-compose.yml
├── flask-app
│ ├── app.py
│ ├── package-lock.json
│ ├── package.json
│ ├── requirements.txt
│ ├── static
│ ├── templates
│ └── webpack.config.js
├── setup-aws-ecs.sh
├── setup-docker.sh
├── shot.png
└── utils
├── generate_geojson.py
└── trucks.geojson
پوشه «flask-app» حاوی اپلیکیشن ایجاد شده با پایتون و پوشه «utils» دارای برنامههای کمکی برای بارگذاری دادهها در Elasticsearch است. همچنین، این شاخه تعدادی فایل «YAML» و یک Dockerfile را شامل میشود که همه آنها با جزئیات بیشتری در ادامه آموزش داکر در این مقاله شرح داده خواهند شد. در صورتی که کنجکاوی در این زمینه وجود دارد، میتوان نگاهی به این فایلها انداخت.
داکریزه کردن اپلیکیشن SF Food Trucks
حال در ادامه به نحوه داکریزه کردن اپلیکیشن مربوطه پرداخته میشود. این اپلیکیشن حاوی یک سرور بکاند مبتنی بر فلسک و یک سرویس Elasticsearch است. یک راه معمول برای کانتینربندی این اپلیکیشن این است که از دو کانتینر استفاده شود. یکی از این کانتینرها برای پردازه فلسک و دیگری هم برای پردازه Elasticsearch استفاده خواهد شد.
به این روش در صورت استقبال از این اپلیکیشن و محبوبیت آن، میتوان با افزودن کانتینرهای بیشتر مقیاس آن را بسته به این مسئله گسترش داد که در کدام بخش تنگنا وجود دارد. بنابراین فعلاً تنها به ۲ کانتینر نیاز است. پیشتر برای آموزش داکر در این مقاله نحوه استقرار روی یک کانتینر شرح داده شد. بنابراین، استقرار اپلیکیشن روی چند کانتینر هم نباید چندان دشوار باشد. اکنون باید در داکر هاب جستجو کرد که آیا ایمیج آمادهای برای Elasticsearch وجود دارد؟ این کار به وسیله دستور زیر انجام میشود:
$ docker search elasticsearch
خروجی دستور فوق به صورت زیر است:
AME DESCRIPTION STARS OFFICIAL AUTOMATED
elasticsearch Elasticsearch is a powerful open source se... 697 [OK]
itzg/elasticsearch Provides an easily configurable Elasticsea... 17 [OK]
tutum/elasticsearch Elasticsearch image - listens in port 9200. 15 [OK]
barnybug/elasticsearch Latest Elasticsearch 1.7.2 and previous re... 15 [OK]
digitalwonderland/elasticsearch Latest Elasticsearch with Marvel & Kibana 12 [OK]
monsantoco/elasticsearch ElasticSearch Docker image 9 [OK]
با کمال شگفتی ملاحظه میشود که یک ایمیج آماده با پشتیبانی رسمی برای Elasticsearch در داکر هاب موجود است. برای آنکه بتوان ES را اجرا کرد، میتوان به سادگی و خیلی سریع از دستور «docker run» استفاده کرد و یک کانتینر ES تک گرهایی (Single-Node) را به صورت محلی اجرا کرد.
نکته: Elastic، شرکتی که Elasticsearch را ایجاد کرده است، رجیستری مربوط به خودش را برای محصولات Elastic نگهداری میکند. توصیه میشود در صورتی که قصد بهکارگیری Elasticsearch وجود دارد، از ایمیجهای رجیستری رسمی استفاده شود.
ابتدا باید ایمیج مربوطه را بیرون کشید و به اصطلاح Pull کرد:
$ docker pull docker.elastic.co/elasticsearch/elasticsearch:6.3.2
سپس باید ایمیج مربوطه را با تعیین پورتها و تنظیم یک متغیر محیطی (Environment Variable) اجرا کرد که خوشه Elasticsearch را برای اجرا به عنوان یک گره تکی پیکربندی میکند:
$ docker run -d --name es -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:6.3.2
نکته: در صورتی که کانتینر مربوطه با مشکلات امنیتی مواجه شود، ممکن است نیاز به تغییر برخی تنظیمات در پرچمهای JVM برای محدود کردن مصرف حافظه آن به وجود بیاید.
همانطور که پیش از این اشاره شد، از دستور «–name es» برای نامگذاری کانتینر استفاده میشود که استفاده از آن را در دستورهای متعاقب آسان میسازد. بعد از اینکه کانتینر اجرا شد، میتوان رویدادنگاریها (لاگها) را با اجرای دستور «docker container logs» به همراه نام کانتینر یا شناسه آن برای بررسی لاگها مشاهده کرد. در صورتی که Elasticsearch با موفقیت اجرا شده باشد، باید لاگهایی مشابه آنچه در ادامه آمده است مشاهده شوند:
نکته: اجرای Elasticsearch ممکن است چند ثانیهای زمان ببرد، بنابراین احتمالاً باید برای ظاهر شدن عبارت «initialized» صبر کرد.
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
277451c15ec1 docker.elastic.co/elasticsearch/elasticsearch:6.3.2 "/usr/local/bin/dock…" 2 minutes ago Up 2 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp es
$ docker container logs es
[2018-07-29T05:49:09,304][INFO ][o.e.n.Node ] [] initializing ...
[2018-07-29T05:49:09,385][INFO ][o.e.e.NodeEnvironment ] [L1VMyzt] using [1] data paths, mounts [[/ (overlay)]], net usable_space [54.1gb], net total_space [62.7gb], types [overlay]
[2018-07-29T05:49:09,385][INFO ][o.e.e.NodeEnvironment ] [L1VMyzt] heap size [990.7mb], compressed ordinary object pointers [true]
[2018-07-29T05:49:11,979][INFO ][o.e.p.PluginsService ] [L1VMyzt] loaded module [x-pack-security]
[2018-07-29T05:49:11,980][INFO ][o.e.p.PluginsService ] [L1VMyzt] loaded module [x-pack-sql]
[2018-07-29T05:49:11,980][INFO ][o.e.p.PluginsService ] [L1VMyzt] loaded module [x-pack-upgrade]
[2018-07-29T05:49:11,980][INFO ][o.e.p.PluginsService ] [L1VMyzt] loaded module [x-pack-watcher]
[2018-07-29T05:49:11,981][INFO ][o.e.p.PluginsService ] [L1VMyzt] loaded plugin [ingest-geoip]
[2018-07-29T05:49:11,981][INFO ][o.e.p.PluginsService ] [L1VMyzt] loaded plugin [ingest-user-agent]
[2018-07-29T05:49:17,659][INFO ][o.e.d.DiscoveryModule ] [L1VMyzt] using discovery type [single-node]
[2018-07-29T05:49:18,962][INFO ][o.e.n.Node ] [L1VMyzt] initialized
[2018-07-29T05:49:18,963][INFO ][o.e.n.Node ] [L1VMyzt] starting ...
[2018-07-29T05:49:19,218][INFO ][o.e.t.TransportService ] [L1VMyzt] publish_address {172.17.0.2:9300}, bound_addresses {0.0.0.0:9300}
[2018-07-29T05:49:19,302][INFO ][o.e.x.s.t.n.SecurityNetty4HttpServerTransport] [L1VMyzt] publish_address {172.17.0.2:9200}, bound_addresses {0.0.0.0:9200}
[2018-07-29T05:49:19,303][INFO ][o.e.n.Node ] [L1VMyzt] started
[2018-07-29T05:49:19,439][WARN ][o.e.x.s.a.s.m.NativeRoleMappingStore] [L1VMyzt] Failed to clear cache for realms [[]]
[2018-07-29T05:49:19,542][INFO ][o.e.g.GatewayService ] [L1VMyzt] recovered [0] indices into cluster_state
بررسی امکان ارسال درخواست به کانتینر ES
اکنون بهتر است بررسی شود که آیا میتوان درخواستی به کانتینر Elasticsearch ارسال کرد؟ برای ارسال یک درخواست «cURL» به کانتینر از پورت 9200 استفاده میشود:
$ curl 0.0.0.0:9200
{
"name" : "ijJDAOm",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "a_nSV3XmTCqpzYYzb-LhNw",
"version" : {
"number" : "6.3.2",
"build_flavor" : "default",
"build_type" : "tar",
"build_hash" : "053779d",
"build_date" : "2018-07-20T05:20:23.451332Z",
"build_snapshot" : false,
"lucene_version" : "7.3.1",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
اکنون باید کانتینر فلسک خود را هم اجرا کرد. اما پیش از انجام این کار، نیاز به یک Dockerfile وجود دارد.
ایجاد Docker File برای پروژه
در بخش قبلی از ایمیجهای «python:3» به عنوان ایمیج پایه استفاده شد. این بار، اگر چه، جدای از نصب متعلقات پایتون از طریق «pip»، لازم است که اپلیکیشن مربوطه فایل جاوا اسکریپت کوچک شده برای انتشار را هم تولید کند. برای این مسئله باید از Nodejs استفاده شود. با توجه به اینکه نیاز به یک گام شخصیسازی شده وجود دارد، برای ایجاد فایل داکر از صفر، باید کار را از ایمیج پایه ubuntu آغاز کرد.
نکته: در صورتی که مشخص شود یک ایمیج موجود نیازهای مربوطه را برآورده نمیکند، باید یک ایمیج پایه دیگر را استارت زد و فرد باید خودش آن را اصلاح و تغییرات لازم را در آن اعمال کند. اگرچه، برای اکثر ایمیجها در داکر هاب، باید بتوان Dockerfile متناظر را در گیتهاب پیدا کرد.
خواندن Dockerfileها یکی از بهترین روشها برای یادگیری نحوه ایجاد و آمادهسازی Dockerfileهای سفارشی و شخصی مربوط به خود فرد است. Dockerfile سفارشیسازی شده مربوط به اپلیکیشن فلسک باید به صورت کدهای زیر باشد:
# شروع کار با ایمیج پایه
FROM ubuntu:18.04
MAINTAINER Prakhar Srivastav
# نصب متعلقات سراسری در سیستم برای پایتون و گره
RUN apt-get -yqq update
RUN apt-get -yqq install python3-pip python3-dev curl gnupg
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash
RUN apt-get install -yq nodejs
# کپی کردن کدهای اپلیکیشن مربوطه
ADD flask-app /opt/flask-app
WORKDIR /opt/flask-app
# دریافت متعلقات مختص اپلیکیشن
RUN npm install
RUN npm run build
RUN pip3 install -r requirements.txt
# در معرض استفاده قرار دادن پورت
EXPOSE 5000
# راهاندازی و استارت زدن اپلیکیشن
CMD [ "python3", "./app.py" ]
در کدهای فوق (فایل داکر مربوطه)، برخی موارد جدید وجود دارند. بنابراین بهتر است توضیحاتی در مورد آنها ارائه شود. ابتدا کار با ایمیج پایه Ubuntu LTS آغاز و از مدیر بسته apt-get برای نصب متعلقات مربوطه یعنی Python و Node استفاده خواهد شد. پرچم «yqq» برای حذف خروجی استفاده میشود و همه اعلانها (Prompt) را «Yes» در نظر میگیرد. سپس از دستور «ADD» برای کپی کردن اپلیکیشن خود در داخل یک Volume در کانتینر در محل «/opt/flask-app» استفاده میشود. کدهای مربوطه در این محل قرار خواهند گرفت. همچنین، این محل به عنوان شاخه کاری تنظیم خواهد شد تا اینکه دستورات بعدی در چارچوب این موقعیت اجرا شوند. اکنون که متعلقات سطح سیستمی نصب شدهاند، نوبت به نصب متعلقات مختص اپلیکیشن فرا میرسد.
نصب متعلقات مختص اپلیکیشن
اول از همه در خصوص Node باید با نصب بستهها (پکیجها) از nmp و اجرای دستور build به همان شکلی استفاده کرد که در فایل package.json تعریف شده است.
این مرحله با نصب بستههای پایتون، در معرض دسترس قرار دادن پورت و تعریف CMD برای اجرا همانطور که در بخش قبلی انجام شد به اتمام میرسد. در نهایت میتوان ادامه داد، ایمیج را ساخت و کانتینر را هم اجرا کرد (باید شناسه کاربری خود را به جای prakhar1989 قرار داد):
$ docker build -t prakhar1989/foodtrucks-web .
در اولین اجرا، کمی زمان خواهد برد تا کلاینت داکر ایمیج Ubuntu را دانلود، تمام دستورات را اجرا و ایمیج خود را آمادهسازی کند. اجرای مجدد دستور «docker build» پس از تغییرات بعدی که روی اپلیکیشن ایجاد میشوند تقریباً بلافاصله انجام خواهد شد. حال در ادامه اپلیکیشن مربوطه اجرا میشود.
$ docker run -P --rm prakhar1989/foodtrucks-web
خروجی دستور فوق به صورت زیر است:
Unable to connect to ES. Retying in 5 secs...
Unable to connect to ES. Retying in 5 secs...
Unable to connect to ES. Retying in 5 secs...
Out of retries. Bailing out...
همانطور که در خروجی دستور اجرای اپلیکیشن ملاحظه میشود، به دلیل اینکه اپلیکیشن فلسک مربوطه امکان اتصال به Elasticsearch را نداشته، خطایی به وجود آمده و اجرا به درستی انجام نشده است. چگونه میتوان یک کانتینر را از وجود دیگری مطلع کرد؟ پاسخ به این سوال در بخش بعدی این مقاله آموزش داکر شرح داده شده است.
شبکه داکر در آموزش استفاده از چند کانتینر
پیش از آنکه پیرامون قابلیتهایی بحث شود که داکر خصوصاً برای چنین شرایطی (سناریوهایی) فراهم میکند، باید بررسی کرد که آیا میتوان راهی برای دور زدن و رفع خطای بالا یافت؟ پس باید دستور «docker container ls» را اجرا کرد (که مشابه دستور docker ps) است و سپس باید بررسی شود که چه کانتینرهایی در دسترس قرار دارند:
$ docker container ls
خروجی به صورت زیر است:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
277451c15ec1 docker.elastic.co/elasticsearch/elasticsearch:6.3.2 "/usr/local/bin/dock…" 17 minutes ago Up 17 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp es
بنابراین یک کانتینر ES در پورت «0.0.0.0:9200» وجود دارد که میتوان مستقیماً به آن دسترسی پیدا کرد. اگر بتوان برای اپلیکیشن فلسک خود معین کرد که به این نشانی URL وصل شود، باید بتوان به ES متصل شد و با آن ارتباط برقرار کرد. اکنون باید به سراغ کدهای پایتون رفت و بررسی کرد که جزئیات اتصال چگونه تعریف شدهاند:
es = Elasticsearch(host='es')
جهت انجام این کار، باید برای کانتینر فلسک تعیین شود که کانتینر ES روی میزبان «0.0.0.0» در حال اجرا است (پورت پیشفرض: 9200) و به این ترتیب همه چیز باید به درستی کار کند. اما متاسفانه این چنین نیست. زیرا نشانی آیپی «0.0.0.0» برای دسترسی به کانتینر ES از ماشین میزبان یعنی کامپیوتر شخصی فرد استفاده میشود.
یک کانتینر دیگر امکان دسترسی به آن را در همان نشانی IP نخواهد داشت. اگر آن IP نه، پس کانتینر ES باید به وسیله کدام IP در دسترس باشد؟ اکنون زمان مناسبی برای شروع جستجو و اکتشاف در داکر است. وقتی که داکر نصب میشود، سه شبکه را به طور خودکار ایجاد میکند:
$ docker network ls
میتوان با استفاده از دستور فوق، اطلاعات مربوط به سه شبکه پیشفرض ایجاد شده توسط داکر را مطابق خروجی زیر ملاحظه کرد:
NETWORK ID NAME DRIVER SCOPE
c2c695315b3a bridge bridge local
a875bec5d6fd host host local
ead0e804a67b none null local
شبکه bridge شبکهای است که در آن کانتینرها به صورت پیشفرض اجرا میشوند. لذا این بدان معناست که وقتی کانتینر ES اجرا شد، در واقع روی این شبکه bridge در حال اجرا بود. برای تایید صحت این مسئله، بهتر است شبکه را وارسی (Inspect) کرد. این کار با استفاده از دستور زیر انجام میشود:
$ docker network inspect bridge
خروجی به صورت زیر است:
[
{
"Name": "bridge",
"Id": "c2c695315b3aaf8fc30530bb3c6b8f6692cedd5cc7579663f0550dfdd21c9a26",
"Created": "2018-07-28T20:32:39.405687265Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"277451c15ec183dd939e80298ea4bcf55050328a39b04124b387d668e3ed3943": {
"Name": "es",
"EndpointID": "5c417a2fc6b13d8ec97b76bbd54aaf3ee2d48f328c3f7279ee335174fbb4d6bb",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
میتوان ملاحظه کرد که کانتینر مربوطه با شناسه «277451c15ec1» در قسمت کانتینرها یعنی Containers در خروجی بالا فهرست شده است. آنچه که علاوه بر این ملاحظه میشود، نشانی IP این کانتینر یعنی «172.17.0.2» است. آیا این همان نشانی IP مورد نظر است؟ برای اطمینان از این مسئله باید کانتینر فلسک را به صورت زیر اجرا کرد و سعی در دسترسی به این IP داشت:
$ docker run -it --rm prakhar1989/foodtrucks-web bash
خروجی دستور فوق در ادامه آمده است:
root@35180ccc206a:/opt/flask-app# curl 172.17.0.2:9200
{
"name" : "Jane Foster",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.1.1",
"build_hash" : "40e2c53a6b6c2972b3d13846e450e66f4375bd71",
"build_timestamp" : "2015-12-15T13:05:55Z",
"build_snapshot" : false,
"lucene_version" : "5.3.1"
},
"tagline" : "You Know, for Search"
}
root@35180ccc206a:/opt/flask-app# exit
با بررسی خروجی فوق همه چیز مشخص میشود؛ کانتینر مربوطه در حالت تعاملی با پردازه «bash» آغاز میشود. «–rm» یک پرچم مناسب برای اجرای آن از طریق دستوری است، زیرا وقتی کار کانتینر تمام شود، پاکسازی خواهد شد. از دستور curl استفاده میشود، اما ابتدا باید آن را نصب کرد. پس از انجام این کار، ملاحظه خواهد شد که میتوان با ES روی سوکت «172.17.0.2:9200» در ارتباط بود. با وجود اینکه راهی برای واداشتن کانتینرها جهت ارتباط با یکدیگر پیدا شده است، اما در این رویکرد دو مشکل وجود دارد:
- چگونه میتوان برای کانتینر فلسک مشخص کرد که منظور از نام میزبان es نشانی آیپی «172.17.0.2» است؟
- با توجه به اینکه شبکه بریج به صورت پیشفرض توسط هر یک از کانتینرها به اشتراک گذاشته شده است، این روش ایمن نیست. چگونه میتوان شبکه خود را ایزوله کرد؟
خبر خوب این است که داکر پاسخ مناسبی برای این سوال ارائه کرده است. داکر به کاربر اجازه میدهد تا با محفظه ایزولگی شبکههای مربوط به خودش را با استفاده از دستور «docker network» تعریف کند. ابتدا باید یک شبکه ایجاد شود. برای انجام این کار باید از دستور زیر استفاده کرد:
$ docker network create foodtrucks-net
خروجی دستور فوق به صورت زیر است:
0815b2a3bb7a6608e850d05553cc0bda98187c4528d94621438f31d97a6fea3c
برای مشاهده شبکههای ایجاد شده از دستور زیر استفاده میشود که خروجی آن نیز در ادامه دستور ملاحظه میشود:
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
c2c695315b3a bridge bridge local
0815b2a3bb7a foodtrucks-net bridge local
a875bec5d6fd host host local
ead0e804a67b none null local
ایجاد شبکه بریج
دستور «network create» منجر به ایجاد یک شبکه بریج جدید میشود. در حوزه داکر، یک شبکه بریج از یک بریج نرم افزاری استفاده میکند که به کانتینرهای متصل به همان شبکه بریج اجازه میدهد تا با یکدیگر ارتباط برقرار کنند و در عین حال، ایزولگی لازم در برابر کانتینرهایی که به شبکه بریج متصل نیستند هم فراهم میشود.
درایور بریج داکر به طور خودکار قوانینی را در ماشین میزبان نصب میکند تا کانتینرهایی که در شبکههای بریج متفاوت هستند نتوانند با یکدیگر ارتباط برقرار کنند.
انواع شبکه دیگری هم وجود دارند که میتوان آنها را ایجاد کرد و میتوان اطلاعات بیشتر در خصوص آنها را در مستندات رسمی یافت. اکنون که یک شبکه ایجاد شده است، میتوان کانتینرهای مربوطه را در داخل این شبکه با استفاده از پرچم «–net» راهاندازی (Launch) کرد. برای راهاندازی یک کانتینر جدید با نام یکسان، باید کانتینر ES که در شبکه (پیشفرض) بریج در حال اجرا است را متوقف و حذف کرد.
$ docker container stop es
es
$ docker container rm es
es
$ docker run -d --name es --net foodtrucks-net -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:6.3.2
13d6415f73c8d88bddb1f236f584b63dbaf2c3051f09863a3f1ba219edba3673
$ docker network inspect foodtrucks-net
[
{
"Name": "foodtrucks-net",
"Id": "0815b2a3bb7a6608e850d05553cc0bda98187c4528d94621438f31d97a6fea3c",
"Created": "2018-07-30T00:01:29.1500984Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"13d6415f73c8d88bddb1f236f584b63dbaf2c3051f09863a3f1ba219edba3673": {
"Name": "es",
"EndpointID": "29ba2d33f9713e57eb6b38db41d656e4ee2c53e4a2f7cf636bdca0ec59cd3aa7",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
همانطور که ملاحظه میشود، کانتینر es اکنون در حال اجرا در داخل شبکه بریج «foodtrucks-net» است. حال باید بررسی شود که چه اتفاقی میافتد وقتی در شبکه «foodtrucks-net» راهاندازی انجام میشود؟ در کدهای زیر ابتدا دستور مربوطه و سپس خروجی آن قابل ملاحظه است:
$ docker run -it --rm --net foodtrucks-net prakhar1989/foodtrucks-web bash
root@9d2722cf282c:/opt/flask-app# curl es:9200
{
"name" : "wWALl9M",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "BA36XuOiRPaghPNBLBHleQ",
"version" : {
"number" : "6.3.2",
"build_flavor" : "default",
"build_type" : "tar",
"build_hash" : "053779d",
"build_date" : "2018-07-20T05:20:23.451332Z",
"build_snapshot" : false,
"lucene_version" : "7.3.1",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
root@53af252b771a:/opt/flask-app# ls
app.py node_modules package.json requirements.txt static templates webpack.config.js
root@53af252b771a:/opt/flask-app# python3 app.py
Index not found...
Loading data in elasticsearch ...
Total trucks loaded: 733
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
root@53af252b771a:/opt/flask-app# exit
همانطور که در کدهای فوق قابل ملاحظه است، همه چیز به درستی کار میکند. در شبکههای تعریف شده توسط کاربر مثل Food Trucks-Net، نه تنها کانتینرها میتوانند از طریق نشانی آیپی ارتباط برقرار کنند، بلکه میتوان نام یک کانتینر را به نشانی آدرس آن نگاشت کرد. این قابلیت شناسایی سرویس خودکار (Automatic Service Discovery) نام دارد. حال در ادامه کانتینر فلسک مورد نظر اجرا شده است:
$ docker run -d --net foodtrucks-net -p 5000:5000 --name foodtrucks-web prakhar1989/foodtrucks-web
852fc74de2954bb72471b858dce64d764181dca0cf7693fed201d76da33df794
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
852fc74de295 prakhar1989/foodtrucks-web "python3 ./app.py" About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp foodtrucks-web
13d6415f73c8 docker.elastic.co/elasticsearch/elasticsearch:6.3.2 "/usr/local/bin/dock…" 17 minutes ago Up 17 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp es
$ curl -I 0.0.0.0:5000
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 3697
Server: Werkzeug/0.11.2 Python/2.7.6
Date: Sun, 10 Jan 2016 23:58:53 GMT
اکنون با مراجعه به نشانی «http://0.0.0.0:5000»، میتوان ملاحظه کرد که اپلیکیشن مربوطه در حال اجرا و مستقر (Live) است. اگر چه احتمال دارد به نظر برسد که فرآیند دشوار و طولانی طی شده است، اما در واقع از گام نخست تا مرحله اجرا تنها از ۴ دستور استفاده شد. این دستورات در یک اسکریپت Bash به صورت زیر گردآوری شدهاند:
# ساخت کانتینر فلسک
docker build -t prakhar1989/foodtrucks-web .
# ایجاد شبکه
docker network create foodtrucks-net
# راهاندازی کانتینر ES
docker run -d --name es --net foodtrucks-net -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:6.3.2
# راهاندازی کانتینر اپلیکیشن فلسک
docker run -d --net foodtrucks-net -p 5000:5000 --name foodtrucks-web prakhar1989/foodtrucks-web
اکنون باید تصور کرد که قرار است اپلیکیشن مربوطه برای اشخاص دیگری توزیع یا این اپلیکیشن روی سروری اجرا شود که داکر در آن نصب شده است:
$ git clone https://github.com/prakhar1989/FoodTrucks
$ cd FoodTrucks
$ ./setup-docker.sh
و به این ترتیب کار به اتمام رسیده است. این یک روش بسیار عالی و قدرتمند برای به اشتراک گذاری و اجرای اپلیکیشنها به حساب میآید.
ابزارهای رایج مورد استفاده در داکر
همه مواردی که تا این بخش از آموزش داکر بیان شدند به کلاینت داکر (Docker Client) اختصاص داشتند. اگرچه در زیستبوم داکر ، تعدادی ابزار متنباز دیگر هم وجود دارند که استفاده از آنها به همراه داکر بسیار مفید و کاربردی است.
برخی از این ابزارها در ادامه فهرست شدهاند:
- Docker Machine : این ابزار برای ایجاد میزبانهای داکر روی کامپیوتر فرد در فضای ارائه دهندگان ابری و داخل مرکز داده خصوصی استفاده میشود.
- Docker Compose : ابزاری است که برای تعریف و اجرای اپلیکیشنهای چند کانتینری استفاده میشود.
- Docker Swarm : این ابزار یک راهکار خوشهبندی بومی را برای داکر ارائه میدهد.
- Kubernetes : یک سیستم متنباز است که برای خودکارسازی استقرارها، سازگاری مقیاس و مدیریت اپلیکیشنهای کانتینربندی شده استفاده میشود.
در بخش بعدی آموزش داکر به معرفی یکی از این ابزارها یعنی Docker Compose پرداخته شده است و ملاحظه خواهد شد که چگونه کار با اپلیکیشنهای چند کانتینری به وسیله این ابزار سادهتر میشود.
ابزار Docker Compose چیست ؟
پیش از شرح چیستی Docker Compose و کاربرد آن در آموزش داکر، بهتر است ابتدا توضیحاتی پیرامون نحوه شکلگیری آن ارائه شود. این کار در ادامه این بخش از آموزش داکر صورت گرفته است.
Docker Compose چگونه به وجود آمد؟
داستان نهفته در پس Docker Compose، بسیار جذاب است. تقریباً در حدود سال ۱۳۹۳ (۲۰۱۴ میلادی) شرکتی به نام OrchardUp ابزاری را به نام Fig منتشر کرد. ایده ارائه Fig این بود که محیطهای توسعه ایزوله شده با داکر کار کنند. از این پروژه در وبسایت «Hacker News» به خوبی استقبال شد. در اولین نظری که در انجمن Hacker News برای Fig ثبت شده است به خوبی میتوان دریافت که Fig درباره چیست:
در این مقطع، داکر به اجرای پردازهها مربوط میشود. در حال حاضر داکر یک API غنی برای اجرای پردازهها ارائه میکند. Volumeها یا همان دایرکتوریهای به اشتراک گذاشته شده بین کانتینرها (که همان اجرای ایمیجها است)، پورت را از میزبان به کانتینر هدایت میکنند، لاگها را نمایش و کارهای دیگری را هم انجام میدهند. اما همهاش همین است، یعنی داکر تا این لحظه در سطح پردازهای باقی مانده است.
در حالی که داکر گزینههایی را برای هماهنگ کردن چند کانتینر جهت ایجاد یک اپلیکیشن واحد فراهم میکند، مدیریت چنین گروههایی از کانتینرها به عنوان یک موجودیت واحد خطاب قرار داده نشده است. اینجاست که کاربرد ابزارهایی مثل Fig یعنی در نظر گرفتن گروهی از کانتینرها به عنوان یک موجودیت واحد مشخص میشود. یعنی در آن دیدگاه به این صورت است که به جای اجرای یک کانتینر، اجرای یک اپلیکیشن کامل (که همان اجرای خوشهای هماهنگ از کانتینرها است) در نظر گرفته میشود.
به نظر میرسد افراد بسیاری که از داکر استفاده میکنند با این انتظارات موافق هستند. درست مثل Fig، شرکت داکر هم به آرامی و به تدریج به محبوبیت رسید، دیده شد، Fig را تصاحب کرد و نام تجاری آن را به «Docker Compose» تغییر داد. حالا این سوال ممکن است به وجود بیاید که Docker Compose چه کاربردی دارد و برای چه کاری استفاده میشود؟
Docker Compose چیست و چه کاربردی دارد؟
Compose ابزاری است که برای تعریف و اجرای اپلیکیشنهای چند کانتینری به شکلی ساده مورد استفاده قرار میگیرد. این ابزار یک فایل پیکربندی به نام «docker-compose.yml» فراهم میکند که میتوان از آن تنها با یک دستور برای استقرار یک اپلیکیشن و مجموعه سرویسهایی استفاده کرد که به آنها وابسته است.
Compose در تمام محیطها کار میکند. هر یک از این محیطها در ادامه فهرست شدهاند:
- تولید (Production)
- صحنه پردازی (Staging)
- توسعه (Development)
- آزمایش (Testing)
- به همراه جریانهای کاری CI
اگرچه، باید گفته که Compose بیشتر برای محیطهای توسعه و تست ایدهآل است. حال در ادامه آموزش داکر به ایجاد یک فایل docker-compose.yml برای اپلیکیشن SF-Foodtrucks پرداخته شده است و بررسی میشود که آیا Docker Compose کارایی لازم را دارد؟
مثال عملی برای Docker Compose
اولین گام، نصب Docker Compose است. در صورتی که از سیستم عاملهای ویندوز یا مک استفاده میشود، Docker Compose از قبل نصب شده است؛ زیرا Docker Compose در جعبه ابزار داکر یا همان Docker Toolbox وجود دارد. کاربران لینوکس نیز میتوانند به راحتی با دنبال کردن دستورالعملهای موجود در مستندات آن، آشنایی لازم و نحوه کار با Docker Compose را به دست آورند. با توجه به اینکه Compose با زبان پایتون نوشته شده است، همچنین میتوان به راحتی از دستور «pip install docker-compose» استفاده کرد. برای آزمایش نصب شدن صحیح Compose از دستور زیر استفاده میشود که خروجی آن هم در خط بعد از آن آمده است:
$ docker-compose --version
docker-compose version 1.21.2, build a133471
اکنون پس از نصب Docker Compose میتوان به مرحله بعدی رفت. در این مرحله، فایل Docker Compose یعنی «docker-compose.yml» بررسی شده است. سینتکس YAML تقریباً ساده و مخزن (Repository | Repo) از قبل حاوی فایل docker-compose است که باید از آن استفاده شود. محتویات فایل Docker Compose به صورت زیر است:
version: "3"
services:
es:
image: docker.elastic.co/elasticsearch/elasticsearch:6.3.2
container_name: es
environment:
- discovery.type=single-node
ports:
- 9200:9200
volumes:
- esdata1:/usr/share/elasticsearch/data
web:
image: prakhar1989/foodtrucks-web
command: python3 app.py
depends_on:
- es
ports:
- 5000:5000
volumes:
- ./flask-app:/opt/flask-app
volumes:
esdata1:
driver: local
توضیح فایل Docker Compose
اکنون بهتر است توضیحات بیشتری پیرامون محتویات فایل Docker Compose ارائه شود. در سطح والد، نام سرویسهای مربوطه یعنی es و web تعریف میشوند. پارامتر image همیشه ضروری است و برای هر سرویسی که میخواهیم داکر آن را اجرا کند، میتوان پارامترهای بیشتری اضافه کرد. برای es تنها به ایمیج elasticsearch ارجاع داده میشود. این ایمیج در رجیستری Elastic در دسترس است. برای اپلیکیشن فلسک مورد نظر به آن ایمیجی ارجاع داده میشود که در ابتدای این بخش از آموزش داکر ساخته شد. سایر پارامترها از جمله command و ports اطلاعات بیشتری را در خصوص کانتینر مربوطه فراهم میکنند. پارامتر volumes یک نقطه نصب (Mount Point) را در کانتینر web در جایی تعیین میکند که کدها قرار دارند.
این مورد کاملاً اختیاری است و در صورتی کاربرد دارد که نیاز به دسترسی به لاگها یا سایر موارد وجود داشته باشد. در ادامه ملاحظه خواهد شد که این مورد چطور میتواند در طول توسعه کاربردی و مفید باشد. میتوان برای یادگیری بیشتر در خصوص پارامترهایی که فایل Docker Compose از آنها پشتیبانی میکنند به مراجع و منابع آنلاین مراجعه کرد. علاوه بر این، volumeهایی هم برای کانتینر es اضافه میشوند تا دادههایی که بارگذاری شدهاند پس از بازنشانیها نیز باقی بمانند. همچنین، پارامتر depends_on نیز تعیین میشود. depends_on برای داکر مشخص میکند که کانتینر es را قبل از کانتینر web آغاز کند. میتوان در مستندات Docker Compose اطلاعات بیشتری در این خصوص به دست آورد.
نکته: برای اجرای اکثر دستورات Compose باید به طور مستقیم در شاخهای قرار گرفت که فایل docker-compose.yml در آن موجود است.
اکنون فایل مربوطه آماده است. حال در ادامه به صورت عملی به آموزش فایل docker-compose پرداخته میشود. اما پیش از آن لازم است اطمینان حاصل شود که پورتها و نامهای مربوطه آزاد هستند. بنابراین در صورتی که کانتینرهای فلسک و ES در حال اجرا هستند، باید آنها را به صورت زیر خاموش کرد:
$ docker stop es foodtrucks-web
es
foodtrucks-web
$ docker rm es foodtrucks-web
es
foodtrucks-web
اکنون میتوان فایل docker-compose را اجرا کرد. برای انجام این کار باید به شاخه Food Trucks رفت و دستور «docker-compose up» را به صورت زیر اجرا کرد (خروجی دستور هم در ادامه آن آمده است):
$ docker-compose up
Creating network "foodtrucks_default" with the default driver
Creating foodtrucks_es_1
Creating foodtrucks_web_1
Attaching to foodtrucks_es_1, foodtrucks_web_1
es_1 | [2016-01-11 03:43:50,300][INFO ][node ] [Comet] version[2.1.1], pid[1], build[40e2c53/2015-12-15T13:05:55Z]
es_1 | [2016-01-11 03:43:50,307][INFO ][node ] [Comet] initializing ...
es_1 | [2016-01-11 03:43:50,366][INFO ][plugins ] [Comet] loaded [], sites []
es_1 | [2016-01-11 03:43:50,421][INFO ][env ] [Comet] using [1] data paths, mounts [[/usr/share/elasticsearch/data (/dev/sda1)]], net usable_space [16gb], net total_space [18.1gb], spins? [possibly], types [ext4]
es_1 | [2016-01-11 03:43:52,626][INFO ][node ] [Comet] initialized
es_1 | [2016-01-11 03:43:52,632][INFO ][node ] [Comet] starting ...
es_1 | [2016-01-11 03:43:52,703][WARN ][common.network ] [Comet] publish address: {0.0.0.0} is a wildcard address, falling back to first non-loopback: {172.17.0.2}
es_1 | [2016-01-11 03:43:52,704][INFO ][transport ] [Comet] publish_address {172.17.0.2:9300}, bound_addresses {[::]:9300}
es_1 | [2016-01-11 03:43:52,721][INFO ][discovery ] [Comet] elasticsearch/cEk4s7pdQ-evRc9MqS2wqw
es_1 | [2016-01-11 03:43:55,785][INFO ][cluster.service ] [Comet] new_master {Comet}{cEk4s7pdQ-evRc9MqS2wqw}{172.17.0.2}{172.17.0.2:9300}, reason: zen-disco-join(elected_as_master, [0] joins received)
es_1 | [2016-01-11 03:43:55,818][WARN ][common.network ] [Comet] publish address: {0.0.0.0} is a wildcard address, falling back to first non-loopback: {172.17.0.2}
es_1 | [2016-01-11 03:43:55,819][INFO ][http ] [Comet] publish_address {172.17.0.2:9200}, bound_addresses {[::]:9200}
es_1 | [2016-01-11 03:43:55,819][INFO ][node ] [Comet] started
es_1 | [2016-01-11 03:43:55,826][INFO ][gateway ] [Comet] recovered [0] indices into cluster_state
es_1 | [2016-01-11 03:44:01,825][INFO ][cluster.metadata ] [Comet] [sfdata] creating index, cause [auto(index api)], templates [], shards [5]/[1], mappings [truck]
es_1 | [2016-01-11 03:44:02,373][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:02,510][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:02,593][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:02,708][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
es_1 | [2016-01-11 03:44:03,047][INFO ][cluster.metadata ] [Comet] [sfdata] update_mapping [truck]
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
اجرای اپلیکیشن با دو کانتینر
اکنون باید به نشانی IP مربوطه مراجعه شود تا بتوان اپلیکیشن خود را به صورت زنده مشاهده کرد. بنابراین به راحتی و تنها با چند خط دستور و انجام تنظیمات اندک، دو کانتینر داکر با موفقیت به صورت هماهنگ اجرا شدهاند. اکنون در ادامه سرویس مربوطه را متوقف کرده و مجدداً در حالت منفصل (Detached) اجرا شده است:
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Killing foodtrucks_web_1 ... done
Killing foodtrucks_es_1 ... done
$ docker-compose up -d
Creating es ... done
Creating foodtrucks_web_1 ... done
$ docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------------------
es /usr/local/bin/docker-entr ... Up 0.0.0.0:9200->9200/tcp, 9300/tcp
foodtrucks_web_1 python3 app.py Up 0.0.0.0:5000->5000/tcp
جای تعجبی ندارد که میتوان هر دو کانتینر را ملاحظه کرد که با موفقیت اجرا شدهاند. ممکن است این سوال به وجود بیاید که نامهای دامنه از کجا آمدهاند؟ در پاسخ باید گفت که این نامها به صورت خودکار توسط Compose ایجاد شدهاند. اما آیا Compose شبکه را هم به طور خودکار ایجاد میکند؟ در ادامه این بخش از آموزش داکر به این سوال پاسخ داده شده است.
آیا Docker Compose شبکه را به صورت خودکار ایجاد میکند؟
اول از همه، باید سرویسها را از حالت اجرا خارج و آنها را متوقف کرد. همواره میتوان آنها را تنها با یک دستور مجدداً راهاندازی کرد. حجمهای داده همچنان باقی خواهند ماند، بنابراین امکان راهاندازی مجدد خوشه با همان دادهها به وسیله دستور docker-compose up وجود دارد. برای تخریب خوشه و حجمهای دادهها، تنها کافی است که از دستور «docker-compose down -v» استفاده شود که اجرا و خروجی آن در ادامه ملاحظه میشود:
$ docker-compose down -v
Stopping foodtrucks_web_1 ... done
Stopping es ... done
Removing foodtrucks_web_1 ... done
Removing es ... done
Removing network foodtrucks_default
Removing volume foodtrucks_esdata1
علاوه بر این، باید شبکه foodtrucks که پیشتر ایجاد شد را هم حذف کرد:
$ docker network rm foodtrucks-net
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
c2c695315b3a bridge bridge local
a875bec5d6fd host host local
ead0e804a67b none null local
اکنون که همه چیز پاکسازی شده است، باید سرویسهای خود را مجدداً اجرا و بررسی کرد که آیا Compose عملکرد مطلوب را به نمایش خواهد گذاشت؟
$ docker-compose up -d
Recreating foodtrucks_es_1
Recreating foodtrucks_web_1
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f50bb33a3242 prakhar1989/foodtrucks-web "python3 app.py" 14 seconds ago Up 13 seconds 0.0.0.0:5000->5000/tcp foodtrucks_web_1
e299ceeb4caa elasticsearch "/docker-entrypoint.s" 14 seconds ago Up 14 seconds 9200/tcp, 9300/tcp foodtrucks_es_1
تا اینجا همه چیز به خوبی پیش رفته است، حال زمان آن فرا رسیده تا بررسی شود که آیا شبکهای ایجاد شده است؟
$ docker network ls
NETWORK ID NAME DRIVER
c2c695315b3a bridge bridge local
f3b80f381ed3 foodtrucks_default bridge local
a875bec5d6fd host host local
ead0e804a67b none null local
میتوان ملاحظه کرد که Compose خودش یک شبکه جدید به نام «foodtrucks_default» ایجاد و هر دو سرویس جدید را در آن شبکه به گونهای ضمیمه کرده است که هر یک از آنها برای دیگری قابل شناسایی باشند. هر کانتینر برای یک سرویس به شبکه پیشفرض میپیوندد و هر دو به وسیله سایر کانتینرها در آن شبکه قابل دسترسی و توسط آنها با نام میزبانی مطابق نام کانتینر قابل شناسایی هستند.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8c6bb7e818ec docker.elastic.co/elasticsearch/elasticsearch:6.3.2 "/usr/local/bin/dock…" About a minute ago Up About a minute 0.0.0.0:9200->9200/tcp, 9300/tcp es
7640cec7feb7 prakhar1989/foodtrucks-web "python3 app.py" About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp foodtrucks_web_1
$ docker network inspect foodtrucks_default
[
{
"Name": "foodtrucks_default",
"Id": "f3b80f381ed3e03b3d5e605e42c4a576e32d38ba24399e963d7dad848b3b4fe7",
"Created": "2018-07-30T03:36:06.0384826Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.19.0.0/16",
"Gateway": "172.19.0.1"
}
]
},
"Internal": false,
"Attachable": true,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"7640cec7feb7f5615eaac376271a93fb8bab2ce54c7257256bf16716e05c65a5": {
"Name": "foodtrucks_web_1",
"EndpointID": "b1aa3e735402abafea3edfbba605eb4617f81d94f1b5f8fcc566a874660a0266",
"MacAddress": "02:42:ac:13:00:02",
"IPv4Address": "172.19.0.2/16",
"IPv6Address": ""
},
"8c6bb7e818ec1f88c37f375c18f00beb030b31f4b10aee5a0952aad753314b57": {
"Name": "es",
"EndpointID": "649b3567d38e5e6f03fa6c004a4302508c14a5f2ac086ee6dcf13ddef936de7b",
"MacAddress": "02:42:ac:13:00:03",
"IPv4Address": "172.19.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "default",
"com.docker.compose.project": "foodtrucks",
"com.docker.compose.version": "1.21.2"
}
}
]
جریان کاری توسعه در آموزش محیط های چند کانتینری
پیش از آنکه بخش بعدی آموزش داکر ارائه شود، لازم است یک مسئله دیگر نیز پیرامون فایل docker-compose بیان شود. همانطور که پیشتر بیان شد، docker-compose برای توسعه و تست بسیار مناسب است. بنابراین، باید بررسی شود که چگونه میتوان Compose را برای سادهتر کردن فرآیندها در طول توسعه نرم افزار پیکربندی کرد.
در طول آموزش داکر در این مقاله، بسیاری از کارها با ایمیجهای داکر از پیش آماده شده انجام شدند. اگرچه در طول این مقاله ایمیجهایی هم از صفر ساخته شدند، اما تا اینجا هنوز هیچ تغییری در کدهای اپلیکیشن داده نشده است و بیشتر پیرامون ویرایش Dockerfileها و پیکربندیهای YAML بحث شد. یک سوالی که ممکن است پیش بیاید این است که جریان کاری در طول فرآیند توسعه چگونه به نظر میرسد.
آیا باید برای هر تغییری به ایجاد ایمیج ادامه داد، سپس آن را منتشر و بعد اجرایش کرد تا بررسی شود که آیا مطابق انتظار کار میکند یا خیر؟ به طور قطع انجام چنین کاری بسیار کسل کننده و دشوار خواهد بود. بنابراین، در این بخش به چگونگی جریان کاری توسعه پرداخته شده است. حال باید بررسی شود که چگونه میتوان تغییری را در اپلیکیشن Food trucks که کمی پیشتر اجرا شد به وجود آورد.
ایجاد تغییراتی در کدهای اپلیکیشن
برای ایجاد تغییرات در کدها باید اطمینان حاصل شود که اپلیکیشن در حال اجرا باشد:
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5450ebedd03c prakhar1989/foodtrucks-web "python3 app.py" 9 seconds ago Up 6 seconds 0.0.0.0:5000->5000/tcp foodtrucks_web_1
05d408b25dfe docker.elastic.co/elasticsearch/elasticsearch:6.3.2 "/usr/local/bin/dock…" 10 hours ago Up 10 hours 0.0.0.0:9200->9200/tcp, 9300/tcp es
اکنون میتوان این اپلیکیشن را به گونهای تغییر داد که یک پیام «Hello world!» را وقتی نمایش دهد که درخواستی در مسیر «/hello» صادر شده باشد. در حال حاضر پاسخ اپلیکیشن به این درخواست یک خطای 404 است:
$ curl -I 0.0.0.0:5000/hello
HTTP/1.0 404 NOT FOUND
Content-Type: text/html
Content-Length: 233
Server: Werkzeug/0.11.2 Python/2.7.15rc1
Date: Mon, 30 Jul 2018 15:34:38 GMT
اما چرا چنین اتفاقی رخ میدهد؟ با توجه به اینکه این اپلیکیشن مبتنی بر فلسک است، میتوان فایل app.py را برای رسیدن به جواب این سوال بررسی کرد. در فلسک، مسیرها با سینتکس @app.routeتعریف شدهاند. در این فایل ملاحظه میشود که تنها سه مسیر شامل «/»، «/debug» و «/search» تعریف شدهاند. مسیر «/» اپلیکیشن اصلی را رندر میکند، مسیر debug برای بازگرداندن برخی از اطلاعات مربوط به خطایابی استفاده میشود و در نهایت، مسیر search به وسیله اپلیکیشن برای پرس و جوی elasticsearch استفاده میشود:
$ curl 0.0.0.0:5000/debug
{
"msg": "yellow open sfdata Ibkx7WYjSt-g8NZXOEtTMg 5 1 618 0 1.3mb 1.3mbn",
"status": "success"
}
با این حساب، چگونه میتوان یک مسیر جدید برای hello اضافه کرد؟ برای این کار ابتدا باید فایل flask-app/app.py را در ویرایشگر دلخواه خود باز و تغییر زیر را اِعمال کرد:
@app.route('/')
def index():
return render_template("index.html")
# add a new hello route
@app.route('/hello')
def hello():
return "hello world!"
اکنون میتوان دوباره یک درخواست صادر کرد:
$ curl -I 0.0.0.0:5000/hello
HTTP/1.0 404 NOT FOUND
Content-Type: text/html
Content-Length: 233
Server: Werkzeug/0.11.2 Python/2.7.15rc1
Date: Mon, 30 Jul 2018 15:34:38 GMT
همانطور که ملاحظه میشود، صدور درخواست با خطا مواجه شده است. چرا چنین خطایی به وجود میآید؟ با وجود اینکه تغییر لازم در فایل app.py انجام شد، فایل در ماشین میزبان قرار دارد. اما به دلیل اینکه داکر در حال اجرای کانتینرهای مربوطه بر اساس ایمیج prakhar1989/foodtrucks-web است، از تغییرات انجام شده اطلاع ندارد. برای معتبرسازی این تغییر باید به صورت زیر عمل کرد:
$ docker-compose run web bash
Starting es ... done
root@581e351c82b0:/opt/flask-app# ls
app.py package-lock.json requirements.txt templates
node_modules package.json static webpack.config.js
root@581e351c82b0:/opt/flask-app# grep hello app.py
root@581e351c82b0:/opt/flask-app# exit
کاری که سعی شده است در اینجا انجام شود این است که تایید شود تغییرات انجام شده در فایل «app.py» که در کانتینر اجرا میشوند وجود ندارند. این کار با اجرای دستور «docker-compose run» انجام میشود که عملکرد آن مشابه دستور «docker run» است، اما آرگومانهای بیشتری را برای این سرویس دریافت میکند (که در این مورد به خصوص web است). به محض اینکه دستور «bash» اجرا شود، شل در «/opt/flask-app» به همان شکلی باز خواهد شد که در Dockerfile مربوطه تعیین شده است.
حال باید بررسی شود که چگونه میتوان این مورد را اصلاح کرد. اول از همه باید برای Docker Compose تعیین شود که ایمیج مربوطه را به کار نگیرد و به جای آن به صورت محلی از فایلها استفاده کند. علاوه بر این، باید حالت عیبیابی یا همان «Debug Mode» را به «true» تغییر داد تا برای فلسک شخص شود که وقتی فایل «app.py» تغییر میکند، باید بارگذاری مجدد انجام شود. حال باید بخش «web» مربوط به «docker-compose.yml» را به صورت زیر تغییر داد:
version: "3"
services:
es:
image: docker.elastic.co/elasticsearch/elasticsearch:6.3.2
container_name: es
environment:
- discovery.type=single-node
ports:
- 9200:9200
volumes:
- esdata1:/usr/share/elasticsearch/data
web:
build: . # replaced image with build
command: python3 app.py
environment:
- DEBUG=True # set an env var for flask
depends_on:
- es
ports:
- "5000:5000"
volumes:
- ./flask-app:/opt/flask-app
volumes:
esdata1:
driver: local
با تغییرات انجام شده [+]، حال در ادامه باید کانتینرهای مربوطه را متوقف و دوباره راهاندازی (استارت) کرد:
$ docker-compose down -v
Stopping foodtrucks_web_1 ... done
Stopping es ... done
Removing foodtrucks_web_1 ... done
Removing es ... done
Removing network foodtrucks_default
Removing volume foodtrucks_esdata1
$ docker-compose up -d
Creating network "foodtrucks_default" with the default driver
Creating volume "foodtrucks_esdata1" with local driver
Creating es ... done
Creating foodtrucks_web_1 ... done
به عنوان یک گام نهایی باید با اضافه کردن یک مسیر جدید تغییری را در فایل «app.py» ایجاد کرد. حالا باید دستور curl اجرا شود. دستور curl یک ابزار خط فرمان است که برای انتقال دادهها به سرور یا دریافت آنها از سرور استفاده میشود.
$ curl 0.0.0.0:5000/hello
hello world
همانطور که ملاحظه میشود، این بار یک پاسخ معتبر دریافت شده است. برای تمرین بیشتر میتوان تغییرات دیگری را هم در اپلیکیشن خود ایجاد و نتیجه را بررسی کرد. به این ترتیب، آموزش Docker Compose در این بخش به پایان رسیده است. با Docker Compose همچنین میتوان سرویسهای خود را موقتاً متوقف، یک دستور یکباره را در کانتینر اجرا و حتی مقیاس تعداد کانتینرها را هم بر حسب نیاز تنظیم کرد. همچنین، پیشنهاد میشود که برخی از سایر موارد استفاده Docker Compose نیز بررسی شوند. امید است در این بخش از آموزش داکر به خوبی نشان داده شده باشد که چقدر مدیریت محیطهایی با چند کانتینر با Compose ساده است. در بخش پایانی آموزش داکر، استقرار اپلیکیشن مورد نظر در AWS انجام شده است.
سرویس کانتینر AWS Elastic
در بخش قبلی از فایل docker-compose برای اجرای محلی اپلیکیشن تنها از یک دستور یعنی «docker-compose up» استفاده شد. حالا که این اپلیکیشن به درستی کار میکند، زمان آن فرا رسیده است تا با جهانیان به اشتراک گذاشته شود و تعدادی کاربر جذب شوند. به این ترتیب در این بخش از آموزش داکر به نحوه استقرار اپلیکیشنهایی با چند کانتینر روی سرویس ابری AWS پرداخته شده است. در صورتی که آموزش داکر تا اینجا به دقت مطالعه و دنبال شده باشد، کارایی و جذابیت فناوری داکر واضح به نظر میرسد.
با رشد و گسترش برقآسای داکر، تقریباً تمامی ارائه دهندگان خدمات ابری افزودن پشتیبانی برای استقرار اپلیکیشنهای مبتنی بر داکر را در پلتفرم خود آغاز کردهاند. در حال حاضر میتوان کانتینرها را در پلتفرم ابری گوگل، AWS آمازون، Azure مایکروسافت و بسیاری از دیگر خدماتدهندگان ابری مستقر کرد. تا اینجا و پیش از این برای آموزش داکر در این مقاله به نحوه استقرار اپلیکیشنهایی با یک کانتینر با استفاده از Elastic Beanstalk پرداخته شد و حالا در این بخش به صورت مقدماتی به نحوه کار با سرویس کانتینر الستیک (Elastic Container Service) در AWS یا همان AWS ECS پرداخته شده است.
AWS ECS یک سرویس مقیاسپذیر و بسیار قابل انعطاف برای مدیریت کانتینر به حساب میآید که از کانتینرهای داکر پشتیبانی میکند. AWS ECS به کاربر اجازه میدهد تا یک خوشه داکر را بر پایه نمونههای EC2 از طریق یک API با کاربری آسان راهبری کند. با وجود اینکه Beanstalk به همراه موارد پیشفرض قابل قبولی ارائه شده است، ECS این امکان را به وجود میآورد که بتوان محیط خود را به طور کامل بر اساس نیاز تنظیم کرد. میتوان اینطور گفت که چنین قابلیتهایی ECS را برای شروع کار پیچیدهتر کرده است.
خوشبختانه ECS یک ابزار CLI (رابط خط فرمان) برای کاربران دارد که فایلهای Docker Compose را درک میکند و به طور خودکار تمهیدات خوشهها را در ECS انجام میدهد. با توجه به اینکه از قبل یک فایل «docker-compose.yml» وجود دارد، راهاندازی و اجرای آن در AWS نباید چندان دشوار باشد. بنابراین در ادامه، موارد لازم انجام شدهاند.
اولین گام نصب CLI است. دستورالعملهای لازم برای نصب CLI هم در سیستم عامل مک و هم لینوکس در مستندات رسمی به وضوح شرح داده شدهاند. پس از نصب CLI، تایید نصب صحیح با اجرای دستور زیر انجام میشود:
$ ecs-cli --version
ecs-cli version 1.18.1 (7e9df84)
سپس، پیکربندی CLI به گونهای انجام میشود که بتوان با ECS ارتباط برقرار کرد. گامهای مربوطه مطابق آنچه انجام میشود که در راهنمای رسمی مربوط به مستندات AWS ECS ارائه شده است. در صورت بروز هر گونه سردرگمی، بهتر است به این راهنما مراجعه شود.
اولین گام شامل ایجاد یک پروفایل میشود که در طول ادامه آموزش داکر در این مقاله از آن استفاده خواهد شد. برای ادامه کار نیاز به «AWS_ACCESS_KEY_ID» و «AWS_ACCESS_KEY_ID» وجود دارد. برای دریافت این کلیدهای شناسایی باید گامهایی را دنبال کرد که در بخشی با عنوان کلید دسترسی (Access Key) و دسترسی سری (Secret Access) در این صفحه [+] شرح داده شدهاند.
$ ecs-cli configure profile --profile-name ecs-foodtrucks --access-key $AWS_ACCESS_KEY_ID --secret-key $AWS_SECRET_ACCESS_KEY
سپس، نیاز به دریافت یک جفتکلید (keypair) وجود دارد که از آنها برای ورود به نمونهها استفاده خواهد شد. حال باید به کنسول EC2 مراجعه و یک keypair جدید ایجاد شود. باید keypair مربوطه را دانلود و آن را در یک محل امن ذخیره کرد. یک مورد دیگری که پیش از خروج از این صفحه باید در نظر گرفته شود، نام منطقه مکانی (Reigion Name) است. مثلاً در اینجا نام کلید مربوطه، «ecs» و موقعیت مکانی هم «us-east-1» انتخاب شده است. بنابراین در ادامه این بخش از آموزش داکر از این نامها استفاده میشود.
گام بعدی، پیکربندی و انجام تنظیمات CLI است:
$ ecs-cli configure --region us-east-1 --cluster foodtrucks
INFO[0000] Saved ECS CLI configuration for cluster (foodtrucks)
دستور «configure» با نام منطقه مکانی مورد نیازی استفاده شده است که قصد قرار گرفتن خوشه مربوطه در آن وجود دارد و یک نام خوشه نیز مورد نیاز است. باید اطمینان حاصل شود که از همان نام منطقه مکانی استفاده شود که در زمان ایجاد keypair تعیین شده است. در صورتی که AWS CLI مربوطه پیش از این روی کامپیوتر کاربر تنظیم نشده باشد، میتوان از راهنمای رسمی استفاده کرد که همه چیز به طور کامل در آن شرح داده شده است. گام بعدی امکان ایجاد یک قالب CloudFormation را برای CLI به وجود میآورد:
$ ecs-cli up --keypair ecs --capability-iam --size 1 --instance-type t2.medium
INFO[0000] Using recommended Amazon Linux 2 AMI with ECS Agent 1.39.0 and Docker version 18.09.9-ce
INFO[0000] Created cluster cluster=foodtrucks
INFO[0001] Waiting for your cluster resources to be created
INFO[0001] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0062] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0122] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0182] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0242] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
VPC created: vpc-0bbed8536930053a6
Security Group created: sg-0cf767fb4d01a3f99
Subnet created: subnet-05de1db2cb1a50ab8
Subnet created: subnet-01e1e8bc95d49d0fd
Cluster creation succeeded.
در اینجا موارد زیر لحاظ شدهاند:
- نام keypair مربوطه که در ابتدا دانلود شده است (با نام ecs در این آموزش).
- تعداد نمونههایی که باید استفاده شوند (–size).
- نوع نمونههایی که قصد اجرای کانتینرها روی آن وجود دارد.
پرچم «–capability-iam» برای CLI مشخص میکند که اذعان میشود این دستور ممکن است منابع IAM به وجود بیاورد. آخرین گام مربوط به زمانی میشود که فایل «docker-compose.yml» مورد استفاده قرار میگیرد. باید تعدادی تغییر اندک لحاظ شوند، بنابراین به جای ویرایش فایل اصلی، بهتر است یک نمونه همسان (کپی) از آن ایجاد شود. محتویات این فایل (پس از انجام تغییرات) به صورت زیر خواهد بود:
version: '2'
services:
es:
image: docker.elastic.co/elasticsearch/elasticsearch:7.6.2
cpu_shares: 100
mem_limit: 3621440000
environment:
- discovery.type=single-node
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
logging:
driver: awslogs
options:
awslogs-group: foodtrucks
awslogs-region: us-east-1
awslogs-stream-prefix: es
web:
image: prakhar1989/foodtrucks-web
cpu_shares: 100
mem_limit: 262144000
ports:
- "80:5000"
links:
- es
logging:
driver: awslogs
options:
awslogs-group: foodtrucks
awslogs-region: us-east-1
awslogs-stream-prefix: web
تنها تغییراتی که نسبت به فایل اصلی «docker-compose.yml» انجام شده است، مربوط به استفاده از مقادیر «mem_limit» (به صورت بایت) و «cpu_shares» برای هر کانتینر و اضافه کردن برخی از پیکربندهای مربوط به رویدادنگاری (Logging) میشود. بدین وسیله، این امکان به وجود میآید تا بتوان لاگهای ایجاد شده در کانتینرهای خود را در AWS CloudWatch مشاهده کرد.
باید برای ایجاد یک log group به نام «foodtrucks» به CloudWatch رفت. باید توجه کرد که چون بلاخره ElasticSearch معمولاً حافظه بیشتری میبرد، تقریباً محدودیت حافظهای در حدود ۳.۴ گیگابایت اختصاص داده شده است. کار دیگری که پیش از رفتن به مرحله بعدی باید انجام داد، این است که ایمیج مربوطه باید در داکر هاب منتشر شود:
$ docker push prakhar1989/foodtrucks-web
اکنون باید دستور پایانی را اجرا کرد که منجر به استقرار اپلیکیشن ما در ECS میشود:
$ cd aws-ecs
$ ecs-cli compose up
INFO[0000] Using ECS task definition TaskDefinition=ecscompose-foodtrucks:2
INFO[0000] Starting container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es
INFO[0000] Starting container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web
INFO[0000] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0000] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0036] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0048] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0048] Describe ECS container status container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-foodtrucks:2
INFO[0060] Started container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/web desiredStatus=RUNNING lastStatus=RUNNING taskDefinition=ecscompose-foodtrucks:2
INFO[0060] Started container... container=845e2368-170d-44a7-bf9f-84c7fcd9ae29/es desiredStatus=RUNNING lastStatus=RUNNING taskDefinition=ecscompose-foodtrucks:2
جای تعجبی ندارد که فراخوانی انجام شده در بالا مشابه آنچه باشد که در Docker Compose انجام شد. اگر همه چیز به خوبی پیش رفته باشد، باید پیامی به صورت «desiredStatus=RUNNING lastStatus=RUNNING» در خط پایانی مشاهده شود. به این ترتیب اکنون اپلیکیشن مربوطه آماده استفاده (Live) است. اما چطور میتوان به آن دسترسی پیدا کرد؟
ecs-cli ps
Name State Ports TaskDefinition
845e2368-170d-44a7-bf9f-84c7fcd9ae29/web RUNNING 54.86.14.14:80->5000/tcp ecscompose-foodtrucks:2
845e2368-170d-44a7-bf9f-84c7fcd9ae29/es RUNNING ecscompose-foodtrucks:2
برای دسترسی به اپلیکیشن خود باید نشانی «http://54.86.14.14» را در مرورگر باز و وب اپلیکیشن Food Trucks را مشاهده کرد. حال در ادامه تصاویری از رابط کاربری AWS ECS مشاهده میشوند:
میتوان در تصویر فوق ملاحظه کرد که خوشه ECS به نام «foodtrucks» ایجاد شده و اکنون در حال اجرای یک وظیفه (Task) با دو نمونه کانتینر است. بهتر است کمی زمان صرف شود و با کنسول ECS بیشتر کار کرد تا آشنایی لازم با آن به دست آید.
پاکسازی
پس از امتحان کردن و اتمام کار با اپلیکیشن مستقر شده نباید غیرفعال یا به اصطلاح Down کردن خوشه مربوطه را فراموش کرد. این کار به صورت زیر انجام میشود:
$ ecs-cli down --force
INFO[0001] Waiting for your cluster resources to be deleted...
INFO[0001] Cloudformation stack status stackStatus=DELETE_IN_PROGRESS
INFO[0062] Cloudformation stack status stackStatus=DELETE_IN_PROGRESS
INFO[0124] Cloudformation stack status stackStatus=DELETE_IN_PROGRESS
INFO[0155] Deleted cluster cluster=foodtrucks
بنابراین ملاحظه شد که تنها با چند دستور اندک امکان استقرار اپلیکیشن مورد نظر روی محیط ابری AWS فراهم میشود. به این ترتیب آموزش داکر در اینجا به پایان میرسد. حال در ادامه به گام بعدی در آموزش داکر پرداخته شده است.
معرفی فیلم های آموزش داکر برای گام بعدی آموزش Docker
با مطالعه این مقاله باید گفت که سفر در دنیای کانتینرها تازه شروع شده است. هدف از ارائه آموزش داکر در این مقاله، ایجاد علاقه و نمایش قابلیتها و قدرت داکر بود. پیش رفتن در دنیای فناوری به تنهایی میتواند دشوار باشد و مقالات و دورههای آموزشی میتوانند در این خصوص به افراد کمک کنند. در این بخش به معرفی برخی از منابع و دورههای مفید برای ادامه آموزش داکر پرداخته شده است. به توسعه دهندگان توصیه میشود تا برای پروژه بعدی خود حتماً از داکر استفاده کنند.
فیلم آموزش مقدماتی کوبرنتیز Kubernetes برای مدیریت کانتینرها
در طول آموزش داکر به ابزار Kubernetes اشاره شد. Kubernetes یک پلتفرم متنباز لینوکسی به حساب میآید که عملیات کانتینربندی به وسیله آن قابل خودکارسازی است. در صورتی که افراد با کانتینرهای بسیاری مواجه باشند و نیاز به خودکارسازی برخی از مراحل در زمان راهاندازی آنها وجود داشته باشد، Kubernetes بسیار مفید واقع خواهد شد. برای یادگیری کوبرنتیز میتوان از دوره آموزشی مقدماتی آن در سایت تم آف استفاده کرد. طول مدت این دوره نزدیک به ۳ ساعت و مدرس آن مهندس آرش فروغی است.
- برای مشاهده فیلم آموزش مقدماتی کوبرنتیز Kubernetes برای مدیریت کانتینرها + اینجا کلیک کنید.
فیلم آموزش سیستم عامل لینوکس (Linux) – مقدماتی
آشنایی با لینوکس یکی از پیش نیازهای مهم برای آموزش داکر به حساب میآید. پیش از گذراندن دوره آموزش Kubernetes نیز یادگیری لینوکس ضروری به نظر میرسد. برای شروع آموزش لینوکس میتوان از دوره آموزش لینوکس مقدماتی تم آف استفاده کرد. طول مدت این دوره آموزشی ۱۵ ساعت و مدرس آن دکتر محمدرضا رازیان است. دوره آموزش مقدماتی لینوکس تم آف شامل هفت درس میشود که از جمله سرفصلهای آن میتوان به آشنایی با لینوکس (Linux)، به کارگیری لینوکس، خط فرمان لینوکس، مجوزها، دستورات پرکاربرد و سایر موارد اشاره کرد.
- برای دیدن فیلم آموزش سیستم عامل لینوکس (Linux) – مقدماتی + اینجا کلیک کنید.
فیلم آموزش سیستم عامل لینوکس (Linux) – تکمیلی
یکی دیگر از پیش نیازهای دوره آموزش Kubernetes، دوره لینوکس تکمیلی تم آف به حساب میآيد. طول مدت این دوره ۴ ساعت و مدرس آن مهندس محمدرضا آقازاده است. در این تم آف، مباحث تکمیلی آموزش لینوکس پس از دوره مقدماتی ارائه شده و استفاده از آن برای افرادی که آشنایی مقدماتی با سیستم عامل لینوکس را دارند مناسب است. این دوره شامل ۸ درس میشود که از جمله سرفصلهای مهم آموزش داده شده در این بخشها میتوان به معماری سیستم عاملهای مبتنی بر لینوکس (Linux)، فایل سیستم، سرویسهای لینوکسی، مدیریت پردازهها، سیستم ثبت گزارش، کامپایل کرنل جدید و سایر موارد اشاره کرد.
- برای دیدن فیلم آموزش سیستم عامل لینوکس (Linux) – تکمیلی + اینجا کلیک کنید.
فیلم آموزش گیت (Git) – تکمیلی
همانطور که در بخش پیش نیازهای آموزش داکر در این مقاله اشاره شد، آشنایی با گیت نیز برای استفاده از این آموزش میتواند مفید واقع شود. برای یادگیری سیستم کنترل نسخه Git میتوان از دوره آموزش گیت تم آف استفاده کرد. یک دوره مقدماتی رایگان گیت با تدریس جادی هم در سایت تم آف ارائه شده است که گذراندن آن پیش از شروع دوره تکمیلی پیشنهاد میشود. در این دوره آموزشی، مباحث تکمیلی پوشش داده شدهاند و نسبت به دوره مقدماتی قدری کاملتر است. طول مدت این دوره کمی بیش از ۴ ساعت و مدرس آن مهندس علی قاسمی هستند. این دوره از پنج بخش تشکیل شده که برخی از سرفصلهای آنها شامل آشنایی با گیت، کار با برنچ ها (Branch)، لاگ ها (Log) و مرج کردن (Merge)، کار با Stash, Cherry و ابزارهای دیباگینگ (Debugging) و سایر موارد است.
- برای مشاهده فیلم آموزش گیت (Git) – تکمیلی + اینجا کلیک کنید.
معرفی فیلم های آموزش پایتون تم آف
یکی دیگر از مجموعههای آموزشی کاربردی و جامع در وب سایت تم آف ، مجموعه دورههای آموزش پایتون است. برای آموزش داکر در این مقاله به نحوه داکریزه کردن و استقرار وب اپلیکیشنهایی پرداخته شد که با زبان برنامه نویسی پایتون توسعه داده شدهاند. پایتون یکی از محبوبترین و پرکاربردترین زبانهای برنامه نویسی دنیا به حساب میآید و یادگیری آن برای شروع فعالیت در زمینه برنامه نویسی به کلیه علاقهمندان توصیه میشود.
برای یادگیری پایتون میتوان از دورههای آموزشی مختلفی استفاده کرد که در مجموعه آموزش پایتون تم آف ارائه شدهاند. آموزش پایتون در این مجموعه به صورت دورههایی با سطوح مختلف از مقدماتی تا پیشرفته و همچنین دورههای آموزشی پروژه محور به همراه آموزش بسیاری از چارچوبها و فناوریهای توسعه مبتنی بر پایتون در اختیار کاربران قرار دارد. برای مثال، جنگو یکی از چارچوبهای محبوب توسعه وب به حساب میآید که دوره آموزشی آن در مجموعه آموزش پایتون قابل دسترسی است.
- برای مشاهده فیلم های آموزش پایتون فراردس + اینجا کلیک کنید.
جمعبندی
در این مقاله پس از یک فرآیند آموزشی طولانی و جامع اما ساده و روان، اکنون آمادگی لازم برای ورود به دنیای کانتینرها به دست آمده است. در صورت دنبال کردن آموزش داکر در این مقاله تا پایان، آشنایی کافی با این فناوری حاصل میشود. آموزش داکر در این مقاله شامل نحوه راهاندازی داکر، اجرای کانتینرهای سفارشی، کار با وب سایتهای ایستا و پویای داکریزه شده و مهمتر از همه، تجربه عملی پیرامون استقرار اپلیکیشنهای کانتینربندی شده در محیط ابری میشود. امید است که با اتمام آموزش داکر در این نوشتار، اعتماد به نفس بیشتری در خصوص کار با سرورها به دست آمده باشد. با یادگیری داکر، وقتی ایدهای برای ساخت اپلیکیشن در ذهن شکل میگیرد، این اطمینان وجود خواهد داشت که میتوان آن را با کمترین دردسر و زحمت ممکن در اختیار کاربران نهایی قرار داد.