<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های Ali Akbar Hemmati</title>
        <link>https://virgool.io/feed/@hemmati.ali.a</link>
        <description>سیس ادمین ساده‌ی ساده</description>
        <language>fa</language>
        <pubDate>2026-07-14 13:09:32</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/148063/avatar/yatrDq.jpeg?height=120&amp;width=120</url>
            <title>Ali Akbar Hemmati</title>
            <link>https://virgool.io/@hemmati.ali.a</link>
        </image>

                    <item>
                <title>ساخت اپ‌های مختلف روی کوبرنتیز با یک هلم چارت</title>
                <link>https://virgool.io/@hemmati.ali.a/one-helm-chart-to-deploy-them-all-ei8zfabel4qw</link>
                <description>به نام خدا مقدمهیکی از دغدغه‌هایی که معمولا برای دیپلوی سرویس‌ها روی کوبرنتیز هست نوشتن فایل‌های مختلف آبجکت‌های کوبرنتیزیه. هلم این کار رو با استفاده از template برامون راحت‌تر می‌کنه. اما خود نوشتن هلم چارت می‌تونه سخت بشه چون باید با دقت values و template طراحی بشه. می‌خوام شما رو در این مقاله با یه هلم چارت کلی آشنا کنم که بشه خیلی از سرویس‌ها رو باهاش دیپلوی کرد. معرفی هلم چارتبا توجه به مسئله‌ای که گفتم، من به این فکر افتادم که یک هلم چارت کلی داشته باشم که بتونم انواع سرویس‌ها رو باهاش دیپلوی کنم. توی اینترنت گشتم و یه ریپوی گیتهاب خوب پیدا کردم. البته مدتی بود که دیگه توسعه داده نمی‌شد. به خاطر این فورکش کردم و تقریبا یه سالی هست که دارم توسعه‌اش میدم و تا الان چندین ورژن جدید هم دادم. برای هر کدوم changelog هم نوشتم که می‌تونید بخونیدش. آدرسش اینه: https://github.com/aahemm/helm-microserviceمدتیه که دارم ازش برای دیپلوی سرویس بکند، فرانت و انواع دیتابیس استفاده می‌کنم و خوب بوده. به کمک این چارت دیگه لازم نیست خودتون یه چارت رو از اول بنویسید و فقط کافیه یک فایل values.yaml بنویسید و با دستور helm install دیپلویش کنید. توی فرایند GitOps هم میشه ازش استفاده کرد. علاوه بر این سعی شده فایل values ساده باشه که دولوپرها هم بدون دانش کوبرنتیز بتونن ازش استفاده کنن و مقادیر لازم رو اضافه کنن. به این ریپو چند تا مثال هم اضافه کردم که راحت‌تر بتونید سرویس‌هایی که می‌خواید رو باهاش دیپلوی کنید و ایده بگیرید که چه ویژگی‌هایی داره. توی پوشه‌ی docs می‌تونید ببینیدشون. در ادامه می‌خوام نحوه‌ی دیپلوی nginx رو با این هلم چارت توضیح بدم.دیپلوی nginx با هلم چارتفایل values که برای nginx استفاده می‌کنیم رو می‌تونید در این لینک ببینید. توی ویرگول متاسفانه سخته قرار دادن این جور فایل‌ها. تو این فایل اول کار تعداد رپلیکاها مشخص شده. دقت کنید که به طور پیشفرض Deployment استفاده میشه و اینجا تعداد رپلیکاهای اون میاد. بعدش اطلاعات ایمیج از جمله تگ و آدرسش داده شده. در قسمت بعد یک Service کوبرنتیز تعریف شده که بقیه‌ی پادهای کلاستر به راحتی بتونن به پورت 80 این پاد برسن و هم چنین بشه با نودپورت 30080 بهش رسید. بخش بعدی در مورد کانفیگ nginx هست. اول volumes رو enabled کردیم. چون PVC نمی‌خوایم اون رو enabled نکردیم. با configMaps کانفیگ‌های لازم رو بهش می‌دیم. اول اسم و محل قرار گرفتن رو می‌ذاریم. بعد هم دیتایی که باید توش باشه رو می‌نویسیم. دقت کنید که داخل data کلمه‌ای که گذاشته میشه اسم فایل در پاد میشه. دیتای فایل هم که یک بلاک ساده در nginx هست. بعد از کانفیگ در resources تعیین می‌کنیم که چقدر cpu و memory به پاد تعلق بگیره. می‌تونید این رو حذف کنید اگه نیاز ندارید ولی توصیه میشه همیشه بذاریدش. با نوشتن این چند خط داخل یه فایل به اسم values.yaml آماده‌ایم که دیپلویش کنیم: helm repo add app https://aahemm.github.io/helm-microservice
helm repo update
helm install my-release app/app --values ./values.yamlمشارکت در پروژهاگر دوست داشتید حتما تو این پروژه مشارکت کنید. حتی کوچک‌ترین مشارکت هم به بهتر شدنش کمک می‌کنه. مثلا اگه سرویس خاصی خواستید دیپلوی کنید و در موردش سوال داشتید زیر همین پست بگید یا ایشوی جدید باز کنید. اگر ایرادی دیدید یا ویژگی جدیدی لازم داشتید هم در قالب ایشوی گیتهاب بگید. یه راه مهم دیگه اینه که خودتون تغییراتی بدید و در گیتهاب pull request بزنید. مخصوصا مثال‌های جدید و مستندات. در نهایت اگر از این ریپو خوشتون اومد توی گیتهاب بهش ستاره بدید و به بقیه معرفی کنید.</description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Fri, 10 Nov 2023 19:53:38 +0330</pubDate>
            </item>
                    <item>
                <title>شبکه در کانتینرها و کوبرنتیز - قسمت ۲</title>
                <link>https://virgool.io/@hemmati.ali.a/container-networking-2-fw1zeghsgnsr</link>
                <description>به نام خدادر قسمت قبل این مجموعه مقالات و هدفشون رو معرفی کردم و در مورد یه سری ابزار شبکه‌ای در لینوکس صحبت کردم. در این قسمت می‌خوام در مورد ساختار شبکه در لینوکس به شکل کلی صحبت کنم. این که وقتی یک پکت وارد کرنل میشه چه اتفاقاتی براش می‌افته. چجوری یه به دست پردازه‌ای که ازش استفاده می‌کنیم می‌رسه و از پردازه به یه مقصدی فرستاده میشه. این توضیحات به این دلیل لازمه که وقتی وارد کانتینرها شدیم بتونیم دید بهتری از اتفاقاتی که داره میفته پیدا کنیم. البته همه‌ی اتفاقات رو نمیشه تو یه مقاله گفت و من هم به همه‌اش مسلط نیستم. چیزهایی که در ادامه به دردمون خواهد خورد رو قراره بگم.مفهوم user space و kernel spaceقبل از این که شروع کنیم در مورد ساختار شبکه صحبت کنیم بهتره این دو مفهوم رو یه بار مرور کنیم. همونطور که می‌دونید کرنل وظیفه‌ی مدیریت سخت‌افزار و اجرای برنامه‌های کاربران روی اون رو بر عهده داره. خود کرنل هم یک برنامه است که باید در CPU اجرا بشه و نیاز به مموری داره. کارهایی که در کرنل انجام میشن رو می‌گیم در kernel space هستن. مثلا وقتی یه پکتی وارد سیستم میشه و قراره پردازش بشه قسمتی از این پردازش رو کرنل انجام میده و ما می‌گیم این بخش در kernel space هست. علاوه بر این قسمتی از پردازش هم توسط برنامه‌هایی که کاربران سیستم عامل نوشتن انجام میشه. کارهایی که توسط این برنامه‌ها انجام میشه رو می‌گیم در user space هستن.لایه‌های شبکهدر بخش قبل در مورد user space و kernel space گفتم. حالا اینجا می‌خوام بگم که در مورد شبکه کدوم بخش از پردازش در کرنل و کدوم بخش در user space انجام میشه. در مدل OSI برای شبکه ما هفت لایه داریم. از لایه‌ی فیزیکی شروع میشه. بعد می‌رسه به لایه‌ی دیتا لینک، شبکه و انتقال. سه لایه‌ی آخر به ترتیب نشست یا session، نمایش و اپلیکیشن هستن.لایه‌ی فیزیکی توسط کارت‌های شبکه انجام میشه. اونا هستن که با توجه به جنس محیط انتقال و شرایط ارسال به شکل مناسبی بسته‌ها رو می‌فرستن به دستگاه‌های بعدی. بعد از اون لایه‌ی ۲ میاد که دیتا لینک هست. این لایه توسط کرنل و کارت شبکه انجام میشه. قسمتی در کرنل هست به اسم network device driver که با کارت‌های شبکه صحبت می‌کنه و پکت‌ها رو به لایه‌ی بعدی می‌فرسته. ما این کارت‌های شبکه رو به شکل اینترفیس (interface) می‌بینیم و باهاشون تعامل می‌کنیم. این همون چیزیه که وقتی دستور ip addr می‌زنیم می‌بینیم. البته تمام اینترفیس‌هایی که نشون میده متصل به کارت شبکه نیستن و ممکنه اینترفیس مجازی هم نشون بده بهمون. ولی میشه اینترفیس‌های فیزیکی رو هم باهاش دید. لایه‌ی ۳ و ۴ هم توسط کرنل هندل میشه و از اون به بعد در اختیار پردازه‌های کاربران قرار می‌گیره. پردازه‌ها هم با استفاده از سوکت محتویات بسته رو می‌گیرن. سوکت در اصل یه رابط برای برنامه‌نویس‌هاست که کرنل در اختیار قرار میده که بتونن راحت و بدون توجه به لایه‌های پایین‌تر شبکه کارشون رو بکنن. مثلا دیگه لازم نیست برنامه‌نویس توجه کنه که کانکشن TCP درست برقرار شده یا نه. فقط محتوا رو از طریق سوکت میده به کرنل و بقیه‌اش رو کرنل انجام میده.البته گاهی اوقات خود پردازه‌ در user space به کرنل درخواست میده که زودتر پکت رو بهش بده. یعنی میگه لایه‌های پایین‌تر رو هم خودم مدیریت می‌کنم. این ویژگی در لینوکس وجود داره و میشه برای موارد خاص و پیشرفته این کار رو هم کرد. راه‌های دور زدن کرنل در شبکه زیاده و هر کدوم می‌تونه به دلیلی استفاده بشه. ما راجع به اون موارد اینجا صحبت نمی‌کنیم و به همون حالت رایج می‌پردازیم.خیلی از اوقات هم پیش میاد که ما مستقیم سوکت باز نمی‌کنیم. به جاش از یه فریم‌ورک یا کتابخونه استفاده می‌کنیم که کارها رو راحت می‌کنه. مثلا در پایتون ما ماژول requests رو داریم که باهاش درخواست http میشه داد. این ماژول نه تنها سوکت و ارتباط با کرنل رو برای ما انجام میده بلکه خیلی از کارهای لازم برای ارتباط http رو هم داخلش داره. نکته‌ای که باید بهش توجه کنیم اینه که در این حالات هم باز کرنل داره با استفاده از سوکت با user space حرف می‌زنه فقط اون قسمتش از ما پنهان شده.بررسی جزئی‌تر روتینگ و netfilter در کرنلامیدوارم در بخش قبل یک دید کلی از شبکه در کرنل پیدا کرده باشید. در این بخش می‌خوام جزئیات بیشتری از لایه‌ی ۳ در کرنل رو بگم که در ادامه برامون مهم خواهد بود. هدف اینه که بدونیم ابزارهایی که استفاده می‌کنیم در کدوم قسمت کار می‌کنن و ترتیبشون چیه.در مسیر ورود پکت، بعد از این که کارهای لایه ۲ انجام میشه و می‌خواد پردازش لایه‌ی ۳ شروع بشه ابزارهایی مثل tcpdump میان و یه کپی از پکت رو می‌گیرن تا خودشون در user space تحلیلش کنن. یعنی خیلی خیلی زود پکت رو می‌گیرن. قبل از این که routing یا netfilter انجام بشه. در شکل زیر می‌بینید بعد از درایور این رو نشون دادم.بعدش پکت وارد جاهایی میشه که ما بیشترین کار رو باهاش داریم. اول میاد داخل netfilter. ما در کرنل ۵ تا جا داریم که به اون‌ها netfilter hook میگن و میشه با نوشتن کرنل ماژول تغییراتی در پکت‌ها اعمال کرد. اون‌هایی که در شکل بالا بیضی هستن هوک‌ها رو نشون میدن. iptables هم بر همین اساس کار می‌کنه و اون دستوراتی که ما می‌زنیم تو این قسمت‌ها اعمال میشن. در شکل بالا مسیر خروج پکت هم کشیده شده که هوک OUTPUT رو در این مسیر می‌بینید. در بخش‌هایی از این مسیر هم تصمیمات روتینگ گرفته میشه. مشخصه که در مسیر ورود بعد از PREROUTING روت انجام میشه. چون ممکنه ما در اونجا پکتی رو NAT کنیم و دوباره نیاز داشته باشه مسیرش مشخص شه. ممکنه یه پکت وارد سیستم بشه و اصلا به user space نرسه و از همون روتینگ اول به  FORWARD بره و خارج شه. در مسیر خروج هم بعد از OUTPUT روتینگ انجام میشه. مسیر خروج مسیریه که یه پکت از user space شروع می‌کنه و وارد کرنل میشه. ممکنه تو این مسیر از سیستم خارج نشه پکت و به یک پردازه‌ی دیگه در سیستم برسه. دونستن ترتیب اینا خیلی مهمه و در دیباگ کردن یا ساختن ابزارها کمکمون خواهد کرد. یه نکته‌ رو هم توجه کنید دوباره. در مسیر خروج tcpdump یا وایرشارک بعد از همه‌ی این‌ها و موقع ورود پکت به درایور قرار می‌گیره. در مسیر ورود هم قبل از همه‌ی این‌ها و بعد از خروج از درایور قرار می‌گیره. این رو ایشالا در کارهای عملی آینده خواهیم دید.به جای جمع‌بندیدر قسمت بعد برای این که با این مفاهیم و ابزارهای قسمت قبل بیشتر آشنا بشیم قراره یک روتر در لینوکس بسازیم. یعنی سیستم لینوکسی رو تبدیل به روتر کنین. شما هم به عنوان تمرین سعی کنید با جستجو یک روتر لینوکسی بسازید که دو تا شبکه رو به هم وصل کنه. در قسمت بعد منم هم‌چین چیزی رو خواهم ساخت.امیدوارم براتون مفید بوده باشه. اگه سوال یا نکته‌ای بود این پایین بنویسید.</description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Fri, 15 Sep 2023 19:37:00 +0330</pubDate>
            </item>
                    <item>
                <title>شبکه در کانتینرها و کوبرنتیز - قسمت ۱</title>
                <link>https://virgool.io/@hemmati.ali.a/container-networking-1-qnsitgrnb15n</link>
                <description>مقدمهیکی از مباحث مهم در دنیای زیرساخت شبکه است. وقتی شبکه رو در دنیای کانتینرها و کوبرنتیز استفاده می‌کنیم پیچیدگی‌های زیادی به وجود میاد. چون تعداد زیاد کانتینر روی یک سرور ساخته میشن که هر کدوم شبکه‌ی خودشون رو دارن. وقتی قرار باشه بین تعداد زیادی سرور این کانتینرها پخش بشن کار سخت‌تر هم میشه. توی یکی دو سال اخیر با توجه به کاری که انجام می‌دادم خیلی درگیر شدم با این مباحث. البته چیزهای زیادی هست که باید هنوز یاد بگیرم ولی گفتم طی یک سری مقاله این مباحث رو توضیح بدم تا هم برای خودم یادآوری بشه و هم امیدوارم برای بقیه مفید باشه. تو این دوره از شبکه‌ی لینوکس شروع می‌کنیم و کم کم به سمت کانتینرها و بعد کوبرنتیز می‌ریم. تمرکزمون روی کانتینرهای لینوکسی خواهد بود و سمت سیستم‌عامل‌های دیگه نخواهیم رفت. به عنوان پیش‌نیاز فرض بر این هست که مفاهیم شبکه و TCP/IP رو بلدید.تو این قسمت قراره چند تا ابزار مهمی که در لینوکس باهاشون کار خواهیم داشت رو معرفی کنم.معرفی ipدستور ip برای سیس ادمین‌های لینوکس دستور مهمیه. چون وضعیت کارت‌های شبکه یا اینترفیس‌ها رو میشه باهاش بررسی کرد. باip addrمیشه اینترفیس‌های سیستم لینوکسی رو دید و اطلاعات زیادی ازشون به دست آورد. با ip میشه اینترفیس‌ها رو کانفیگ هم کرد. ایجاد route در سیستم‌ از دیگر کارهایی هست که میشه باهاش انجام داد.یه کار باحال دیگه که میشه با ip کرد اینه که بیایم نیم‌اسپیس شبکه بسازیم. در مورد نیم‌اسپیس‌ها در لینوکس صحبت خواهم کرد.در قسمت‌های بعدی به طور عملی با ip کار خواهیم کرد.معرفی iptablesیکی از ابزارهایی که باهاش زیاد کار خواهیم کرد iptables هست. خیلی اینجا در موردش توضیح نمی‌دم. بعدا بیشتر آشنا می‌شیم و عملی کار می‌کنیم. ولی در این حد بگم که میشه باهاش در کرنل لینوکس ruleهایی تعریف کرد که می‌تونن کارهایی مثل فیلترینگ و NAT رو انجام بدن. کارهای باحالی باهاش انجام خواهیم داد. در کوبرنتیز هم به شکل پیش فرض از iptables برای پیاده‌سازی آبجکت Service استفاده میشه.معرفی tcpdumpبرای بررسی این که پکت‌های شبکه چه شکلی حرکت می‌کنن از tcpdump استفاده میشه. بیشتر جنبه‌ی دیباگ کردن داره و اگه کانفیگ جدیدی در شبکه زده باشیم کمک می‌کنه از درست بودنش مطمئن بشیم. ابزارهایی مثل tshark و wireshark هم هستن که می‌تونن به کار بیان در جاهای مختلف ولی tcpdump در خیلی از موارد کار رو راه می‌اندازه.جمع‌بندیتو این قسمت ۳ تا از ابزارهای شبکه که به نظرم مهم‌تر و پرکاربردتر هستن رو مختصرا توضیح دادم. جدا از بحثی که در مورد کانتینرها پیش می‌بریم ابزارهای گفته شده برای کسی که یه سیستم لینوکسی رو مدیریت می‌کنه هم مفیدن. با این مقدمه ان شاء الله در ادامه وارد بحث‌های جدی‌تر خواهیم شد.امیدوارم براتون مفید بوده باشه. اگه نظر یا سوالی دارید در قسمت نظرات بگید. </description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Fri, 04 Aug 2023 19:23:27 +0330</pubDate>
            </item>
                    <item>
                <title>چرا کوبرنتیز این شکلی طراحی شده؟ - قسمت چهارم و آخر</title>
                <link>https://virgool.io/paasino/kubernetes-design-principles-4-h7ibnqpulzqr</link>
                <description>مقدمهاین مطلب قسمت چهارم و آخر از سری نوشته‌های اصول طراحی کوبرنتیز هست. در سه قسمت قبلی سه اصل رو گفتیم و در مورد هر کدوم توضیحاتی داده شد. الان می‌خوایم اصل چهارم رو بررسی کنیم که ایجاد abstraction از زیرساخت هست. کوبرنتیز با داشتن این ویژگی مثل یک سیستم عامل اون چیزی که در زیرساخت هست رو از اپلیکیشن پنهان می‌کنه و باعث میشه بتونیم به راحتی بین زیرساخت‌های مختلف جابجا بشیم. این مطالب از یک ارائه در kubecon 2018 گرفته شدن.اگه در حوزه‌ی زیرساخت هستید و با کوبرنتیز کار می‌کنید این نوشته می‌تونه به شما دید خوبی بده تا علاوه بر ساختار کوبرنتیز علتش رو هم بدونید و عمیق‌تر با کوبرنتیز آشنا بشید. تو این نوشته فرض شده شما با کوبرنتیز آشنایی ابتدایی دارید. اگر هم تجربه‌ی عملی داشته باشید که چه بهتر. معرفی volume و persistent volume در کوبرنتیزقبل از رسیدن به بحث اصلی در مورد ذخیره‌سازی داده در کوبرنتیز صحبت می‌کنم. چون بهمون در درک مطلب کمک می‌کنه. راهی که ما در کوبرنتیز برای ذخیره کردن داده داریم استفاده از volume هست؛ مثل داکر که مفهوم volume رو داره و میشه اون رو داخل کانتینر mount کرد. اما در کوبرنتیز بسیار بیشتر به بحث ذخیره‌سازی پرداخته شده و انواع و اقسام گزینه‌ها برای این کار فراهم هست. بیاید یک نمونه پاد که از volume استفاده می‌کنه رو ببینیم:به دو قسمت توجه کنید؛ اول به volumes که در spec پاد نوشته میشه و بعد به volumeMounts که در داخل تعریف هر کانتینر میاد. با استفاده از volume میشه نوع اون رو مشخص کرد و در volumeMounts در تعریف کانتینر میشه volumeهای تعریف شده رو mount کرد. برای دیدن انواع volumeها به این لینک مراجعه کنید. با دیدن انواع volumeها ممکنه این طور به نظر بیاد که برای هر زیرساختی لازمه که تعریف volumeها رو تغییر بدیم؛ اما یک نوع volume بسیار مهم در کوبرنتیز وجود داره که در ایجاد abstraction به ما کمک می‌کنه و اون persistent volume هست.برای آشنایی با persistent volume در کوبرنتیز بیاید یک پاد رو با این نوع volume ببینیم:دقت کنید فقط تعریف volume عوض شده و از PersistentVolumeClaim استفاده شده که یک آبجکت در کوبرنتیز هست و نقش اصلی رو در ایجاد abstraction بازی می‌کنه. برای این که PersistentVolumeClaim رو در تعریف volume بیاریم باید قبلش این شکلی یه آبجکت ازش بسازیم:اینجا حجم دیسک درخواستی ۲ گیگ هست. توجه کنید که این آبجکت فقط یک درخواست برای منابع ذخیره‌سازی هست و باید یک PersistentVolume هم باشه که به این آبجکت bind بشه. بعد از ساختن این آبجکت با این دستور:kubectl apply -f pvc.yamlدو حالت داریم. یا باید یک آبجکت PersistentVolume رو ادمین کلاستر برامون بسازه که مشخصات claim رو برآورده کنه یا باید StorageClass داشته باشیم که به شکل اتوماتیک برای claim یک PersistentVolume بسازه. به طور خلاصه میشه ارتباط پاد با PersistentVolume و PersistentVolumeClaim رو در این عکس نشون داد:ما یک پاد می‌سازیم و یک PVC که به یک PV وصل یا bind میشه. خود PV می‌تونه به شکل dynamic یا static ساخته بشه. راجع به اون تقسیم‌بندی user space و kernel space در عکس در قسمت بعد توضیح میدم.اصل چهارم: ایجاد abstraction از زیرساختیکی از کارهایی که کوبرنتیز سعی کرده برای ما انجام بده، کاری شبیه عملکرد سیستم عامل است؛ یعنی موقعی که کاربران مختلف کلاستر می‌خوان پاد تعریف کنن به زیرساختی که توش هستن توجهی نمی‌کنن. این وظیفه‌ی ادمین کلاستر هست که با توجه به زیرساخت موجود نیازهای کاربران رو برطرف کنه. مثل سیستم عامل که سخت افزار زیرین رو برای نرم افزارها abstract می‌کنه. در مورد کوبرنتیز میشه به PVC و PV اشاره کرد. ما (به عنوان کاربر معمولی کلاستر) موقعی که پاد رو تعریف می‌کنیم تنها اسم PVC رو میاریم و پاد رو با اون تعریف می‌کنیم؛ به همین دلیل این دو تا آبجکت رو در شکل قبلی در user space آوردم. موقع تعریف PVC هم مقدار و نوع storage درخواستی رو می‌نویسیم. از اینجا به بعد دیگه دست ادمین کلاستر هست که یا به شکل static (دستی) یا dynamic (اتوماتیک) برای ما PV رو ایجاد کنه. در شکل قبلی هم اگر نگاه کنید می‌بینید ساخت PV در kernel space گذاشته شده که نشون میده اگه کلاستر کوبرنتیز رو سیستم عامل در نظر بگیریم، ساخت PV رو کرنل (ادمین کلاستر) باید انجام بده. با این ویژگی کاربران به راحتی می‌تونن workloadهای خودشون رو بین زیرساخت‌های مختلف انتقال بدن و دغدغه‌ای برای این جابجایی نداشته باشن.جمع‌بندیدر این قسمت اصل چهارم طراحی کوبرنتیز رو معرفی کردیم. به کمک کوبرنتیز ما می‌تونیم workloadهای خودمون رو به زیرساخت‌های مختلف ببریم و این موضوع اصل چهارم است. در مورد PVC و PV هم صحبت کردیم که به ما امکان ایجاد این abstraction از زیرساخت رو میدن.امیدوارم این مطلب براتون مفید بوده باشه. همون طور که اول گفتم این آخرین اصل بود. کدوم یک از این چهار اصل براتون جالب‌تر بود؟ آیا به نظرتون ویژگی مهمی از کوبرنتیز هست که در این اصول آورده نشده؟ نظرات خودتون رو این پایین بنویسید. اگر هم سوالی هست خوشحال میشم مطرح کنید. قسمت قبلی</description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Sat, 02 Apr 2022 15:08:55 +0430</pubDate>
            </item>
                    <item>
                <title>چرا کوبرنتیز این شکلی طراحی شده؟ - قسمت سوم</title>
                <link>https://virgool.io/paasino/kubernetes-design-principles-3-tlqbinzgjbqt</link>
                <description>مقدمهدر این سری نوشته‌ها قصد داریم ببینیم اصول طراحی کوبرنتیز چی هستن. در قسمت اول و دوم دو تا اصل رو بررسی کردیم و حالا وقتشه بریم سراغ سومی. در این قسمت ابتدا یکی از ویژگی‌های ایده‌آل یک نرم‌افزار رو معرفی می‌کنیم و بعد بحث می‌کنیم چجوری با کوبرنتیز میشه این ویژگی رو پیاده کرد. جا داره دوباره اشاره کنم این مطالب از یک ارائه در kubecon 2018 گرفته شدن. اگه در حوزه‌ی زیرساخت هستید و با کوبرنتیز کار می‌کنید این نوشته می‌تونه به شما دید خوبی بده تا علاوه بر ساختار کوبرنتیز علتش رو هم بدونید و عمیق‌تر با کوبرنتیز آشنا بشید. تو این نوشته فرض شده شما با کوبرنتیز آشنایی ابتدایی دارید. اگر هم تجربه‌ی عملی داشته باشید که چه بهتر.متدولوژی Twelve-Factor App در نوشتن نرم‌افزارقبل از رسیدن به اصل سوم بذارید یه کم مقدمه‌چینی کنم. احتمالا در مورد متدولوژی Twelve-Factor App یا ۱۲ فاکتور شنیدید. در این متدولوژی ۱۲ ویژگی ایده‌آل برای نرم‌افزار شمرده شده که با رعایت اون‌ها می‌تونیم فرایند بهتری برای توسعه‌ی نرم‌افزار داشته باشیم. یکی از  ویژگی‌های شمرده شده در این متدولوژی این هست که کانفیگ نرم‌افزار باید در محیطی که دیپلوی میشه باشه نه داخل کد به شکل هاردکد شده. منظور از کانفیگ هر چیزی هست که بین محیط‌های مختلف (مثل staging و production) عوض میشه؛ مثلا یک نرم‌افزار موقع اجرا می‌خواد بدونه برای اتصال به دیتابیس باید به چه آدرسی وصل بشه. برای دادن چنین چیزی نباید اون رو داخل کد قرار بدیم. بلکه باید از یک فایل یا متغیر محیطی بخونیم. در این لینک می‌تونید بیشتر در موردش بخونید.حالا که در مورد این ویژگی حرف زدیم، باید ببینیم آیا کوبرنتیز چنین امکانی به ما میده؟ و اگر جواب مثبته چطوری؟معرفی ConfigMap و Secretدو تا از آبجکت‌هایی که در کوبرنتیز میشه ساخت و داخل اون‌ها کانفیگ‌های نرم‌افزار رو قرار داد، ConfigMap و Secret هستن. یه نمونه از هر کدوم رو ببینیم. اولی یک ConfigMap هست:و دومی Secret:در ConfigMap تنظیمات غیرحساس رو می‌ذارن. مثلا اینجا اطلاعات اتصال به دیتابیس گذاشته شده‌ان و در نیم‌اسپیس staging هست. در مورد Secret باید توجه کنیم که اطلاعات فقط base64 میشن و عملا به شکل مستقیم در دسترس هستن. توی این مثال نام کاربر و رمز دیتابیس رو گذاشتم. میشه دسترسی به Secretها رو در کلاستر محدود کرد یا از روش‌های امن‌تری برای نگهداری Secret استفاده کرد که بحث ما اینجا نیست. هدف اینه که این دو تا آبجکت رو بشناسیم.خب حالا این‌ها رو در یه فایل می‌ذاریم و با زدن این دو دستور آبجکت‌ها رو می‌سازیم:kubectl apply -f secret.yaml
kubectl apply -f configmap.yaml چجوری در نرم‌افزار استفاده‌اش کنیم؟ یک راهی که به ذهن می‌رسه این هست که خود برنامه بیاد به API Server درخواست بده و این آبجکت‌ها رو بخونه. اما این کار اصلا خوب نیست چون نمی‌خوایم برنامه وابسته به زیرساختی که توش هست باشه؛ چون ممکنه من بخوام توی سیستم خودم برای تست با داکر اجراش کنم. اونجا دیگه API Serverی در کار نیست. علاوه بر این، برای این کار باید کد رو تغییر بدیم تا از API Server کانفیگ رو بخونه که باعث میشه هزینه‌ی زمانی بیشتری برای استفاده از کوبرنتیز بدیم. پس این کار رو نمی‌کنیم. اینجاست که به اصل سوم می‌رسیم؛ یعنی قابلیت جابجایی کاربر در محیط‌های مختلف.اصل سوم: قابلیت جابجایی در محیط‌های مختلفنمی‌دونم ترجمه‌ی خوبی هست یا نه ولی در ارائه این اصل رو&quot;meet the users where they are&quot;عنوان کرده. منظورش اینه که ما کافیه ویژگی گفته شده در متدولوژی ۱۲ فاکتور رو رعایت کنیم و کانفیگ رو از محیط (فایل یا متغیر محیطی) بگیریم. وقتی از روی کد ما ایمیج ساخته ميشه و در تعریف پاد میاریمش، همونجا می‌تونیم این فایل‌های کانفیگ یا متغیرهای محیطی رو تعیین کنیم. مثلا فرض کنید برنامه‌ای که نوشتم از مسیر/app/config/.envاطلاعات دیتابیس به غیر از نام کاربر و رمز رو می‌خونه. می‌تونم پادم رو این شکلی تعریف کنم و از ConfigMap ساخته شده در قسمت قبل استفاده کنم:اینجا قصد آموزش ندارم. فقط خلاصه بگم که یک volume تعریف کردم که از ConfigMap استفاده می‌کنه و در کانتینر مربوطه فایل رو در مسیر مناسب قرار دادم. به شکل مشابه میشه از Secret هم استفاده کرد.راه‌های دیگه‌ای برای دادن کانفیگ به پاد هست که بهش نمی‌پردازیم. هدفم این بود که ببینیم کوبرنتیز چنین قابلیت‌هایی داره.با توجه به این اصل کوبرنتیز من می‌تونم ایمیجی که ساختم و تعریف پاد متناظرش رو به راحتی بین کلاستر یا نیم‌اسپیس‌های مختلف جابجا کنم. تنها چیزی که بین محیط‌ها تغییر می‌کنه اون ConfigMap یا Secret هست که رفتار نرم‌افزار رو متناسب با محیط تغییر میده. مثلا در تعریفشون نیم‌اسپیس رو به جای staging می‌ذاریم production و مقادیر رو به شکل مناسب تغییر می‌دیم. این شکلی میشه ازشون در پادهای production استفاده کرد. علاوه بر این برنامه هیچ اطلاعی نخواهد داشت که روی کوبرنتیز هست یا نه.جمع‌بندیدر این مطلب ابتدا در مورد متدولوژی ۱۲ فاکتور صحبت کردیم  و یکی از ویژگی‌های مهمی که نرم‌افزارها باید داشته باشن (گرفتن کانفیگ از محیط) رو بررسی کردیم. در ادامه دیدیم چجوری میشه از قابلیت‌های کوبرنتیز استفاده کرد تا بشه نرم‌افزاری رو که این ویژگی رو داره در محیط‌های مختلف دیپلوی کنیم. به این شکل دیگه لازم نیست کد رو تغییر بدیم و میشه به راحتی کانفیگ نرم‌افزار رو در جای مناسب قرار داد. بدون این که نرم‌افزار بدونه در کوبرنتیز اجرا میشه.امیدوارم این مطلب براتون مفید بوده باشه. اگر سوال یا نظری دارید این پایین بنویسید.قسمت قبلیقسمت بعدی</description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Sat, 19 Mar 2022 20:02:15 +0330</pubDate>
            </item>
                    <item>
                <title>چرا کوبرنتیز این شکلی طراحی شده؟ - قسمت دوم</title>
                <link>https://virgool.io/paasino/kubernetes-design-principles-2-fals1tgr93tn</link>
                <description>مقدمهدر قسمت قبل در مورد اصل اول طراحی کوبرنتیز گفتیم. چی بود؟ اینکه به جای imperative در کوبرنتیز از declarative API استفاده شده. توضیح هر کدوم هم دیدیم. حالا در ادامه‌ی بحث قبلی قراره اصل دوم رو ببینیم. این مطالب برگرفته از ارائه‌ی سعد علی از شرکت گوگل در kubecon سال ۲۰۱۸ هست. ایشون جزو توسعه‌دهندگان کوبرنتیز هست و تو این ارائه توضیح میده که اصول معماری کوبرنتیز چه چیزهایی هستن و دلیل هر کدوم چیه.اگه در حوزه‌ی زیرساخت هستید و با کوبرنتیز کار می‌کنید این نوشته می‌تونه به شما دید خوبی بده تا علاوه بر ساختار کوبرنتیز علتش رو هم بدونید و عمیق‌تر با کوبرنتیز آشنا بشید. تو این نوشته فرض شده شما با کوبرنتیز آشنایی ابتدایی دارید. اگر هم تجربه‌ی عملی داشته باشید که چه بهتر.سوالآخر قسمت قبل این سوال رو پرسیدم که «وقتی ما به کوبرنتیز (دقیق‌ترش رو بگم API server) گفتیم حالت دلخواهمون چیه چه شکلی ما رو به اون می‌رسونه» آیا API server خودش به نودها دستورات لازم رو میده؟ جوابش نه هست. برای این که ببینیم چجوری اصل دوم رو می‌بینیم.اصل دوم: هیچ API پنهانی بین اجزای کوبرنتیز نیستممکنه یه کم مبهم باشه عنوانش. قدم به قدم جلو میریم تا ببینیم چی میگه.معنی API پنهان چیه؟بیاید تعریف این پاد رو در نظر بگیریم:apiVersion: v1 
kind: Pod
metadata:
  name: frontend
  labels:
    app: cache
    tier: frontend
spec:
   containers:
        - name: web-server
          image: nginx:1.21.1
فرض کنید ماشین مستر خودش با نودها صحبت می‌کرد و پاد رو برای ما بالا می‌آورد. برای این باید به نودها درخواست می‌داد و می‌گفت یه کانتینر از روی ایمیج nginx:1.21.1 بسازید. در کنارش باید مدام وضعیت کانتینر رو روی نودها بررسی می‌کرد و اگه تغییری لازم داشتن اعمال می‌کرد. این حالت رو توی عکس‌های زیر می‌بینید.برای این درخواست‌هایی که مستر به نودها میده، لازم هست یک API در نودها وجود داشته باشه تا کاملا توسط مستر کنترل بشن. این API از ما کاربران مخفیه و ازش استفاده نمی‌کنیم؛ به همین دلیل اسمش شد API پنهان. چیزی که اصل دوم میگه اینه که چنین APIی وجود نداره. نودها و بقیه‌ی اجزای کوبرنتیز دقیقا با همون APIی که ما (مثلا با kubectl) استفاده می‌کنیم با مستر صحبت می‌کنن و مستر مخفیانه با اون‌ها حرف نمی‌زنه. اگر مستر خودش می‌خواست تمام جزئیات رو مدیریت کنه بسیار سنگین می‌شد و مثل الان اجزاش قابل گسترش یا جایگزینی نبودن.پس چجوری پادها بالا میان؟درک جواب این سوال به ما کمک می‌کنه که تقریبا نحوه‌ی کار همه‌ی اجزای کوبرنتیز رو متوجه بشیم. بذارید مثال قبل رو ادامه بدیم. من به کوبرنتیز گفتم یه پاد درست کنه. وقتی دستور ساخت پاد به API server  داده میشه (هنوز روی نودها کانتینری ساخته نشده) باید تعیین بشه روی کدوم نود بالا بیاد. اینجا scheduler که خودش یه عضوی از مستر هست می‌بینه یه پاد هست که نود نداره:چجوری scheduler متوجه میشه؟ scheduler در هر لحظه API server رو watch می‌کنه که اگه پادی بدون نود ساخته شد، دست به کار بشه و با توجه به معیارهایی که داره یک نود رو برای هر پاد مشخص کنه. بعد از تعیین نود، آیا scheduler به اون نود میگه که پاد رو بسازه؟ نه. فقط به API server میگه پاد رو آپدیت کنه و  مقدار نود رو تعیین می‌کنه:تو این مثال مقدار رو  node 2 قرار داده. نودها هم هميشه دارن API server رو watch می‌کنن که اگه یه پاد به اون‌ها داده شد، ایجادش کنن. الان نود ۲ می‌بینه یک پاد بهش اختصاص داده شده و هنوز اون رو نساخته. پس یه کانتینر رو از روی ایمیج nginx:1.21.1 می‌سازه (اگه لازم باشه ایمیج پول میشه):از این به بعد حواس این نود هست که همیشه این پاد بالا باشه. اگر ما پاد رو از روی API server حذف کنیم، نود مطلع میشه و اون پاد رو حذف می‌کنه:توجه کنید که منظورم از نود تو همه‌ی موارد kubelet بود.این چه خوبی‌ای داره؟با این روش سیستم ما در مقابل اتفاقات غیرمنتظره خیلی مقاوم‌تر هست. فرض کنید یک نود مدتی از دسترس خارج بشه و بعد برگرده. وقتی برمی‌گرده دوباره API server رو نگاه می‌کنه و اگه لازم باشه پادی بسازه، می‌سازه یا اگه باید پادی حذف بشه، حذفش می‌کنه. یعنی تنها وضعیت فعلی مهمه و تغییراتی که تو بازه‌ی قطعی افتاده تاثیری روی نود نداره. هم‌چنین اگه مستر از دست بره خود نود‌ها وضعیت فعلی‌شون رو حفظ می‌کنن تا دوباره مستر بالا بیاد. یعنی با از دست رفتن مستر کلاستر نابود نمیشه. نکته‌ی دیگه اینه که مستر خیلی بزرگ و سنگین نمیشه و اجزای مختلف در یک ساختار توزیع‌شده دست به دست هم میدن تا به حالت مطلوب کاربر برسن.یکی از بزرگ‌ترین مزیت‌های این روش اینه که میشه کوبرنتیز رو گسترش داد. یعنی ممکنه من بخوام به جای scheduler کوبرنتیز یک scheduler مخصوص خودم بذارم. بدون تغییر در ساختار کوبرنتیز scheduler رو با برنامه‌ای که خودم نوشتم جایگزین می‌کنم. کافیه فقط بتونه با API server صحبت کنه و منطق خاص من رو برای scheduling پیاده کنه. هم‌چنین اگه یک کاری رو کوبرنتیز نمی‌کنه، من خودم می‌تونم به کوبرنتیز اضافه کنم. مفهوم CRD و اپراتور هم به این شکل در کوبرنتیز قرار گرفته. برای مثال اپراتورهایی که برای دیتابیس‌ها وجود دارن یا اپراتور پرومتئوس. از قدرتمند‌ترین ویژگی‌های کوبرنتیز همین گسترش‌پذیری‌اش هست.جمع‌بندیتو این قسمت در مورد اصل دوم در طراحی کوبرنتیز صحبت کردیم. به شکل خلاصه اگر بخوایم بگیم، در کوبرنتیز اجزا به طور مستقل API server رو watch می‌کنن و هر کدوم نقش خودشون رو برای رسیدن به وضعیت مطلوب ایفا می‌کنن. به این شکل دیگه لازم نیست در مستری چیزی باشه که به بقیه دستور بده چی کار کنن. این باعث میشه مستر سبک‌تر باشه، سیستم در مقابل اتفاقات مقاوم‌تر باشه و کوبرنتیز قابلیت گسترش داشته باشه.امیدوارم براتون مطلب مفیدی بوده باشه. اگر سوال یا نکته‌ای دارین این پایین بفرمایین.قسمت قبلیقسمت بعدی</description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Fri, 03 Dec 2021 22:44:21 +0330</pubDate>
            </item>
                    <item>
                <title>چرا کوبرنتیز این شکلی طراحی شده؟ - قسمت اول</title>
                <link>https://virgool.io/@hemmati.ali.a/kubernetes-design-principles-pu8opvf0gxyx</link>
                <description>مقدمهکوبرنتیز که این همه سر و صدا کرده چجوری طراحی شده؟ و دلیل این طراحی چیه؟ جواب این دو تا سوال می‌تونه به افرادی که در زمینه‌ی زیرساخت کار می‌کنن کمک کنه درک بهتری از این ابزار محبوب داشته باشن. تو این قسمت و قسمت‌های بعد می‌خوام راجع به این موضوع صحبت کنم. این مطالب برگرفته از ارائه‌ی سعد علی از شرکت گوگل در kubecon سال ۲۰۱۸ هست. ایشون جزو توسعه‌دهندگان کوبرنتیز هست و تو این ارائه توضیح میده که اصول معماری کوبرنتیز چه چیزهایی هستن و دلیل هر کدوم چیه. ما هم اینجا اون اصول رو بررسی می‌کنیم. اگه در حوزه‌ی زیرساخت هستید و با کوبرنتیز کار می‌کنید این نوشته می‌تونه به شما دید خوبی بده تا علاوه بر ساختار کوبرنتیز علتش رو هم بدونید و عمیق‌تر با کوبرنتیز آشنا بشید. تو این نوشته فرض شده شما با کوبرنتیز آشنایی ابتدایی دارید. اگر هم تجربه‌ی عملی داشته باشید که چه بهتر.کوبرنتیز چیه؟خب فرض کرده بودیم کسایی که این متن رو می‌خونن می‌دونن کوبرنتیز چیه. پس این بخش رو فاکتور می‌گیریم :) برای اطلاعات بیشتر به سایت رسمی کوبرنتیز مراجعه کنید. حالا که معلوم شد کوبرنتیز چیه، به اصول طراحی کوبرنتیز می‌رسیم.اصل اول - declarative به جای imperativeتفاوت imperative با declarative این دو تا عبارت رو احتمالا در ابزارهای دواپس زیاد دیدید و شنیدید. imperative یعنی من وقتی می‌خوام یه کاری انجام بشه تمام دستورات لازم برای اون رو بگم. مثلا یه برنامه نوشتم و از روش یک ایمیج ساختم و تو یه رجیستری پوش کردم. می‌خوام همیشه سه تا کانتینر از این بالا باشه.‌ برای انجامش به شکل imperative باید بگم اول ایمیج رو پول کنم، بعد از روی ایمیج سه تا کانتینر بسازم و حواسم باشه هر وقت تعداد کانتینرها کم شد (مثلا یکیش OOM شد) دوباره یه دونه بالا بیارم. تازه اگه چند تا ماشین مجازی یا حقیقی داشته باشم که بحث scheduling هم پیش میاد.اما declarative برخلاف این هست. یعنی من حالت مورد انتظارم رو میگم و بقیه‌اش رو می‌سپارم به یه ابزاری که خودش اون حالت رو برآورده کنه. مثلا میگم سه تا کانتینر از ایمیج nginx:1.21.1. دیگه کاری ندارم چه اتفاقی می‌افته. ابزاری که دارم خودش حواسش هست و سعی می‌کنه به اون حالت مطلوب برسه. اینجا اون ابزار کوبرنتیزه.یک مثالتفاوت این دو تا رو میشه با یه مثال بهتر درک کرد. imperative مثل وقتی هست که خلبان هواپیما خودش داره هواپیما رو کنترل می‌کنه. تو این شرایط خلبان همه چیز رو مانیتور می‌کنه و اگه کاری لازم باشه انجام میده. در مقابلش declarative حالت auto pilot هست که سیستم خود هواپیما کنترل‌کننده است و تغییرات رو زیر نظر داره و همیشه سعی می‌کنه وضعیت رو اون طور که خلبان گفته نگه داره.در کوبرنتیز چه شکلی پیاده شده؟ حالا بیاید ببینیم در کوبرنتیز چجوری از declarative API استفاده میشه. به عنوان مثال فرض کنید ما با kubectl به API server دستور میدیم که یک object (مثلا یک ReplicaSet) ساخته بشه و اون هم داخل etcd ذخیره‌اش می‌کنه. تعریف ReplicaSet تو این مثال این شکلی هست: apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
  labels:
    app: cache
    tier: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
       -name: web-server
        image: nginx:1.21.1
خواستم که ۳ تا پاد از ایمیج nginx:1.21.1 رو همیشه بالا نگه داره. از این به بعد دیگه کاری نداریم که چه اتفاقی می‌افته. خود کوبرنتیز حواسش هست که همیشه این ۳ تا بالا باشن. تو این شکل‌های پایین به شکل ساده شده این موضوع رو می‌بینین:ارسال درخواست به کوبرنتیز برای ساخت ReplicaSetایجاد پادها توسط کوبرنتیز روی نودهای workerگفتم کوبرنتیز خودش حواسش هست که ۳ تا رپلیکا همیشه داشته باشیم؛ اما چجوری حواسش هست؟ آیا API server خودش این رو مدیریت می‌کنه؟ یا شکل دیگه‌ای پیاده شده؟ این که چجوری این اتفاق در کوبرنتیز می‌افته موضوع اصل دوم هست که ایشالا در قسمت بعد صحبت می‌کنیم. جمع‌بندیدر این نوشته یکی از اصول طراحی کوبرنتیز که داشتن declarative API به جای imperative بود رو بررسی کردیم و تفاوت این دو رو هم دیدیم. در قسمت بعد در مورد اصل دوم حرف می‌زنیم. امیدوارم این نوشته براتون مفید بوده باشه. اگر نظر یا سوالی دارین این پایین بفرمایین.قسمت بعد </description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Wed, 24 Nov 2021 23:23:03 +0330</pubDate>
            </item>
                    <item>
                <title>داکر برای برنامه‌نویس‌ها: قسمت سیزدهم - آشنایی با اجزای فایل docker-compose.yaml</title>
                <link>https://virgool.io/paasino/docker-compose-file-h74vx0ch0czc</link>
                <description>مقدمهدر قسمت قبل با داکر کامپوز آشنا شدیم و یه سرویس کوچولو باهاش راه انداختیم. تو این قست کمی دقیق‌تر اجزای یه فایل docker-compose.yaml رو بررسی می‌کنیم و یه اپ‌ جنگو با دیتابیس پستگرس بالا میاریم. کد این قسمت رو در این ریپو در گیتهاب می‌تونید ببینید.برای همراهی با این مطلب لازمه که تجربه‌ی کار با داکر و کانتینرها رو داشته باشین و هم‌چنین آشنایی ابتدایی با داکر کامپوز داشته باشین. اگر این طور نیست خوبه که آموزش‌های قبلی رو ببینید.ساختار کلی فایل اولین چیزی که توی docker-compose.yaml می‌نویسیم ورژن است. ورژن‌های مختلف داکر کامپوز ویژگی‌های مختلفی را پشتیبانی می‌کنن. ما در اینجا جدیدترین نسخه رو نوشتیم:version: &amp;quot3.9&amp;quotبعد از اون services رو داریم که اصل کار ماست.version: &amp;quot3.9&amp;quot
services:داخل این بخش هر چی سرویس داریم رو می‌نویسیم. مثلا یک اپ بک اند داریم و یک دیتابیس. در نتیجه دو تا سرویس داخل services باید بنویسیم. version: &amp;quot3.9&amp;quot
services:
   web:

    db:
برای مشخص کردن هر سرویس اول یه اسم می‌نویسیم. تو مثال بالا یه سرویس به نام web داریم که همون اپ جنگو هست و یه سرویس db برای دیتابیس. حالا داخل هر سرویس قراره مشخصاتش رو بنویسیم و هر کدوم رو پر کنیم. نوشتن سرویس webمن به web یک ایمیج دادم با عبارت image. اسم و تگ ایمیج رو اینجا باید بنویسیم. بعدش تعدادی پورت با ports نوشتم. ترتیب عبارات در فایل yaml تفاوتی ایجاد نمی‌کنه. version: &amp;quot3.9&amp;quot
services:
  web:
    image: django-blog:1
    environment:
      - DB_NAME=postgres
      - DB_USER=postgres
      - DB_PASSWORD=postgres
      - DB_HOST=db
      - DB_PORT=5432 
    ports:
      - &amp;quot8000:8000&amp;quot
    depends_on:
      - dbدقت کنید که ports یک لیست می‌گیره و مثل وقتی هست که با docker run آپشن p- رو می‌زدیم؛ یعنی اول پورت روی سیستم میزبان و دوم پورت کانتینر. اگر بخوایم متغیر محیطی داشته باشیم اون رو با environment می‌نویسیم. تو این مثال مشخصات اتصال به دیتابیس رو دادم. همون طور که معلومه به شکل لیست داده میشه. تو هر مورد به ترتیب اسم متغیر، علامت = و مقدارش میاد. متغیرهای محیطی رو این شکلی هم میشه نوشت: environment:
    DB_NAME: postgres
    DB_USER: postgres
    DB_PASSWORD: postgres
    DB_HOST: db
    DB_PORT: 5432 اگر یه فایل از قبل دارید که این متغیرها از قبل توش نوشته شده می‌تونید با env_file بنویسید و بعد مسیر فایل رو بدید:env_file:
    - web-variables.envهمونطور که می‌بینید یک لیست هست و میشه چندتا فایل هم داد. اگه شما سورس کدی دارین و دارین توسعه‌اش میدین می‌تونین خودتون هر دفعه با دستور docker build بیلدش کنین و اسم ایمیج رو توی image بهش بدین. اما میشه بیلد رو به کمک داکر کامپوز انجام داد. یعنی یک قسمت به نام build به سرویس اضافه کنیم و به این شکل در میاد سرویس web:version: &amp;quot3.9&amp;quot 
services:
   web:
     build: ./
     environment:
       - DB_NAME=postgres
       - DB_USER=postgres
       - DB_PASSWORD=postgres
       - DB_HOST=db
       - DB_PORT=5432
     ports:
       - &amp;quot8000:8000&amp;quot
     depends_on:
       - dbجلوی build مسیر ساخت ایمیج رو میدیم. همونجور که موقع زدن docker build می‌دادیم. حالا هر وقت کدمون تغییری کنه میشه در روت پروژه دستور docker-compose build رو زد تا بیلد انجام بشه. دیگه image رو لازم نیست بنویسم. اگه بنویسم اسم و تگ ایمیجی که ساخته میشه رو می‌ذاره همون چیزی که من جلوی image نوشتم.یه نکته باقی مونده. اونم اینه که برنامه‌ی جنگوی من برای شروع نیاز داره که دیتابیس آماده باشه. برای این که وابستگی رو بیان کنیم توی سرویس web از depends_on استفاده می‌کنیم و یه لیست میدیم از سرویس‌هایی که این سرویس بهشون وابسته است. اینجا web فقط به db وابسته بود.نوشتن سرویس dbحالا سرویس دیگه‌مون که db هست رو می‌نویسیم:version: &amp;quot3.9&amp;quot 
services:
   web:
     image: django-blog:1
     environment:
       - DB_NAME=postgres
       - DB_USER=postgres
       - DB_PASSWORD=postgres
       - DB_HOST=db
       - DB_PORT=5432
     ports:
       - &amp;quot8000:8000&amp;quot
     depends_on:
       - db
  db:
    image: postgres
    volumes:
      - ./data/db:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgresایمیجش postgres هست چون می‌خوام از این دیتابیس استفاده کنم. در این سرویس می‌خوام اطلاعاتم باقی بمونه و با هر بار از خاموش و روشن کردن کانتینر از بین نره. به همین دلیل از volume استفاده کردیم. داخلش یه لیست قرار می‌گیره و مثل آپشن v- در docker run اول مسیر تو سیستم خودمون رو میدیم بعدش مسیر داخل کانتینر. اینجا می‌خوام اطلاعات دیتابیس که در مسیر var/lib/postgresql/data/ درون کانتینر هست رو توی پوشه‌ی data/db داخل پروژه‌ی خودم نگه دارم. بقیه‌ی چیزهایی که نوشتم رو قبلا دیدیم. اجرای سرویس‌هاالان دیگه آماده‌ایم. تو همون پوشه دستور docker-compose up رو می‌زنیم: به نظر میاد همه چی خوبه. حالا برای اطمینان از کارکردش با curl یک درخواست بهش می‌فرستم که یک user جدید بسازم:می‌بینید در جواب کد ۲۰۱ داده شده و همه چی خوب کار می‌کنه.جمع‌بندیما در این قسمت دیدیم چجوری یه فایل داکر کامپوز برای اپ جنگو با دیتابیس بنویسیم. با بعضی از تنظیماتی که میشد روی سرویس‌ها انجام داد هم آشنا شدیم. برای دیدن مرجع کامل داکر کامپوز به این لینک در سایت داکر مراجعه کنید.اميدوارم این مطلب براتون مفید بوده باشه. اگه سوال یا نظری دارین این پایین بگین.قسمت قبلی</description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Fri, 05 Nov 2021 20:55:01 +0330</pubDate>
            </item>
                    <item>
                <title>داکر برای برنامه‌نویس‌ها: قسمت دوازدهم - معرفی داکر کامپوز</title>
                <link>https://virgool.io/paasino/docker-compose-intro-inlgmaj0kixv</link>
                <description>مقدمهبرنامه‌هایی که می‌نویسیم معمولا تنها نیستند و کنارشون باید سرویس‌های دیگه‌ای هم اجرا بشن. مثلا یک دیتابیس کنار برنامه اصلی باید باشه تا بتونه اطلاعات رو ذخیره کنه. هنگام نوشتن و تست برنامه‌ هم دوست داریم چنین شرایطی رو داشته باشیم. یعنی واقعا یک دیتابیس بالا بیاد و برنامه‌ی ما بتونه با اون کار کنه. داکر کامپوز (docker compose) ابزاری هست که به ما اجازه میده چند تا سرویس رو در داکر کنار هم بالا بیاریم و به هم متصل کنیم. در این مطلب قصدمون این هست که یک معرفی کوتاهی بر داکر کامپوز داشته باشیم، نصبش کنیم و یه سرویس ساده هم باهاش اجرا کنیم.برای درک بهتر این نوشته باید با داکر و کانتینرها کار کرده باشید و به یک سیستم لینوکسی دسترسی داشته باشید.آشنایی با داکر کامپوزهمون طور که در بخش قبلی گفته شد شما با داکر کامپوز می‌تونید چند سرویس کانتینری رو کنار هم اجرا کنید. کافیه در یک فایل yaml اطلاعات رو بنویسید و با دستور docker-compose up اون رو اجرا کنید. فرض کنید یه سرویس جنگو (یک فریم ورک بک اند به زبان پایتون) نوشتید و اون نیاز داره به یک دیتابیس MySQL وصل بشه. تو فایل yaml می‌تونید دو تا سرویس تعریف کنید که یکیش ایمیج mysql هست و دیگری ایمیجی که از روی کد شما ساخته میشه. در این فایل yaml اطلاعات ارتباط جنگو به mysql رو می‌دیم و وقتی جنگو بالا بیاد به یک دیتابیس MySQL وصل میشه. به این شکل در محیط development خودتون می‌تونید برنامه رو تست کنید.نصب داکر کامپوزحالا این ابزار باحال رو چجوری نصب کنیم؟ قبل از نصب لازمه داکر رو داشته باشید. برای نصب داکر می‌تونید به این پست قبلی مراجعه کنید. در این‌جا نصب داکر کامپوز در یک سیستم لینوکسی رو میگیم. برای داشتن داکر کامپوز فقط کافیه یک فایل باینری رو دانلود کنیم و قابلیت اجرایی بهش بدیم. به این لینک برید و آخرین نسخه‌ (یا هر نسخه‌ای که می‌خواید) رو دانلود کنید.من اونی که تو عکس دورش خط کشیدم رو دانلود کردم. حالا با دستور زیر بهش قابلیت اجرایی میدم: chmod +x docker-compose-Linux-x86_64 دستور chmod دسترسی‌های مختلف فایل رو تغییر میده. این‌جا فقط قابلیت اجرا شدن رو به فایل دادم. الان میشه اجراش کرد: این خروجی نشون میده تا اینجا درست اومدم. اما خوبه که فایل باینری رو تو PATH سیستم بذارم تا هر دفعه راحت اجراش کنم. اسمش هم عوض می‌کنم که راحت‌تر بنویسمش. برای این کار این دستور رو اجرا می‌کنم:  mv docker-compose-Linux-x86_64 /usr/local/bin/docker-composeدیگه به راحتی تو هر مسیری می‌تونم docker-compose رو اجرا کنم:اجرای سرویس سادهیک فایل با نام docker-compose.yaml ایجاد کنید و داخل اون این شکلی بنویسید:version: &amp;quot3.9&amp;quot
services:
    nginx:
        image: &amp;quotnginx&amp;quot    
        ports:     
             - &amp;quot8000:80&amp;quotاین فایل تنها یه کانتینر nginx بالا میاره که روی پورت ۸۰۰۰ در سیستم میزبان جواب میده. در همون پوشه‌ای که این فایل درش قرار داره دستور docker-compose up رو بزنید تا این خروجی رو ببینید: این نشون میده داکر کامپوز داره کارش رو به خوبی انجام میده. می‌تونید در مرورگر خودتون آدرس localhost:8000 برید و ببینید nginx داره جواب میده. خب اینم از این. در قسمت‌های بعدی ان شاء الله نوشتن این فایل رو یاد می‌گیریم.جمع بندیدر این مطلب با داکر کامپوز آشنا شدیم، نصبش کردیم و یک سرویس ساده رو باهاش اجرا کردیم. امیدوارم براتون مفید بوده باشه. اگر نظر یا سوالی دارین این پایین بفرمایین.قسمت قبلیقسمت بعدی</description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Mon, 26 Apr 2021 23:49:57 +0430</pubDate>
            </item>
                    <item>
                <title>داکر برای برنامه‌نویس‌ها: قسمت یازدهم - best practices (ادامه)</title>
                <link>https://virgool.io/paasino/best-practices-2-ok7dfmsx1fk5</link>
                <description>مقدمهقسمت قبلی با تعدادی از best practiceهای دنیای کانتینرها و داکر آشنا شدیم. در این قسمت می‌خوایم به تعدادی دیگه‌ از این‌ نکات بپردازیم. این نوشته برای برنامه‌نویس‌ها و مهندسان DevOps مفید می‌تونه باشه.فرض بر این هست که شما سابقه برنامه‌نویسی دارید و با کانتینرها و داکر هم کار کردید.استفاده از dockerignore. وقتی در یک پوشه دستور docker build رو اجرا می‌کنیم کل محتوای پوشه به عنوان build context به حساب میان و اگر کل پوشه رو کپی کنیم همه‌شون میرن به ایمیج. بعضی از فایل‌ها یا پوشه‌ها ممکنه داخل ایمیج لازم نباشن. چجوری اینا رو حذف کنیم؟ مثل gitignore. داکر هم یه فایل dockerignore. داره که با اون می‌تونیم هر چیزی که نمی‌خوایم رو حذف کنیم. این شکلی بدون این که دست به ساختار پوشه بزنیم یه چیزایی رو کنار می‌ذاریم. مثلا ممکنه یک سری README.md نوشته باشید و نخواید تو ایمیج بذارید. این جاست که dockerignore. به دردتون می‌خوره. برای آشنایی با نحوه‌ی استفاده از الگوهای مختلف در این فایل می‌تونید این لینک رو ببینید.بیلد چند مرحله‌ایبعضی از برنامه‌ها هستن که برای بیلد شدن باید کامپایل بشن و برای این کامپایل شدن باید تعدادی ابزار وجود داشته باشه. این ابزارها برای اجرای نهایی برنامه لازم نیستن و باعث میشن حجم ایمیج زیاد بشه. این جور مواقع از بیلد چند مرحله‌ای استفاده می‌کنیم. به عنوان مثال زبان گو رو در نظر بگیرید. وقتی برنامه‌ای به این زبان کامپایل میشه یک فایل باینری به دست میاد که فقط باید دسترسی execute بهش بدیم تا بتونیم اجراش کنیم. چیز دیگه‌ای لازم نیست. یک داکرفایل به عنوان مثال آوردم:
FROM golang:1.7.3 AS builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app .
CMD [&amp;quot./app&amp;quot]این مثال تو این لینک آورده شده. دقت کنید دو تا FROM داریم. یعنی دو تا مرحله داریم و دو تا ایمیج قراره ساخته بشه. تو مرحله اول از ایمیج رسمی golang استفاده شده و برنامه رو بیلد کرده. خروجی بیلد به یک فایل به نام app میره. چیزی که احتمالا بهش توجه کردید AS builder در انتهای خط اوله. AS یکی از keywordهای داکرفایل هست و یک اسم به ایمیجی که ساخته میشه میده. این اسم رو گذاشتیم تا در مرحله دوم ازش استفاده کنیم.حالا بریم سراغ FROM دوم. می‌بینید که از alpine استفاده کرده که حجم خیلی کوچیکی داره. این همون چیزیه که این روش رو خیلی جذاب می‌کنه. تنها کافیه فایل باینری رو از ایمیج قبلی کپی کنیم. تو دستور COPY یک آپشن استفاده شده و اون from-- هست. با این آپشن اسم ایمیجی که ازش کپی می‌کنیم تعیین میشه. یعنی دیگه از سیستم خودمون کپی نمی‌کنیم. تو این مورد اسم ایمیج قبلی builder است. آخر سر هم app رو اجرا می‌کنیم. با این روش به جای استفاده از ایمیج golang که بیش از ۲۰۰ مگابایت حجم داره رسیدیم به alpine (با تنها چند مگابایت حجم) به علاوه فایل باینری.استفاده از non root userدستوراتی که توی داکرفایل برای RUN و ENTRYPOINT و CMD می‌نویسیم با کاربر root اجرا میشن. اما این از لحاظ امنیتی ممکنه خطرساز بشه؛ چون دسترسی بالایی داره. برای این که این اتفاق نیفته از USER استفاده می‌کنیم: FROM python:3.7
ENV PYTHONUNBUFFERED 1 
RUN mkdir /code 
WORKDIR /code 
COPY requirements.txt /code/ 
RUN pip install -r requirements.txt 
COPY . /code/ 
RUN useradd nonroot 
USER nonroot
ENTRYPOINT [&amp;quot/bin/bash&amp;quot, &amp;quotstart.sh&amp;quot]خط یکی مونده به آخر ازش استفاده کردم. جلوی USER نام کاربر رو می‌ذاریم. قبلش یادتون باشه باید کاربر تو سیستم ساخته بشه. خط قبلیش من useradd رو اجرا کردم. میشه بعد از نام دو نقطه بذاریم و گروهش رو هم مشخص کنیم. گروه هم باید قبلش ساخته بشه. هر چی دستور بعد از اون اجرا بشه رو این کاربر انجام میده. اگر توی شل کانتینر ساخته شده از این ایمیج هم بریم باز همون کاربر هستیم و نه root: تو تصویر بالا (به شل کانتینری که از داکرفایل قبلی ساخته شده رفتم) که به خروجی دستور id نشون میده نام کاربری من nonroot هست و گروهم هم nonroot. چرا گروه nonroot وجود داره؟ من که نساخته بودمش. به این فکر کنید و اگر جواب رو پیدا کردید تو نظرات بگید.جمع بندیدر این مطلب با یک سری دیگه از best practiceها برای برنامه‌نویس‌ها در دنیای کانتینرها و داکر آشنا شدیم. اگر نکات دیگه‌ای هم سراغ دارید معرفی کنید تا همه استفاده کنیم. اگر هم سوال یا نظری دارید این پایین بفرمایید.قسمت قبلیقسمت بعدی</description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Sun, 21 Mar 2021 14:43:58 +0330</pubDate>
            </item>
                    <item>
                <title>گیتلب و CI/CD: یک راهنمای ساده - قسمت اول</title>
                <link>https://virgool.io/CodeLovers/gitlab-ci-1-mlwvikni0bva</link>
                <description>مقدمهبرای این که یک برنامه رو دیپلوی کنیم و به کاربران عرضه کنیم فقط نوشتن کدهای برنامه کافی نیست و لازمه استراتژی مناسبی برای این که چجوری و در چه زمان‌هایی دیپلوی کنیم هم داشته‌ باشیم. یکی از روش‌های مرسوم CI/CD هست که در این مطلب قصد داریم به اهمیت اون و معرفی Gitlab CI بپردازیم. قصدم بر اینه که طی چند نوشته با مفاهیم ابتدایی تا نسبتا پیشرفته در Gitlab CI آشنا بشیم و کار کنیم. در این نوشته لازمه که با دستورات در شل لینوکس آشنایی داشته باشید. هم‌چنین داشتن اطلاعات در مورد کانتینرها و داکر هم مفیده.  مفهوم و ابزارهای CI/CDاین عبارت مخفف Continuous Integration Continuous Delivery یا Deployment هست. همون طور که مشخصه از دو بخش تشکیل میشه؛ بخش اول مربوط به تست و بیلد برنامه‌ها و بخش دوم مربوط به دیپلوی کردن هست. یک عبارت مهم هم در جفتشون هست که به استمرار زمانی اشاره داره. ما در این روش به کمک ابزارهایی به طور پیوسته کدهامون رو بیلد، تست و دیپلوی می‌کنیم.گفتیم ابزارهایی برای این کار لازمه. ابزاری که همیشه استفاده میشه گیت هست. در اصل این پیوستگی با استفاده از پوش کردن در یک سرور گیت رخ میده.‌ با انجام تنظیماتی می‌تونیم بگیم هر وقت به برنچ خاصی پوش شد اون کد رو بیلد، تست و دیپلوی کن. کنار گیت یک سری ابزار دیگه هم باید باشن که یک pipeline رو برای ما تشکیل بدن تا این پیوستگی رو داشته باشیم. خیلی دوست داریم که هر چه بیشتر این ابزارهای لازم توی خود گیت سرور باشن تا ما دردسرهای کمتری داشته باشیم. خبر خوب اینه که چنین چیزی وجود داره و اون هم گیتلب (Gitlab) هست. گیتلب یک گیت سرور هست که هم سایتش به آدرس gitlab.com موجوده و به شکل open source در اختیار ما قرار داره و می‌تونیم ازش به عنوان گیت سروری که مجموعه‌ی ابزارهای CI/CD رو داره استفاده کنیم.گیتلب و CI/CDفارغ از این که از gitlab.com استفاده کنیم یا خودمون بالا بیاریمش، یک سری عبارت هستن که ازش استفاده می‌کنیم. تو این قسمت می‌خوایم به اونا بپردازیم.برای این که برای یک repo در گیتلب CI/CD داشته باشیم یک فایل به نام gitlab-ci.yml. داخل پوشه اصلی پروژه می‌ذاریم. داخل این فایل کارهایی که برای CI/CD لازمه رو می‌نویسیم که در ادامه به اون هم می‌رسیم.وقتی ما می‌خوایم عملیات بیلد، تست و دیپلوی رو انجام بدیم ابزاری باید باشه که این‌ها رو اجرا کنه. این ابزار یک نرم‌افزار هست که می‌تونه کارهایی که تو gitlab-ci.yml. نوشته شده رو انجام بده. به این‌ نرم‌افزار گیتلب رانر (gitlab runner) میگیم. سایت گیتلب رانرهایی داره که میشه از اون‌ها استفاده کرد. خودمون هم می‌تونیم رانر بالا بیاریم و به گیتلب معرفی کنیم تا pipeline توسط اون انجام بشه. به رانری که همه‌ی پروژه‌های موجود در یک instance گیتلب می‌تونن روش pipeline اجرا کنن میگیم shared runner. منظورم از instance همون گیتلب هست که جایی بالا اومده. حالا می‌تونه همون gitlab.com باشه یا روی سرور خودمون.حالا گیتلب رانر رو کجا بالا بیاریم؟ هر محیطی که بشه توش گیتلب رانر رو اجرا کرد می‌تونه باشه. مثلا لینوکس روی ماشین مجازی یا یه کانتینر.گیتلب رانر رو یه جایی اجرا کردم. دستورهایی که بهش میدم رو چجوری و کجا اجرا می‌کنه؟ به اون میگیم executor. مثلا ممکنه بخوام داخل shell این کارو کنه برام. یا مثلا داخل کانتینر. این رو موقعی که به گیتلب معرفیش می‌کنم باید تعیین کنم.برای این آموزش از دارکوب استفاده می‌کنم که یکی از سرویس‌های شرکت هم‌روش هست و به ما کمک می‌کنه برنامه‌های خودمون رو به راحتی دیپلوی کنیم. دارکوب pipeline رو داخل کانتینر داکر و به کمک کوبرنتیز اجرا می‌کنه. برای گیت هم از هم‌گیت استفاده می‌کنم که سرویس گیتلب هم‌روش هست و به شکل رایگان در دسترسه.ثبت رانر در هم‌گیتبرای ثبت یک رانر در گیتلب باید به Settings -&gt; CI/CD و بعد به بخش Runners بریم و رانر رو ثبت کنیم. در این بحث نمیخوام راجع به رانرها زیاد صحبت کنم به همین دلیل از رانر هم‌گیت استفاده می‌کنم. در هم‌گیت لازم نیست رانر رو ثبت کنیم؛ چون خودش ثبت می‌کنه. فقط باید به همونجا بریم و دکمه &quot;Enable shared runners&quot; رو بزنیم که دکمه سبز رنگ در تصویر زیر است:سورس کد خودمون رو که به هم‌گیت پوش کردیم به سراغ دارکوب میریم. اول یک اپ جدید می‌سازیم:&quot;منبع گیت&quot; رو انتخاب می‌کنیم. با این کار ما به دارکوب میگیم که کد ما رو از رو هم‌گیت بخونه. با زدن &quot;انتخاب ریپو&quot; بهش آدرس پروژه رو میدیم:بقیه مراحل هم طی می‌کنیم تا اپ تکمیل بشه. بعد از این هر وقت به برنچ master پوش کنیم یک فرایندی رو خود دارکوب با darkube-cli انجام میده که یک ایمیج می‌سازه و اون رو دیپلوی می‌کنه. اما اگر بخوایم خودمون این فرایند رو با گیتلب CI انجام بدیم لازم هست یه کاری کنیم. دارکوب برای این که بیلد و دیپلوی رو انجام بده میاد یک webhook برای پروژه‌ی ما تنظیم می‌کنه. به قسمت Settings -&gt; Webhooks در پروژه‌تون برید. پایین صفحه یه دونه webhook در بخش Project webhooks می‌بینید:جلوش delete رو بزنید تا دیگه دارکوب خودش برنامه رو بیلد و دیپلوی نکنه و ما خودمون این فرایند رو به دست بگیریم.اجرای یک pipeline سادهبرای این که بتونیم با نوشتن gitlab-ci.yml. آشنا بشیم به سبک زبان‌های برنامه‌نویسی یه hello world انجام میدیم. یعنی فقط یک متن ساده رو چاپ می‌کنه برامون.‌ یک سری مفاهیم هستن که خوبه قبل از نوشتن بدونیم.اولیش stage هست. می‌تونیم مرحله ترجمه‌اش کنیم. در هر stage تعدادی کار انجام میشه که به اون‌ها job میگیم. هر stage یک هدفی رو دنبال می‌کنه؛ مثلا یک stage برای بیلد قرار میدیم. می‌تونیم چندین کار مختلف تعریف کنیم تا به این هدف برسیم. stage‌ها به همون ترتیبی که ما تعیین کردیم اجرا میشن. به طور پیش فرض سه تا stage در گیتلب داریم که به ترتیب deploy, test, build هستن.‌همون طور که گفته شد یک stage از تعدادی job تشکیل شده و کارهایی هست که ما به گیتلب رانر میگیم انجام بده. مثلا در یک job من برنامه رو کامپایل می‌کنم و از روش ایمیج جدید می‌سازم. توجه کنید که jobهای یک stage همزمان اجرا میشن. اگر یک job دچار مشکل بشه دیگه stageهای بعدی اجرا نمیشن ولی jobهای همون stage اجرا میشن.حالا که این مفاهیم رو به شکل نظری دیدیم بیاید یک gitlab-ci.yml. ساده بنویسیم. ابتدا یک job می‌نویسیم و  یک اسم برای job انتخاب می‌کنیم:اسمی که انتخاب کردم hello-world است. جلوی اسم دو نقطه می‌ذارم و به توصیف اون می‌پردازم. یک بخش خیلی مهم در هر job دستوراتی هست که قراره اجرا بشه. اون رو با script مشخص می‌کنیم:بعد از script یک لیست از دستورات نوشته میشه که به ترتیب اجرا میشن. من این‌جا یک دستور فقط دارم که hello world from Hamravesh رو چاپ می‌کنه. برای تمرین اسم خودتون رو به جای Hamravesh بذارید! دقت کنید این یک لیسته و با - اجزای مختلفش مشخص میشه. بعدش stage هست که میگه این job در چه stageی هست:اگر این رو نذاریم stage رو test در نظر می‌گیره. البته چون ما فقط یک job داریم stage اهمیتی نداره. ولی حالا گذاشتم. شما هم بذارید! در اینجا image هم لازم هست که همیشه لازم نمیشه و به محیطی که executor داره بستگی داره. در مورد دارکوب به این احتیاج داریم چون از داکر استفاده می‌کنه (اگر ندیم خودش ایمیج پیشفرض رو اجرا می‌کنه که ubuntu:16.04 هست):ایمیج انتخابی من ubuntu:20.04 هست. من این فایل رو دستی در هم‌گیت ایجاد کردم و خودش یک commit درست کرد. بعدش هم شروع به اجرای فرایند CI/CD می‌کنه و علامتش رو میشه کنار commit hash دید:اگر در حال اجرا باشه علامت آبی رنگ میده. اگر خطا داشته باشه قرمز. اگر موفق باشه سبز و اگر منتظر اجرا شدن باشه نارنجی رنگ میشه. روش کلیک می‌کنم و به این صفحه میرم:می‌تونستم از پنل روی CI/CD -&gt; Pipelines بزنم و بعد به pipeline دلخواه برم و به همین صفحه می‌رسم. تو این صفحه stageها و jobهای هر مرحله رو می‌بینم. من فقط یه stage و یه job داشتم. حالا روی اون job کلیک می‌کنم تا لاگ‌هاش رو ببینم:و به این شکل این اولین pipeline رو به زیبایی اجرا کردیم. جمع بندیدر این قسمت با CI/CD و Gitlab CI آشنا شدیم. بعدش مفاهیم ابتدایی در Gitlab CI رو دیدیم. در بخش آخر هم یک pipeline ساده رو اجرا کردیم. امیدوارم این مطلب براتون مفید بوده باشه. اگر سوال یا نظری دارید این پایین بنویسید.</description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Wed, 17 Mar 2021 10:52:38 +0330</pubDate>
            </item>
                    <item>
                <title>داکر برای برنامه‌نویس‌ها: قسمت دهم - best practices</title>
                <link>https://virgool.io/paasino/best-practices-1-c5rrtqpiomzq</link>
                <description>مقدمهقسمت قبل یک برنامه جنگو رو داکرایز کردیم. اما برای یک برنامه‌نویس کافی نیست که فقط ایمیج بسازه. بلکه باید یک سری نکات رو رعایت کنه تا به استانداردهای لازم برسه. طی دوقسمت قراره به برخی از این نکات بپردازیم و دلیلش رو هم ببینیم. به این نکات میگن best practice. قطعا برای برنامه‌نویس‌ها این مطالب به درد می‌خورن. مهندسین دواپس هم این مطالب رو مفید خواهند یافت.برای ارتباط بهتر با این نوشته باید با کانتینرها، داکر و نحوه‌ی داکرایز کردن یک برنامه آشنایی داشته باشین. داشتن پیش‌زمینه در برنامه‌نویسی هم لازمه.ساختار ایمیج و چگونگی بیلد آنابتدا بیاید ساختار یک ایمیج رو بررسی کنیم. ایمیج‌ها یک سری لایه read only هستند و وقتی ما در داکرفایل برخی کارها رو می‌کنیم یک لایه جدید ساخته میشه. مثلا داکرفایل قسمت قبل رو ببینید: 
FROM python:3.7 
ENV PYTHONUNBUFFERED 1 
RUN mkdir /code 
WORKDIR /code 
COPY requirements.txt /code/ 
RUN pip install -r requirements.txt 
COPY . /code/ 
ENTRYPOINT [&amp;quot/bin/bash&amp;quot, &amp;quotstart.sh&amp;quot]بعضی دستورها هستن که فایل سیستم رو تغییر میدن. مثلا وقتی COPY رو استفاده می‌کنم یه فایل از سیستم من می‌فرسته به ایمیج. در نتیجه فایل سیستم ایمیج تغییر می‌کنه. زمانی که چنین دستورهایی رو اجرا می‌کنیم داکر یک لایه جدید ایجاد می‌کنه. فایده‌‌ی این لایه لایه بودن چیه؟ در بخش بعد می‌بینیم.استفاده از قابلیت بیلد کش (build cache)طبق صحبتی که بخش قبل کردیم، با اجرای بعضی دستورها لایه‌هایی به ایمیج اضافه میشن. خوبی استفاده از لایه‌ها اینه که می‌تونیم از قابلیت کش استفاده کنیم. یعنی وقتی یک لایه قبلا ساخته شده و تغییری هم قرار نیست بکنه دوباره ساخته نمیشه و سریع میره مرحله بعد. دو تا از دستورهایی که فایل رو از سیستم میزبان به ایمیج منتقل می‌کنن COPY و ADD هستن. COPY رو قبلا دیدیم؛ فایل رو کپی می‌کنه. ADD هم همین کار رو انجام میده با این تفاوت که می‌تونیم علاوه بر مسیر داخل سیستم میزبان بهش یک url بدیم تا اون رو دانلود کنه و بذاره داخل ایمیج. وقتی این دو تا دستور می‌خواد اجرا شه داکر میاد روی لایه فعلی تغییرات رو ایجاد کنه. تمامی لایه‌هایی که تو سیستم هستن و از روی لایه فعلی ساخته شدن توسط داکر بررسی میشن. به این لایه‌ها میگیم لایه‌های فرزند برای لایه‌ی فعلی.  بررسی لایه‌های فرزند در داکر برای استفاده از cacheداخل این لایه‌های فرزند چی رو بررسی می‌کنه؟ فایل‌هایی که در ایمیج هست رو نگاه می‌کنه. اگه تمام فایل‌ها در یک لایه فرزند وجود داشته باشن و تغییری نکرده باشن از همون لایه استفاده می‌کنه و لایه‌ی جدید نمی‌سازه. مثلا به داکرفایلی که بالا گذاشتم دوباره نگاه کنید. به جایی که می‌خوام requirements.txt رو کپی کنم توجه کنید. دارم یه دونه فایل به ایمیج کپی می‌کنم. دستور قبلیش هم ببینید. داکر به همه لایه‌هایی که بعد از دستور قبلی وجود دارن نگاه می‌کنه و توی اون‌ها فایل‌ها رو با فایل‌های لایه فعلی مقایسه می‌کنه. البته در مورد requirements.txt محتوای فایلی که داره کپی میشه رو می‌بینه. اگه یکیشون دقیقا همین محتویات رو داشته باشه، از همون استفاده می‌کنه و لایه جدیدی نمی‌سازه. به این شکل سرعت بیلد بالاتر میره (داخل پرانتز بگم که این مقایسه رو با هش کردن انجام میده و نمیاد دونه دونه اطلاعات داخل فایل رو ببینه).یک دستور دیگه هم هست که برای کش کردن مهمه و در ارتباط با دو دستور بالا خیلی بهتر میشه. اون دستور RUN هستش. RUN موقع ساخت ایمیج دستوری رو داخلش اجرا می‌کنه. مثلا من در داکرفایل بالا pip install زدم. برای این دستور دیگه نمیاد تمام فایل‌های توی فایل سیستم رو بررسی کنه. بلکه فقط به دستوری که جلوش نوشته شده نگاه می‌کنه. مثل بند قبل میاد تمام فرزندان لایه قبلی رو نگاه می‌کنه و اگه بینشون لایه‌ای با همین دستور ساخته شده باشه از اون استفاده می‌کنه. حالا می‌تونیم ترکیب این با بند قبل رو داشته باشیم؛ تو داکرفایل وقتی کپی می‌کنم اغلب اوقات از کش استفاده میشه چون requirements.txt خیلی کم تغییر می‌کنه. در نتیجه RUN هم از کش استفاده می‌کنه چون لایه قبلیش تغییر نکرده و دستور جلوی RUN هم ثابته. اما اگر تمام سورس کد رو اول کپی می‌کردم (چون سورس کد دائما در حال تغییره) اون وقت برای COPY هر دفعه یک لایه جدید ساخته میشه و برای RUN هم دیگه کشی وجود نخواهد داشت چون لایه قبلیش جدیده. پس هر دفعه تمام اون پکیج‌های پایتون رو نصب می‌کنه که خیلی کار رو کند می‌کنه.ساخت ایمیج‌ برای همه جاوقتی یک ایمیج رو می‌سازیم باید دقت داشته باشیم که ممکنه به هر جایی بره و باید بیشترین انعطاف ممکن رو داشته باشه. منظورم اینه که نباید رفتار کدی که می‌نویسیم به شکل  hard code شده داخلش قرار گرفته باشه و باید با خوندن یک فایل یا متغیر محیطی رفتارش تعیین بشه. برای مثال فرض کنید من یک برنامه نوشتم که قراره به برنامه‌ی یک همکار دیگه از طریق شبکه متصل بشه و بهش درخواست HTTP بده.  این اصلا خوب نیست که آدرس، پورت و حتی HTTP یا HTTPS بودن این درخواست در برنامه‌ی من hard code بشه؛ چون در آینده شاید همه‌ی این‌ها تغییر کنه یا به محیط جدیدی بریم که نیازمند تغییر این مقادیر باشیم. در عوض مثلا این‌ها باید در یک متغیر محیطی گذاشته و متناسب با جایی که ایمیج در اون دیپلوی میشه تعیین بشن.ایمیج‌های statelessیکی از مهم‌ترین نکاتی که باید رعایت کنیم و از ویژگی‌های یک برنامه‌ی ۱۲ فاکتور این هست که ایمیج‌های ما داخل خودشون چیزی رو ذخیره نکنن. وظیفه‌ی نگهداری اطلاعات رو باید به ابزارهای خاصی که به این منظور نوشته شدن بسپاریم. به چنین سرویسی stateless میگیم چون هیچ state یا حالتی رو در خودش نگه نمی‌داره. مثلا برای نگهداری اطلاعات کاربران اون‌ها رو به دیتابیس MySQL بفرستیم که با ایمیج mysql اجرا شده. چنین ایمیجی وقتی اجرا بشه به راحتی می‌تونه scale بشه. اطلاعاتی ام که داخل ram یا فایل سیستم خود کانتینر قرار می‌گیرن برای cache استفاده میشن و نه برای ذخیره‌ی حالت سیستم.جمع بندیدر این مطلب تعدادی از best practiceها یا نکات مهم در نوشتن برنامه و داکرفایل رو مرور کردیم. این موارد به ما کمک می‌کنن نرم‌افزارمون به شکل مناسب بیلد و دیپلوی بشه. امیدوارم این مطلب براتون مفید بوده باشه. در صورتی که سوال یا نظری دارید این پایین بفرمایید.قسمت قبلیقسمت بعدی</description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Fri, 19 Feb 2021 12:05:28 +0330</pubDate>
            </item>
                    <item>
                <title>داکر برای برنامه‌نویس‌ها: قسمت نهم - جنگو در داکرفایل</title>
                <link>https://virgool.io/paasino/django-dockerfile-ds5hqqfn8yel</link>
                <description>مقدمهقسمت قبلی یک داکرفایل ساده نوشتیم و از روش ایمیج درست کردیم. این دفعه قراره یک برنامه پایتون که با فریم‌ورک جنگو نوشته شده رو داکرایز و اجرا کنیم. این مطلب برای برنامه‌نویس‌هایی که می‌خوان برنامه‌هاشون رو در داکر اجرا کنن مفید خواهد بود.برای دنبال کردن مطالب این قسمت باید با داکر و اجرا کردن کانتینر در اون آشنا باشید. هم‌چنین خوبه که آشنایی ابتدایی با نوشتن داکرفایل و دستورات خط فرمان لینوکس داشته باشید.معرفی برنامهمن یک برنامه با جنگو نوشتم که می‌تونید اون رو تو این لینک گیتهاب ببینید و اگه خواستید کلون کنید. به برنچ simple-app برید. البته در زمان نوشتن این متن master با simple-app فرقی ندارن ولی در آینده تغییر می‌کنن. داکرفایلش رو هم همونجا می‌بینید که می‌خوایم در موردش صحبت کنیم. این برنامه وقتی اجرا بشه به درخواست‌های http ما جواب میده. چند تا جدول داره داخل دیتابیس که برای نویسنده و بلاگ هست. یک سری پارامتر هم داره که موقع اجرای برنامه از متغیرهای محیطی می‌خونه. از جمله اطلاعات ادمین. داخل فایل start.sh دستوراتی هست که برنامه رو اجرا می‌کنه و روی پورت ۸۰۰۰ گوش میده.نوشتن داکرفایلFROM python:3.7
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code/
ENTRYPOINT [&amp;quot/bin/bash&amp;quot, &amp;quotstart.sh&amp;quot]اولش که قرار شد اسم ایمیج پایه رو بنویسیم. من از python:3.7 استفاده کردم. بعدش با ENV مقدار یک متغیر محیطی به نام PYTHONUNBUFFERED رو 1 گذاشتم که وقتی کانتینر اجرا شد لاگ‌ها رو بافر نکنه و تو خروجی استاندارد بنویسه. می‌تونستم موقع اجرا هم این متغیر رو بدم ولی چون می‌خوام تو همه‌ی کانتینرها باشه اینجا نوشتم. می‌خوام کدهای برنامه رو در مسیر code/ کپی کنم. اول این پوشه رو با RUN می‌سازم. با RUN یک دستور رو هنگام بیلد ایمیج داخل اون اجرا می‌کنیم. کلمه WORKDIR رو دیده بودیم. پوشه در مسیر code/ رو در نظر گرفتم تا از این به بعد اونجا باشیم.بعدش در دو مرحله فایل‌ها رو کپی می‌کنیم. دلیلش رو ان شاء الله قسمت بعد می‌بینیم. دستور COPY رو دیده بودیم قبلا. اول فایلی که requirement های برنامه رو داره منتقل می‌کنم و از روی اون با کمک RUN ماژول‌های لازم نصب میشه. دستوری که اجرا کردم pip هست و برای نصب پکیج‌های پایتون استفاده میشه. وقتی docker build رو اجرا کنم پکیج‌های لازم روی ایمیج نصب شده و هر جا که از روی اون کانتینری رو اجرا کنم این پکیج‌ها رو خواهم داشت. در بخش دوم سورس کد رو منتقل می‌کنم به پوشه اصلی. الان دیگه همه چیز رفته داخل ایمیج.آخرین کاری که انجام میدم اینه که اسکریپت start.sh رو اجرا کنم. با استفاده از ENTRYPOINT این کار رو تو بش انجام میدم. جلوش داخل یک آرایه دستور رو میدم. هر جا قرار باشه فاصله بذارم یا یه آپشن جدید از دستور رو بنویسم یه عنصر جدید به آرایه اضافه می‌کنم. ترتیب هم طبییعتا مهمه. حالا داکرفایل آماده است. بریم که بیلد و اجراش کنیم.بیلد ایمیج و اجرای کانتینربا دستور docker build داخل پوشه‌ای که داکرفایل هست بیلد رو شروع می‌کنم: با t- نام و تگ ایمیج رو میدم و بعد نقطه گذاشتم که یعنی پوشه اصلی همینجاست. دقت کنید فرایند بیلد مرحله به مرحله است و هر مرحله روی بعدی میاد. این نکته‌ی مهمی هست که ایشالا بعدا بهش می‌پردازیم. خب الان از روی ایمیج کانتینر می‌سازم (پورت رو یادتون نره): و با کمک curl بهش درخواست REST میدم (درخواست‌های نمونه رو در فایل curl.sh می‌تونید ببینید): هورااا...می‌بینم که کارم درست شده و کانتینر کار میکنه. با این درخواست یک کاربر جدید ثبت‌نام کردم و توکن گرفتم. دقت کنید مقدار متغیر PORT رو همون مقداری بذارید که موقع اجرای کانتینر پابلیش کردید.  جمع بندیدر این قسمت یک برنامه پایتون که با فریم‌ورک جنگو نوشته شده رو داکرایز کردیم، از روش ایمیج ساختیم و اجراش کردیم. در نهایت برای اطمینان از عملکردش یک درخواست دادیم و جواب گرفتیم. امیدوارم این نوشته براتون مفید بوده باشه. اگر نظر یا سوالی دارید این پایین بفرمایید.قسمت قبلیقسمت بعدی</description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Sun, 31 Jan 2021 10:59:59 +0330</pubDate>
            </item>
                    <item>
                <title>داکر برای برنامه‌نویس‌ها: قسمت هشتم - بیلد کردن ایمیج با داکرفایل</title>
                <link>https://virgool.io/paasino/dockerfile-ivcreo31l1qd</link>
                <description>مقدمهبعد از این که با ایمیج‌های بقیه کار کردیم حالا می‌خوایم خودمون ایمیج بسازیم. وقتی برنامه‌ای رو می‌نویسیم اون رو تبدیل به یک ایمیج می‌کنیم تا ازش به شکل یه کانتینر استفاده کنیم. امروزم قصد داریم این رو یاد بگیریم. این مطلب برای یک برنامه‌نویس که می‌خواد برنامه‌اش رو داکرایز کنه خیلی مفید میتونه باشه. برای سیستم ادمین‌ها هم خوندنش ضرر نداره. برای این مطلب آشنایی با داکر و کانتینرها لازمه. هم‌چنین دونستن دستورات بش کمک میکنه. برای مطالعه در مورد داکر می‌تونید به قسمت‌های قبلی مراجعه کنید. برای بش در لینوکس هم به این دنباله می‌تونید برید. معرفی داکرفایلبرای این که بتونیم از روی ایمیج‌های دیگه ایمیج بسازیم باید یک فایل با نام Dockerfile بنویسیم. هیچ پسوندی نداره. حرف اولش هم بزرگه. این فایل رو داخل پوشه اصلی برنامه می‌ذاریم. اینجا یک فایل ساده‌ی بش دارم و می‌خوام به شکل کانتینری اجراش کنم. از عمد یک مثال ساده در نظر گرفتم تا فقط روی مفاهیم تمرکز کنیم. ان شاء الله قسمت‌های بعد فریم‌ورک‌ها و زبان‌های مختلف رو خواهیم دید. محتوای فایل بش این شکلیه:کار خاصی نمی‌کنه؛ هر ۲ ثانیه یه بار جمله‌ای رو چاپ می‌کنه. حالا تو همین پوشه داکرفایل رو درست می‌کنم. ویرایشگر من vscode هست و با ایجاد کردن داکر فایل لوگوی داکر رو نشون میده:احتمالا در ویرایشگرهای دیگه هم همین طوره.نوشتن داکرفایلخب دیگه وقتشه شروع به نوشتن کنیم. داخل داکرفایل یک سری کلمات خاص وجود دارن که با حروف بزرگ نوشته میشن. به تدریج باهاشون آشنا میشیم. اولین کاری که می‌کنیم اینه که بگیم از روی کدوم ایمیج می‌خوایم ایمیج جدید رو بسازیم و بهش ایمیج والد یا اصلی یا parent image میگیم. من از ubuntu استفاده کردم. برای این کار از FROM استفاده می‌کنم و جلوش اسم ایمیج رو می‌نویسم: FROM ubuntuاول داکرفایل همیشه FROM رو داریم تا مشخص بشه روی چه ایمیجی کار می‌کنیم. حالا فایل‌هایی که می‌خوایم رو به ایمیج اصلی منتقل می‌کنیم. اول مشخص می‌کنیم که تو کدوم پوشه از ایمیج هستیم.‌ این رو با WORKDIR نشون میدم: WORKDIR /rootبعدش فایل(های) مورد نظرم رو کپی می‌کنم: COPY ./script.sh ./دستور COPY دو تا آرگومان داره؛ اولیش فایل یا پوشه مبدا که در سیستم اصلی هست رو میگه و دومی پوشه مقصد که داخل ایمیج هست. تو آرگومان اول نقطه به معنای پوشه‌ای هست که داکرفایل توشه و تو آرگومان دوم نقطه پوشه‌ای هست که با WORKDIR تعیین گردیم.آخرین کاری که می‌کنم دادن دستوری برای اجرا هست. یعنی موقعی که یه کانتینر از روی این ایمیج اجرا شد چی کار کنه. در این مورد می‌خوام اسکریپت من اجرا بشه: ENTRYPOINT [ &amp;quot/bin/bash&amp;quot, &amp;quot./script.sh&amp;quot ]کلمه ENTRYPOINT رو نوشتم و بعدش دستوری که قراره اجرا شه. دقت کنید که دستور به شکل آرایه باید داده بشه و هر قسمت از دستور یک عنصری از آرایه هست. تمام اعضای لیست هم باید به شکل string باشن.بیلد کردن ایمیج و اجرای کانتینرحالا که یه داکرفایل ابتدایی نوشتم می‌خوام از روش ایمیج بسازم. به این کار build میگیم. با استفاده از دستور docker build در پوشه‌ای که داکرفایل دارم این کارو انجام میدم:جلوش t- گذاشتم تا اسم ایمیج جدید رو بدم. در ضمن بعد از : تگ مناسب هم گذاشتم. یک برنامه که می‌نویسیم اسم ایمیج یکسانی داره ولی با دادن نسخه‌های مختلف تگش تغییر می‌کنه. در آخر نقطه گذاشتم به این معنا که پوشه اصلی همینجاست.الان این ایمیج رو در لیست ایمیج‌ها می‌بینم:و بعد از ساخت کانتینر از روش: همون چیزی که می‌خواستم شد و خوشحالم :)جمع بندیدر این مطلب با داکرفایل و نحوه نوشتنش آشنا شدیم. بعدش ایمیج‌مون رو با docker build ساختیم و یه کانتینر درست کردیم. امیدوارم براتون مفید بوده باشه. اگر نظر یا سوالی دارید این پایین بفرمایید.قسمت قبلی</description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Mon, 18 Jan 2021 21:51:29 +0330</pubDate>
            </item>
                    <item>
                <title>داکر برای برنامه‌نویس‌ها: قسمت هفتم - دستورات متفرقه ولی مفید!</title>
                <link>https://virgool.io/paasino/docker-miscellaneous-hoblkeojgupj</link>
                <description>مقدمه در این قسمت چند تا دستور رو می‌بینیم که تو هیچ دسته‌ی خاصی نذاشتمشون. این دستورها به بررسی کانتینر، رجیستری داکر و انتقال تصویر به یک ماشین دیگه مربوط میشن. آخرشم یه کار باحال انجام میدیم!دونستن این موارد میتونه به سیس‌ ادمین‌ها و برنامه‌نویس‌هایی که با داکر کار دارن کمک کنه.پیش نیاز این بحث نصب داشتن داکر روی سیستم هست و باید کار با کانتینرها در داکر رو تجربه کرده باشید. برای این موارد در صورت نیاز می‌تونید قسمت‌های قبلی رو ببینید.دیدن لاگ کانتینرمعمولا برنامه‌هایی که می‌نویسیم لاگ‌هایی تولید می‌کنن. اگر این لاگ‌ها در stdout یا stderr نوشته بشن میشه با دستور docker logs اون‌ها رو دید: بعد از logs آیدی کانتینر رو نوشتم. اگر لاگ برنامه‌ی داخل کانتینر تو یه فایل نوشته بشه باید خود فایل رو خوند. مثلا با docker exec که تو این قسمت دیدیم بریم تو کانتینر و فایل رو ببینم یا با docker cp که در قسمت قبل داشتیم اون رو به سیستم خودمون کپی کنیم.استفاده از inspectبا دستور docker inspect می‌تونیم هر اطلاعاتی که مربوط به کانتینر هست رو ببینیم: بعد از inspect آیدی کانتینر رو نوشتم. فرمت خروجی به شکل json هست. خیلی هم طولانیه. جابجایی تصویر داکرگاهی پیش میاد که یک تصویر رو توی یه سیستم پول کردید و می‌خواید تو یه سیستم دیگه هم اون رو داشته باشید. اگه نخواید دوباره حجم اینترنت مصرف کنید یا اصلا سیستم دوم به اینترنت دسترسی نداشته باشه می‌تونید از docker save استفاده کنید:جلوی save اسم تصویر میاد. به طور پیشفرض خروجی در stdout نوشته میشه. اما اینجا من redirect کردم به یه فایل. extension اون فایل رو tar. گذاشتم چون داکر خروجی رو به شکل آرشیو شده میده (البته می‌دونیم تو لینوکس extension مهم نیست و این کار برای خودمونه). با آپشن o- هم میشد این کارو کرد. کافیه اسم فایل رو جلوش بدید. خب حالا این فایل رو میشه به هر شکلی که دلمون میخواد بفرستیم به یه سیستم دیگه. مثلا با scp. من ادامه مراحل رو تو همون سیستم قبلی ادامه میدم ولی از اینجا به بعد باید تو سیستم مقصد اجرا شه. قبل از این کار تصویر رو حذف می‌کنم تا شبیه سیستم مقصد بشه:دیگه اون تصویر رو ندارم. اما با docker load اون فایل رو لود می‌کنم:با i- بهش گفتم از کدوم فایل بخونه. حالا دوباره تصویر رو دارم و این کار رو با load انجام دادم.لاگین کردن در داکر رجیستریاخیرا داکر یه محدودیتی در پول کردن تصاویر از رجیستری خودش گذاشته. برای من پیش اومده که اشتباها بهم میگه محدودیت رو رد کردم. احتمالا یکی دیگه با ip من این کارو کرده یا به هر دلیل داکر اشتباه کرده. برای نخوردن به این مشکل میشه یه حساب ساخت و در اون لاگین کرد تا ما رو با اسم بشناسه. وقتی لاگین کنیم دو برابر حالت قبل می‌تونیم پول کنیم. یه موقعی هم هست که رجیستری خصوصی داریم و برای استفاده ازش لازمه لاگین کنیم. برای لاگین از دستور (اگه گفتید؟!) login استفاده میشه (درست گفتید!): اگه به جایی غیر از داکرهاب لاگین می‌کنید آدرسش رو بعد از login بنویسید. از شما نام کاربری و رمز عبورتون رو می‌پرسه و اگر درست باشه می‌نویسه Login Succeeded. چون من قبلا این کارو کرده بودم دیگه از من چیزی نخواست. از این به بعد شما کاربر شناخته شده‌ای برای این رجیستری هستید. اگر در داکرهاب حسابی ندارید برای ساخت حساب به سایت داکر برید.یه کار باحال خب حالا که تا اینجا اومدین بذارین یه چیز باحال ببینیم. برای دیدن تمام کانتینرها از docker ps -a استفاده می‌کردیم. با q- میشه کاری کرد که فقط آیدی کانتینرها رو نشون بده:این به چه دردی می‌خوره؟ به این درد که همه کانتینرها رو با هم حذف کنیم:از back tick استفاده کردم و خروجی دستور قبلی رو گذاشتم جلوی docker rm. این طوری تک تک اون‌ها رو پاک می‌کنه. وقتی تعداد زیادی کانتینر دارید که در حال اجرا نیستن با این کار همه‌شون پاک میشن.به روز رسانی: یک نکته خوبی رو فرهاد در نظرات گفت و اون هم دستور prune هست. با prune میشه هر کانتینری که stop شده رو حذف کرد:اول از شما می‌پرسه مطمئن هستید؟ بعد شما y رو وارد می‌کنید و اونم حذف می‌کنه. با تشکر از فرهاد. جمع بندیدر این مطلب چند مبحث رو بررسی کردیم. اول لاگ کانتینر و اطلاعات اون رو دیدیم. بعد تصویر رو بین سیستم‌ها جابجا کردیم. بعد لاگین کردن رو تجربه کردیم. آخر سر هم همه کانتینرها رو با یه دستور پاک کردیم. امیدوارم براتون مفید بوده باشه. اگر نظر یا سوالی دارید این پایین بفرمایید.قسمت قبلیقسمت بعدی</description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Sun, 27 Dec 2020 08:15:31 +0330</pubDate>
            </item>
                    <item>
                <title>داکر برای برنامه‌نویس‌ها: قسمت ششم - اشتراک و جابجایی فایل در کانتینر</title>
                <link>https://virgool.io/paasino/docker-mount-copy-ijmhcw9vtgg7</link>
                <description>مقدمهدر این قسمت می‌خوایم فایل‌ها رو به کانتینر انتقال بدیم یا از اون فایلی رو به فایل سیستم خودمون بیاریم. هم‌چنین فایل‌ها رو بین کانتینرها به اشتراک میذاریم. برنامه‌نویس‌ها و سیس ادمین‌هایی که با محیط‌های کانتینری کار دارن میتونن از این مطلب استفاده کنن. فرض بر این هست که شما نرم‌افزار داکر رو در سیستم خودتون نصب کردید و اجرای کانتینرها در داکر رو بلد هستید. هم چنین این که چطوری داخل یه کانتینر به شل دسترسی پیدا کنیم هم باید بدونید. می‌تونید قسمت‌های قبلی این دنباله رو ببینید. علاوه بر این باید با مفاهیم فایل سیستم لینوکس آشنایی داشته باشید.اشتراک فایل با کانتینروقتی بخوایم یک پوشه رو از سیستم خودمون داخل کانتینر داشته باشیم اون رو داخلش mount می‌کنیم.  بعد از این کار اون پوشه داخل کانتینر دقیقا همون پوشه سیستم ماست. با آپشن v- این کارو انجام میدیم: بعد از گذاشتن v-، اول مسیر پوشه در سیستم خودمون بعد دو نقطه و در آخر مسیر پوشه در کانتینر رو میدیم. من در این مثال پوشه‌ای که توش هستم رو به جایی که nginx ازش فایل‌ index.html رو می‌خونه mount کردم. در این پوشه این فایل موجود نیست. بیاید به این کانتینر درخواست بدیم: یه پیغام خطا میده و غیر اون چیزی بهمون نمیده. چون فایلی که می‌خواد نیستش. حالا index.html رو می‌سازم و داخلش یه چیزی می‌نویسم:این بار درخواستم رو جواب داد. چون فایلی که می‌خواست رو پیدا کرد. من می‌تونم همین پوشه رو با کانتینرهای دیگه هم به اشتراک بذارم (mount کنم). این بار از اوبونتو استفاده می‌کنم:این دفعه تو پوشه home برای کاربر root گذاشتم. دیدیم که فایلی که داشتیم دوباره اینجاست. هر تغییری توش بدم هم تو سیستم خودم و هم تو nginx اعمال میشه:کپی کردن فایل از/به کانتینرمواقعی پیش میاد که نمی‌خوایم فایلی رو با سیستم خودمون به اشتراک بذاریم و فقط می‌خوایم یه چیزی رو به کانتینر بفرستیم یا ازش بگیریم. در این مواقع از cp استفاده میشه: اگر بخوایم از کانتینر به سیستم انتقال بدیم اول آیدی کانتینر، بعد دو نقطه و مسیر مورد نظر داخل کانتینر رو می‌نویسیم. در آخر یه فاصله میذاریم و مسیر در سیستم خودمون رو می‌نویسیم. در صورتی که قصدمون انتقال به کانتینر باشه این رو برعکسش می‌کنیم؛ یعنی اول مسیر تو سیستم، یه فاصله، بعد آیدی کانتینر، دو نقطه و مسیر داخل کانتینر. تو تصویر بالا من new.html رو به root/ در کانتینر انتقال دادم. جمع بندیدر این قسمت دیدیم چطوری میشه فایل‌ها رو به داخل کانتینر فرستاد یا پوشه‌ها رو در کانتینر mount  کرد. امیدوارم براتون مفید بوده باشه. اگر سوال یا نظری دارید این پایین بفرمایید.قسمت قبلیقسمت بعدی</description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Sat, 26 Dec 2020 08:54:03 +0330</pubDate>
            </item>
                    <item>
                <title>داکر برای برنامه‌نویس‌ها: قسمت پنجم - ارتباط با کانتینر</title>
                <link>https://virgool.io/paasino/docker-exec-publish-hh1xiqfcs03q</link>
                <description>مقدمهوقتی کانتینری رو اجرا می‌کنیم معمولا دلمون میخواد باهاش ارتباط برقرار کنیم. این ارتباط می‌تونه از طریق شبکه باشه یا این که داخل کانتینر یک شل بگیریم. در این قسمت این موارد رو بررسی می‌کنیم. مطالب این دفعه به درد برنامه‌نویس‌هایی که می‌خوان برنامه‌های داکرایز شده بنویسن می‌خوره. کسانی هم که قصد دارن ادمین سیستم بشن این مطلب رو مفید خواهند یافت.دیدن پورت کانتینر در پورت سیستمبیاید یک تصویر موجود در داکرهاب به نام nginx رو اجرا کنیم:این همون وب سرور معروف هست که در پورت ۸۰ به درخواست http ما گوش میده. اما در حال حاضر فقط لاگ‌هایی که میده رو می‌بینیم. برای ارتباط با این کانتینر ما نمی‌تونیم به ip اون درخواست بدیم چون دسترسی بهش نداریم. ما باید یک پورت اون رو expose کنیم. وقتی می‌خوایم یک کانتینر رو اجرا کنیم با آپشن p- بهش میگیم یک پورت از کانتینر رو در یه پورت سیستم publish کنه. جلوی این آپشن اول پورت سیستم و بعد پورت کانتینر رو میدیم:اینجا من پورت ۸۰ کانتینر رو می‌خواستم چون nginx روی اون جواب میده. پورت سیستم رو هر پورتی که آزاد باشه می‌تونم بذارم که من ۸۰۰۰ گذاشتم. حالا میشه تو مرورگر یا با curl به پورت ۸۰۰۰ سیستم و در نتیجه پورت ۸۰ کانتینر برسم:به این شکل ارتباط دنیای بیرون رو با کانتینر برقرار می‌کنم. جواب دریافت شده همون صفحه پیشفرض nginx هست.ارتباط از طریق شلممکنه یه موقعی بخوام برم داخل کانتینر و برای بررسی اون چند تا دستور اجرا کنم. در این موقع از exec استفاده می‌کنم. با exec میشه هر دستوری تو کانتینر اجرا کرد:تو این مثال گفتم در بش hello رو بنویسه.حالا با exec می‌خوایم بریم داخل کانتینر. بعد از اجرای کانتینر، نام یا id اون رو استفاده می‌کنم تا داخلش شل باز کنم: دو تا آپشن استفاده کردم: it- که به ما اجازه میده داخل کانتینر به شکل interactive کار کنیم. آخر هم مسیر بش رو دادم تا یه دونه شل اجرا بشه داخل کانتینر. خب الان داخلش هستم. میخوام فایل پیش فرض nginx رو تغییر بدم: حالا دوباره میرم خارج کانتینر curl می‌کنم: هورااا! تونستم از طریق دسترسی شل محتوای کانتینر رو تغییر بدم ^_^در کنار exec یه دستور دیگه هم هست که ممکنه با این اشتباه گرفته بشه. اونم attach هست. به exec هر دستوری بدید یه پروسه جدید شروع می‌کنه کنار پروسه اصلی. اما با attach ما به خود پروسه اصلی وصل میشیم. بیاید ببینیم. اول nginx رو با آپشن d- اجرا می‌کنم: این آپشن باعث میشه دیگه خروجی‌های کانتینر رو نبینم و در پس زمینه اجرا شه. در عوض فقط id کانتینر رو می‌نویسه. حالا با attach بهش وصل میشم:الان دوباره خروجی‌های nginx دیده میشه. البته خروجی‌های اولش رو دیگه نشون نمیده و فقط از اون لحظه که دستور رو اجرا کردم به بعد رو میاره.‌جمع بندی در این جلسه با روش‌هایی آشنا شدیم که میشه باهاشون با کانتینر ارتباط برقرار کرد. یک روش از طریق در معرض قرار دادن پورت هست و دیگری ssh کردن به اون. موقعی که یه برنامه نوشتیم و می‌خوایم داخل کانتینر اجراش کنیم این دو کار خیلی کمکمون می‌کنه.این قسمت هم تموم شد. امیدوارم استفاده کرده باشید. اگه صحبت یا نظری دارید این پایین بفرمایید.قسمت قبلیقسمت بعدی</description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Fri, 18 Dec 2020 22:53:58 +0330</pubDate>
            </item>
                    <item>
                <title>داکر برای برنامه‌نویس‌ها: قسمت چهارم - حذف تصویر و کانتینر در داکر</title>
                <link>https://virgool.io/paasino/docker-delete-container-image-zhlocv90dvz7</link>
                <description>مقدمهکم کم داریم در زمینه داکر راه می‌افتیم. تو قسمت قبل چند تا دستور ابتدایی رو اجرا کردیم و با اونا با تصاویر و کانتینرها آشنا شدیم. در این قسمت به حذف تصویر و کانتینر و فرستادن سیگنال به کانتینر خواهیم پرداخت. این مطلب برای برنامه‌نویس‌هایی که می‌خوان برنامه‌هاشون در داکر اجرا بشه و هم‌چنین سیس ادمین‌ها مفید خواهد بود.برای درک مطالب و اجرای دستورات لازمه با داکر و دستورات اون برای اجرای کانتینر آشنایی داشته باشید و داکر روی سیستم شما نصب باشه. می‌تونید برای این منظور قسمت‌های قبل این دنباله رو ببینید. هم‌چنین با مفهوم سیگنال و فرستادن اون به پروسه‌ها در لینوکس آشنایی داشته باشید. حذف تصویرتو قسمت قبل pull کردن تصویر رو یاد گرفتیم. اگه بخوایم تصویری رو حذف کنیم از docker rmi استفاده میشه: کلمه rmi رو با rm و i یاد داشته باشید. rm برای remove و i برای image. با docker images لیست تصاویر توی سیستم رو می‌بینم. همون طور که می‌بینید بعد از این دستور دیگه اون تصویر روی سیستم من نیست و اگر بخوامش باید دوباره دانلود کنم. اگه یه کانتینر در حال اجرا از اون تصویر داشته باشم لازمه اول اون رو از بین ببرم تا بتونم تصویرش رو پاک کنم:این‌جا بهم گفته که یه کانتینر از این تصویر وجود داره. باید کانتینر اول حذف شه. برای این کار بخش بعدی رو بخونید.حذف کانتینر وقتی کانتینری رو اجرا می‌کنم ممکنه بخوام حذفش کنم. قبلا هم دیدیم که کانتینرها پروسه‌‌های در حال اجرا هستند. پس به اونا میشه سیگنال فرستاد. با دستور docker stop به پروسه‌ی اصلی کانتینر سیگنال SIGTERM میفرسته تا خودش رو جمع و جور کنه و از بین بره. اگرم زیاد طول بکشه بعد چند ثانیه SIGKILL میفرسته و در جا از بین می‌بردش: تو اینجا یه کانتینر در حال اجرا رو دیدید که stop شد و از کار افتاد. دیگه توی docker ps نمی‌بینمش چون در حال اجرا نیست. ولی اگر docker ps -a بزنم هستش. برای این که از اونجا هم پاک شه از docker rm استفاده میشه: دیگه توی docker ps -a نیست. برای این دستورات لازم نیست از id کانتینر به شکل کامل استفاده کنیم. تا هر جا که بشه تشخیص داد (قابل تمایز از بقیه باشه) بنویسیم خودش میفهمه: تو این دستور b هم می‌نوشتم می‌فهمید.اگر خواستیم با اسم کانتینر رو حذف کنیم (یا هر دستور دیگه‌ای روش اجرا کنیم) می‌تونیم از auto completion با زدن TAB استفاده کنیم. در کنار حذف کارهای دیگه‌ای هم میشه با کانتینر انجام داد. می‌تونیم با دستور docker pause سیگنال SIGSTOP رو به پروسه اصلی بفرستیم: در بخش status وضعیت این کانتینر رو می‌بینید که متوقف شده. میشه کانتینرها رو از این دو وضعیت در‌آورد. می‌تونم با docker unpause از وضعیت paused به حالت running در بیارمش. با docker start هم میشه یه کانتینر که stop شده رو اجرا کرد. برای مثال start رو ببینین:اینجا اول کانتینر در حال اجرا نبود ولی با start اجرا شد. در کل اگر خواستین سیگنالی به کانتینر بفرستین از docker kill استفاده کنید که مثل kill در لینوکس عمل می‌کنه. جمع بندیدر این قسمت دیدیم چطور میشه یک تصویر یا کانتینر رو از بین برد. هم‌چنین یاد گرفتیم میشه به پروسه‌های کانتینر سیگنال‌های مختلف رو فرستاد. امیدوارم استفاده کرده باشید. اگر سوال یا نظری دارید این پایین بفرمایید. قسمت قبلیقسمت بعدی</description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Thu, 10 Dec 2020 18:13:36 +0330</pubDate>
            </item>
                    <item>
                <title>داکر برای برنامه‌نویس‌ها: قسمت سوم - دستورات ابتدایی در داکر</title>
                <link>https://virgool.io/paasino/docker-commands-pull-image-run-containers-xjahqv1ecsxi</link>
                <description>مقدمه رسیدیم به قسمت عملی ماجرا. در قسمت‌های قبل مفهوم کانتینر رو دونستیم و داکر رو نصب کردیم. حالا می‌خوایم در چند جلسه با کانتینرها و تصاویر کار کنیم تا تجربه عملی کسب کنیم. آشنایی و کار عملی با این مفاهیم هم به درد برنامه‌نویس‌ها می‌خوره و هم کسانی که می‌خوان سیس ادمین بشن. برای این قسمت باید داکر رو نصب کرده باشین و با مفهوم کانتینر، ایمیج و رجیستری داکر آشنایی داشته باشین.شناخت بیشتر تصویر (image)برای این که یه کانتینر بسازیم باید یه تصویر یا به انگلیسی image داشته باشیم. تصویر تمام اطلاعاتی که یه کانتینر لازم داره رو داخل خودش داره. مثلا فرض کنید شما یه برنامه به زبون پایتون نوشتید و می‌خواید به شکل کانتینر راه‌اندازی کنیدش. باید تمام فایل‌ها و تنظیمات لازم رو داخل یه تصویر قرار بدید و از روی تصویر کانتینر بسازید. خود ما می‌تونیم از اول یه تصویر رو بسازیم. اما خیلی بعیده که لازم باشه تصویری رو از اول خودمون بسازیم. ما از روی تصاویری که موجود هست تصویر جدید می‌سازیم یا همون‌ها رو استفاده می‌کنیم.تعداد زیادی تصویر آماده توسط شرکت‌های معتبر ساخته شده و در رجیستری داکر موجود هست.‌ ما می‌تونیم اون‌ها رو دانلود کنیم و بعد اجراشون کنیم یا از روشون تصویر جدید بسازیم. بیاید برای مثال یه تصویر خیلی ساده رو دانلود کنیم: با این دستور pull موتور داکر میره تو رجیستری و دنبال تصویری به نام hello-world می‌گرده و دانلودش می‌کنه. بعد از اتمام موفقیت‌آمیز این دستور، تصویر در سیستم ما وجود داره. با دستور docker images می‌تونم تصویرهایی که در سیستم هستن رو ببینم: در ستون اول اسم تصویر میاد. بعد تگ اون میاد. تگ خیلی مهمه برای تصویر. چون نسخه اون رو نشون میده. اگه موقع pull کردن هیچ تگی رو ندیم میره آخرین نسخه یا latest رو دانلود می‌کنه. برای این که نسخه بدیم به تصویر با دو نقطه معلومش می‌کنیم. مثلا ubuntu:20.04 نسخه 20.04 تصویر اوبونتو رو نشون میده. در ستون بعد یک id یکتا هست برای تصویر که می‌تونیم با اون هم صداش کنیم. بعد زمان ساخته شدن تصویر و در نهایت اندازه اون رو می‌بینیم. حالا می‌تونیم از روش کانتینر بسازیم: با دستور run از روی تصویری که جلوش نوشتیم کانتینر ساخته میشه. می‌تونستم همون اول run رو بنویسم. این دستور اگه ببینه تصویر وجود نداره، خودش اون رو pull می‌کنه. خروجیش رو ببینید. کانتینر اجرا شد و یک پیام نوشت و از بین رفت. وقتی پروسه‌ای که تو کانتینر در حال اجراست کارش تموم شه، کانتینر هم کارش تمومه.خب یه تصویر ساده رو اجرا کردیم و خروجیش رو دیدیم. تصاویر به درد بخور‌تری تو داکر رجیستری هست. مثلا تصویر ubuntu که وقتی اجرا شه گویا کانتینر ما داخل یه ماشین اوبونتو هست. تا دلتون بخواد تصاویر خوب و کاربردی در رجیستری داکر موجوده و تقریبا برای هر چیزی تصویر داریم. یه دسته از این تصاویر برای اجرای برنامه‌هایی که می‌نویسیم خیلی کاربردی هستن. مثلا تصویر python که توش پایتون هست و برای اجرای برنامه‌ی پایتون از اون استفاده میشه. از این دست تصاویر برای فریم‌ورک‌ها و زبان‌های مختلف ساخته شده و روی رجیستری داکر قرار دادن. با یه جستجو میشه برای هر برنامه‌ای تصویرش رو پیدا کرد.کار خوب دیگه‌ای که با تصویرها میکنن اینه که گاهی برای راحتی استفاده از یه ابزاری اون رو داخل تصویری میذارن و توی داکر رجیستری قرارش میدن. مثلا pyspark که برای big data کاربرد داره. چون نصب و تنظیم کردنش سخته گذاشتن تو یه تصویر که هر کی خواست دانلود کنه و برای کارهای علمی ازش بهره ببره. یا مثلا یه جا دیدم یه تصویر بود که مجموعه برنامه‌های مربوط به بیو الکتریک توش بود.پس در کل، با داشتن تصویر ما این امکان رو داریم یه برنامه یا مجموعه ابزار رو به شکل یکسان و سبک روی ماشین‌های مختلف داشته باشیم. فقط لازمه که داکر نصب شده باشه.کار با کانتینرها تو بخش قبل دیدیم که با دستور run میشه یه تصویر رو (در صورتی که روی سیستم‌مون نیست) pull کنیم و بعد کانتینری رو از روش بسازیم. حالا بیاید تصویر alpine رو اجرا کنیم:این تصویر یه لینوکس خیلی سبکه و کمک می‌کنه تصویری که از روش می‌سازیم هم خیلی سبک و کم حجم باشه. با دستور docker ps کانتینرهای در حال اجرا رو می‌بینیم: هیچ کانتینری در حال اجرا نیست. اون کانتینری که ساختیم خیلی سریع از بین رفت چون کاری ندادیم بهش. با اضافه کردن a- می‌تونیم تمام کانتینرها رو ببینیم؛ حتی اگه در حال اجرا نباشن: برای این که دستوری رو توی کانتینر اجرا کنیم این شکلی می‌نویسیم:جلوی اسم تصویر اون دستور رو نوشتم و بهش گفتم ۱۰۰ ثانیه فقط منتظر بمونه. حالا میرم تو یه شل دیگه تا docker ps رو اجرا کنم: این‌جا می‌بینم که کانتینر رو نشون میده. ستون اول یه id یکتا برای کانتینر هست. بعد تصویرش و بعد دستوری که زدیم. ستون بعدی زمانی که کانتینر ساخته شده رو میگه. ستون پنجم حالت کانتینر رو بیان می‌کنه که اینجا در حال اجراست. دقت کنید فاصله بین ساخت و در up شدن این کانتینر ۲ ثانیه بوده. این رو با یه ماشین مجازی مقایسه کنید! ستون ششم پورتی که از کانتینر expose کردیم رو میگه. فعلا این بحث رو انجام ندادیم ولی خیلی زود ایشالا بهش می‌رسیم. آخرین ستون هم یه اسم هست که خودش برای کانتیر انتخاب کرده. ما خودمون با name-- می‌تونیم این کار رو بکنیم.جمع بندیتو این جلسه با دستورهای ابتدایی داکر آشنا شدیم. دیدیم چطور تصویری pull میشه و می‌تونیم تصاویر موجود در سیستم رو ببینیم. هم‌چنین یاد گرفتیم چطوری از روی تصویر کانتینر بسازیم و کانتینرهای در حال اجرا تو سیستم رو ببینیم.قسمت قبلیقسمت بعدی</description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Thu, 03 Dec 2020 18:21:02 +0330</pubDate>
            </item>
                    <item>
                <title>داکر برای برنامه‌نویس‌ها: قسمت دوم - نصب داکر</title>
                <link>https://virgool.io/paasino/docker-install-hbf9lglvpbey</link>
                <description>مقدمهامروز می‌خوایم راجع به نصب داکر صحبت کنیم. این مطلب برای هر کسی که می‌خواد با داکر کار کنه مفید خواهد بود. فرقی نداره کار dev می‌کنید یا کارای ops.  برای این نوشته لازمه که با تنظیمات شبکه‌ای در لینوکس آشنایی داشته باشید و با خط فرمان لینوکس کار کرده باشید.ممکنه برای نصب داکر به مشکل تحریم بخوریم. ممکن هم هست نخوریم. بگیر نگیر داره. برای نصب داکر از این لینک پیروی کنید.اینجا میخوام اجرای این روند نصب و رفع مشکل تحریم رو نشون بدم. اگر نکاتی هم باشه در حین کار میگم. فعلا راجع به سرور اوبونتو 18.04 صحبت می‌کنیم و ایشالا بعدا برای centos هم تکمیل میشه.مشکل تحریمبرای این که بتونیم داکر رو نصب کنیم ممکنه لازم نباشه این مرحله رو بریم. می‌تونید مراحل نصب رو طی کنید و ببینید مشکل تحریم هست یا نه. قبلا هم گفتم. بگیر نگیر داره. راهکاری که من دارم استفاده از شکن هست. این سایت دو تا ip به عنوان dns server ارائه داده که ما باید اون رو تنظیم کنیم. راهی که خیلیا استفاده میکنن اینه که اون ip ها رو داخل etc/resolv.conf/ بنویسن. این میتونه کار کنه ولی ممکنه لازم باشه مدام این کارو انجام بدین؛ چون این فایل تغییر می‌کنه. راه مطمئن چیه؟ این که بیایم تو تنظیمات interface شبکه‌مون این آدرس‌ها رو بذاریم. در اوبونتو 18 از netplan برای تنظیم interface شبکه استفاده میشه.با دسترسی روت داخل فایلی که توی etc/netplan/ هست این بخش رو می‌نویسم:    ....
     ethernets:
       ....
         enp01:
         ....
            nameservers:
                addresses: 
                    - 178.22.122.100
                    - 185.51.200.2دقت کنید که enp01 اسم اینترفیس شبکه هست و باید با دستور ifconfig یا هر دستوری که خودتون می‌دونید این اسم رو پیدا کنید و اینجا بذارید.حالا کافیه برای اینکه این تغییرات اعمال بشن دستور زیر رو بزنیم: $ sudo netplan applyبه این شکل شما می‌تونید مشکل تحریم رو در صورت وجود رفع کنید.نصب داکر چند تا راه در سایت داکر موجود هست ولی ما رایج‌ترین و راحت‌ترینش رو انجام میدیم.اول گفته که هر کدوم از نسخه‌های قبلی رو پاک کنیم: اگر هیچ کدومشون وجود نداشتن هم مشکلی نداره.بعد apt رو به‌ روز‌ رسانی کرده و تعدادی بسته نصب می‌کنیم:ممکنه چند دقیقه طول بکشه. بعد هم مراحل اضافه کردن مخزن داکر به apt رو طی می‌کنیم: با اضافه کردن مخزن جدید لازمه دوباره apt رو به روز رسانی کنیم و داکر رو نصب کنیم: این یکی ممکنه خیلی طول بکشه. درصد پیشرفت رو می‌نویسه. اگر نسخه خاصی از اون رو لازم دارید اول با دستور زیر ببینید چه نسخه‌هایی موجود هست:  یه لیست بلند بالا میاد براتون. بعد به این شکل نسخه‌ی دلخواه رو نصب کنید: ایشالا برای سیس‌ادمین‌هایی که لازم دارن روی تعداد زیادی ماشین داکر رو نصب کنن در مورد نصب اون با ansible هم یه مطلب می‌نویسم ولی در این دوره که برای برنامه‌نویس‌ها هست دونستن اون لازم نیست. حالا دستور زیر رو اجرا کنیم تا مطمئن شیم همه چی درسته:برای این که لازم نباشه مدام sudo بزنیم برای دستور docker می‌تونید این کار رو بکنید:به جای اوبونتو user خودتون رو بنویسید. با این کار user شما به گروه docker اضافه میشه و میتونه دستور رو خودش اجرا کنه و لازم نیست sudo کنه. ممکنه لازم باشه یه بار شل رو ببندید و باز کنید تا تغییرات تاثیر بذارن. جمع بندی در این قسمت دیدیم چطور میشه داکر رو نصب کرد تا در قسمت‌های بعدی از اون استفاده کنیم. هم‌چنین اگر به مشکل تحریم خوردید میتونید با استفاده از شکن حلش کنید. دقت کنید که برای مصرف تجاری شکن پولیه. این مطلب به اتمام رسید. امیدوارم استفاده کرده باشید. اگر نظر یا سوالی دارید این پایین بفرمایید. قسمت قبلیقسمت بعدی</description>
                <category>Ali Akbar Hemmati</category>
                <author>Ali Akbar Hemmati</author>
                <pubDate>Thu, 26 Nov 2020 23:38:07 +0330</pubDate>
            </item>
            </channel>
</rss>