پیشنهاد می کنم متن گزارش الکساندر سیگاچف از Inventos "توسعه و فرآیند آزمایش با Docker + Gitlab CI" را بخوانید.
کسانی که به تازگی شروع به پیاده سازی فرآیند توسعه و آزمایش بر اساس Docker + Gitlab CI کرده اند، اغلب سوالات اساسی می پرسند. از کجا شروع کنیم؟ چگونه سازماندهی کنیم؟ چگونه تست کنیم؟
این گزارش خوب است زیرا به روشی ساختاریافته در مورد فرآیند توسعه و آزمایش با استفاده از Docker و Gitlab CI صحبت می کند. خود گزارش مربوط به سال 2017 است. من فکر می کنم که از این گزارش می توانید اصول، روش، ایده، تجربه استفاده را بیاموزید.
چه کسی اهمیت می دهد، لطفا زیر گربه.
نام من الکساندر سیگاچف است. من برای Inventos کار می کنم. من در مورد تجربه خود از استفاده از Docker و نحوه اجرای تدریجی آن در پروژه های شرکت به شما خواهم گفت.
موضوع ارائه: فرآیند توسعه با استفاده از Docker و Gitlab CI.
این دومین صحبت من در مورد داکر است. در زمان اولین گزارش، ما فقط از Docker در توسعه در ماشین های توسعه دهنده استفاده می کردیم. تعداد کارمندانی که از داکر استفاده کردند حدود 2-3 نفر بود. کم کم تجربه کسب شد و کمی جلوتر رفتیم. پیوند به ما
در این گزارش چه خواهد بود؟ ما تجربه خود را در مورد اینکه چه رنک جمع آوری کرده ایم، چه مشکلاتی را حل کرده ایم به اشتراک خواهیم گذاشت. نه همه جا زیبا بود، اما اجازه داد که به جلو برود.
شعار ما این است: هر چیزی که به دستمان می رسد را به اسکله بریزید.
چه مشکلاتی را حل می کنیم؟
وقتی چندین تیم در یک شرکت وجود دارد، برنامه نویس یک منبع مشترک است. مراحلی وجود دارد که یک برنامه نویس از یک پروژه بیرون کشیده می شود و برای مدتی به پروژه دیگری داده می شود.
برای اینکه برنامه نویس به سرعت متوجه شود، باید کد منبع پروژه را دانلود کرده و در اسرع وقت محیط را راه اندازی کند، که به او اجازه می دهد تا برای حل مشکلات این پروژه بیشتر حرکت کند.
معمولاً اگر از ابتدا شروع کنید، اسناد کمی در پروژه وجود دارد. اطلاعات مربوط به نحوه راه اندازی فقط برای قدیمی ترها در دسترس است. کارمندان در یک یا دو روز به تنهایی محل کار خود را راه اندازی می کنند. برای سرعت بخشیدن به این کار، از Docker استفاده کردیم.
دلیل بعدی استانداردسازی تنظیمات در توسعه است. در تجربه من، توسعه دهندگان همیشه ابتکار عمل را به دست می گیرند. در هر پنجمین مورد، یک دامنه سفارشی وارد می شود، به عنوان مثال vasya.dev. در کنار او همسایه اش پتیا نشسته است که دامنه اش petya.dev است. آنها یک وب سایت یا بخشی از سیستم را با استفاده از این نام دامنه توسعه می دهند.
هنگامی که سیستم رشد می کند و این نام های دامنه شروع به وارد شدن به تنظیمات می کنند، یک تضاد محیط توسعه ایجاد می شود و مسیر سایت بازنویسی می شود.
همین امر در مورد تنظیمات پایگاه داده نیز اتفاق می افتد. کسی با امنیت کار نمی کند و با رمز عبور خالی روت کار می کند. در مرحله نصب، MySQL از شخصی رمز عبور درخواست کرد و رمز عبور ۱۲۳ بود. اغلب اتفاق میافتد که پیکربندی پایگاه داده بسته به تعهد توسعهدهنده دائماً تغییر میکند. یکی تصحیح کرد، یکی پیکربندی را اصلاح نکرد. ترفندهایی وجود داشت که ما نوعی پیکربندی آزمایشی را وارد کردیم .gitignore
و هر توسعه دهنده باید پایگاه داده را نصب می کرد. این کار شروع را دشوار می کرد. لازم است، از جمله موارد دیگر، در مورد پایگاه داده به یاد داشته باشید. پایگاه داده باید مقداردهی اولیه شود، رمز عبور باید وارد شود، کاربر باید ثبت شود، جدول باید ایجاد شود و غیره.
مشکل دیگر نسخه های مختلف کتابخانه ها است. اغلب اتفاق می افتد که یک توسعه دهنده با پروژه های مختلف کار می کند. یک پروژه Legacy وجود دارد که پنج سال پیش (از سال 2017 - یادداشت ویرایش) شروع شده است. در زمان راه اندازی، ما با MySQL 5.5 شروع کردیم. همچنین پروژههای مدرنی وجود دارد که سعی میکنیم نسخههای مدرنتری از MySQL را پیادهسازی کنیم، بهعنوان مثال، 5.7 یا قدیمیتر (در سال 2017 - یادداشت ویرایش)
هرکسی که با MySQL کار میکند میداند که این کتابخانهها وابستگیهایی را به همراه دارند. اجرای 2 پایه با هم مشکل ساز است. حداقل، مشتریان قدیمی برای اتصال به پایگاه داده جدید مشکل دارند. این به نوبه خود مشکلات متعددی را ایجاد می کند.
مشکل بعدی زمانی است که یک توسعه دهنده روی یک ماشین محلی کار می کند، از منابع محلی، فایل های محلی، رم محلی استفاده می کند. تمام تعاملات در زمان ایجاد راه حل برای مشکلات در چارچوب این واقعیت انجام می شود که روی یک ماشین کار می کند. یک مثال زمانی است که در Production 3 سرورهای پشتیبان داریم و توسعه دهنده فایل ها را در دایرکتوری ریشه ذخیره می کند و از آنجا nginx فایل ها را می گیرد تا به درخواست پاسخ دهد. وقتی چنین کدی وارد Production می شود، معلوم می شود که فایل در یکی از 3 سرور موجود است.
جهت گیری میکروسرویس ها اکنون در حال توسعه است. وقتی برنامه های بزرگ خود را به اجزای کوچکی تقسیم می کنیم که با یکدیگر تعامل دارند. این به شما امکان می دهد فناوری ها را برای مجموعه خاصی از وظایف انتخاب کنید. همچنین به شما این امکان را می دهد که کار و مسئولیت ها را بین توسعه دهندگان به اشتراک بگذارید.
Frondend-developer که در JS در حال توسعه است، تقریباً هیچ تأثیری بر Backend ندارد. توسعه دهنده باطن نیز به نوبه خود، در مورد ما، Ruby on Rails را توسعه می دهد و با Fronend تداخلی نمی کند. تعامل با استفاده از API انجام می شود.
به عنوان یک امتیاز، با کمک Docker، ما توانستیم منابع را در Staging بازیافت کنیم. هر پروژه به دلیل ویژگی های خاص خود نیاز به تنظیمات خاصی داشت. از نظر فیزیکی، لازم بود یا یک سرور مجازی تخصیص داده شود و آنها را به طور جداگانه پیکربندی کنیم، یا اینکه نوعی محیط متغیر به اشتراک گذاشته شود و پروژه ها بسته به نسخه کتابخانه ها بتوانند بر یکدیگر تأثیر بگذارند.
ابزار. از چه چیزی استفاده می کنیم؟
- خود داکر. Dockerfile وابستگی های یک برنامه را توصیف می کند.
- Docker-compose بستهای است که تعدادی از برنامههای Docker ما را گرد هم میآورد.
- ما از GitLab برای ذخیره کد منبع استفاده می کنیم.
- ما از GitLab-CI برای یکپارچه سازی سیستم استفاده می کنیم.
گزارش از دو بخش تشکیل شده است.
بخش اول در مورد نحوه اجرای Docker بر روی ماشین های توسعه دهندگان صحبت خواهد کرد.
بخش دوم در مورد نحوه تعامل با GitLab، نحوه اجرای تستها و نحوه اجرای مرحلهبندی صحبت خواهد کرد.
داکر یک فناوری است که (با استفاده از یک رویکرد اعلامی) اجازه می دهد تا اجزای لازم را توصیف کند. این یک نمونه Dockerfile است. در اینجا ما اعلام می کنیم که از تصویر رسمی Ruby:2.3.0 Docker به ارث برده ایم. این شامل روبی نسخه 2.3 نصب شده است. ما کتابخانه های ساخت و NodeJS مورد نیاز را نصب می کنیم. ما توضیح می دهیم که یک دایرکتوری ایجاد می کنیم /app
. دایرکتوری برنامه را به عنوان دایرکتوری کاری تنظیم کنید. در این دایرکتوری حداقل Gemfile و Gemfile.lock مورد نیاز را قرار می دهیم. سپس پروژه هایی را می سازیم که این تصویر وابستگی را نصب می کنند. نشان میدهیم که کانتینر برای گوش دادن به درگاه خارجی 3000 آماده خواهد بود. آخرین دستور دستوری است که مستقیماً برنامه ما را راهاندازی میکند. اگر دستور شروع پروژه را اجرا کنیم، برنامه سعی می کند دستور مشخص شده را اجرا و اجرا کند.
این یک نمونه حداقلی از یک فایل docker-compose است. در این حالت نشان می دهیم که بین دو ظرف ارتباط وجود دارد. این به طور مستقیم به سرویس پایگاه داده و سرویس وب است. برنامه های کاربردی وب ما در بیشتر موارد به نوعی پایگاه داده به عنوان پشتیبان برای ذخیره داده ها نیاز دارند. از آنجایی که ما از MySQL استفاده می کنیم، مثال با MySQL است - اما هیچ چیز ما را از استفاده از پایگاه داده دیگری (PostgreSQL، Redis) باز نمی دارد.
تصویر MySQL 5.7.14 را بدون تغییر از منبع رسمی از داکر هاب می گیریم. ما تصویری را که مسئول برنامه وب ما است از دایرکتوری فعلی جمع آوری می کنیم. در اولین پرتاب تصویری را برای ما جمع آوری می کند. سپس دستوری را که در اینجا اجرا می کنیم اجرا می کند. اگر به عقب برگردیم می بینیم که دستور راه اندازی از طریق پوما تعریف شده است. پوما سرویسی است که به زبان روبی نوشته شده است. در حالت دوم، ما لغو می کنیم. این دستور بسته به نیاز یا وظایف ما می تواند دلخواه باشد.
ما همچنین توضیح می دهیم که باید یک پورت را در دستگاه میزبان توسعه دهنده خود از 3000 به 3000 در پورت کانتینر فوروارد کنیم. این به طور خودکار با استفاده از iptables و مکانیسم آن که مستقیماً در Docker تعبیه شده است انجام می شود.
توسعه دهنده همچنین می تواند مانند قبل به هر آدرس IP موجود دسترسی داشته باشد، به عنوان مثال، 127.0.0.1 آدرس IP محلی یا خارجی دستگاه است.
خط آخر می گوید که کانتینر وب به ظرف db بستگی دارد. هنگامی که شروع وب کانتینر را فراخوانی می کنیم، docker-compose ابتدا پایگاه داده را برای ما راه اندازی می کند. در حال حاضر در شروع پایگاه داده (در واقع، پس از راه اندازی ظرف! این آمادگی پایگاه داده را تضمین نمی کند) برنامه، باطن ما را راه اندازی می کند.
این از خطاها در زمانی که پایگاه داده بالا نمی آید جلوگیری می کند و زمانی که ظرف پایگاه داده را متوقف می کنیم، منابع را ذخیره می کند، بنابراین منابع را برای پروژه های دیگر آزاد می کند.
چه چیزی به ما امکان استفاده از dockerization پایگاه داده را در پروژه می دهد. ما نسخه MySQL را برای همه توسعه دهندگان تعمیر می کنیم. با این کار از برخی خطاهایی که ممکن است در هنگام واگرایی نسخه ها، زمانی که نحو، پیکربندی، تنظیمات پیش فرض تغییر می کنند، رخ دهد، جلوگیری می کند. این به شما امکان می دهد یک نام میزبان مشترک برای پایگاه داده، ورود به سیستم، رمز عبور تعیین کنید. ما در حال دور شدن از باغ وحش نام ها و درگیری ها در فایل های پیکربندی که قبلاً داشتیم، هستیم.
ما این فرصت را داریم که از یک پیکربندی بهینه تر برای محیط توسعه استفاده کنیم که با پیش فرض متفاوت است. MySQL به طور پیش فرض برای ماشین های ضعیف پیکربندی شده است و عملکرد خارج از جعبه آن بسیار ضعیف است.
Docker به شما امکان می دهد از مفسر Python، Ruby، NodeJS، PHP نسخه مورد نظر استفاده کنید. ما از نیاز به استفاده از نوعی مدیر نسخه خلاص می شویم. پیش از این، روبی از یک بسته rpm استفاده می کرد که به شما امکان می داد بسته به پروژه نسخه را تغییر دهید. همچنین به لطف کانتینر Docker، اجازه می دهد تا کد را به آرامی منتقل کرده و آن را همراه با وابستگی ها نسخه کنید. ما مشکلی در درک نسخه مفسر و کد نداریم. برای به روز رسانی نسخه، ظرف قدیمی را پایین بیاورید و ظرف جدید را بالا بیاورید. اگر مشکلی پیش آمد، می توانیم ظرف جدید را پایین بیاوریم، ظرف قدیمی را بالا بیاوریم.
پس از ساخت تصویر، کانتینرها در توسعه و تولید یکسان خواهند بود. این امر به ویژه در مورد تاسیسات بزرگ صادق است.
در Frontend ما از JavaScipt و NodeJS استفاده می کنیم.
اکنون آخرین پروژه در ReacJS را داریم. توسعه دهنده همه چیز را در کانتینر اجرا کرد و با استفاده از بارگذاری مجدد داغ توسعه داد.
سپس، وظیفه اسمبلی جاوا اسکپت راه اندازی می شود و کد کامپایل شده به استاتیک از طریق منابع ذخیره nginx داده می شود.
در اینجا من طرح آخرین پروژه خود را آورده ام.
چه کارهایی حل شد؟ ما نیاز به ایجاد سیستمی داشتیم که دستگاه های تلفن همراه با آن تعامل داشته باشند. داده ها را دریافت می کنند. یکی از امکان ها ارسال push notifications به این دستگاه است.
ما برای این کار چه کرده ایم؟
ما این برنامه را به اجزای زیر تقسیم کردیم: بخش مدیریت در JS، باطن، که از طریق رابط REST تحت Ruby on Rails کار می کند. Backend با پایگاه داده تعامل دارد. نتیجه ای که ایجاد می شود به مشتری داده می شود. پنل مدیریت با باطن و پایگاه داده از طریق رابط REST تعامل دارد.
ما همچنین نیاز به ارسال اعلانهای فشار داشتیم. قبل از آن، پروژهای داشتیم که مکانیزمی را پیادهسازی کرد که وظیفه ارسال نوتیفیکیشنها به پلتفرمهای موبایل را بر عهده دارد.
ما طرح زیر را توسعه دادهایم: یک اپراتور از مرورگر با پنل مدیریت تعامل میکند، پنل مدیریت با باطن تعامل میکند، وظیفه ارسال اعلانهای Push است.
اعلانهای فشاری با مؤلفه دیگری که در NodeJS پیادهسازی شده است، تعامل دارند.
صف ها ساخته می شوند و سپس نوتیفیکیشن ها مطابق سازوکارشان ارسال می شود.
دو پایگاه داده در اینجا ترسیم شده است. در حال حاضر به کمک داکر از 2 پایگاه داده مستقل استفاده می کنیم که به هیچ وجه به هم مرتبط نیستند. علاوه بر این، آنها یک شبکه مجازی مشترک دارند و داده های فیزیکی در دایرکتوری های مختلف در ماشین توسعه دهنده ذخیره می شود.
همینطوره ولی به تعداد اینجاست که استفاده مجدد از کد مهم است.
اگر قبلاً در مورد استفاده مجدد از کد در قالب کتابخانه ها صحبت کردیم، در این مثال، سرویس ما که به اعلان های Push پاسخ می دهد به عنوان یک سرور کامل مجدداً استفاده می شود. یک API ارائه می دهد. و توسعه جدید ما در حال حاضر با آن تعامل دارد.
در آن زمان ما از نسخه 4 NodeJS استفاده می کردیم. اکنون (در سال 2017 - یادداشت ویرایش) در توسعه های اخیر از نسخه 7 NodeJS استفاده می کنیم. هیچ مشکلی در اجزای جدید برای درگیر کردن نسخه های جدید کتابخانه ها وجود ندارد.
در صورت لزوم می توانید نسخه NodeJS را از سرویس Push notification refactor کرده و ارتقا دهید.
و اگر بتوانیم سازگاری API را حفظ کنیم، میتوان آن را با پروژههای دیگری که قبلاً استفاده میشد جایگزین کرد.
برای اضافه کردن Docker به چه چیزی نیاز دارید؟ ما یک Dockerfile را به مخزن خود اضافه می کنیم که وابستگی های لازم را توضیح می دهد. در این مثال، اجزا به صورت منطقی شکسته می شوند. این حداقل مجموعه یک توسعه دهنده باطن است.
هنگام ایجاد یک پروژه جدید، ما یک Dockerfile ایجاد می کنیم، اکوسیستم مورد نظر را توصیف می کنیم (Python، Ruby، NodeJS). در docker-compose، وابستگی لازم - پایگاه داده را توصیف می کند. ما توضیح می دهیم که به یک پایگاه داده از فلان نسخه نیاز داریم، داده ها را آنجا و آنجا ذخیره کنیم.
برای سرو استاتیک از یک ظرف سوم جداگانه با nginx استفاده می کنیم. امکان آپلود تصاویر وجود دارد. Backend آنها را در یک حجم از پیش آماده شده قرار می دهد، که همچنین در یک ظرف با nginx نصب می شود، که استاتیک را می دهد.
برای ذخیره تنظیمات nginx، mysql، یک پوشه Docker اضافه کردیم که تنظیمات لازم را در آن ذخیره می کنیم. هنگامی که یک توسعه دهنده یک کلون git از یک مخزن را روی دستگاه خود انجام می دهد، از قبل پروژه ای آماده برای توسعه محلی دارد. هیچ سوالی وجود ندارد که چه پورتی یا چه تنظیماتی اعمال شود.
بعد، ما چندین مؤلفه داریم: admin، inform-API، push notifications.
برای شروع همه اینها، ما یک مخزن دیگر ایجاد کردیم که آن را dockerized-app نامیدیم. در حال حاضر قبل از هر جزء از چندین مخزن استفاده می کنیم. آنها فقط از نظر منطقی متفاوت هستند - در GitLab مانند یک پوشه به نظر می رسد، اما در ماشین توسعه دهنده، یک پوشه برای یک پروژه خاص. یک سطح پایین تر، اجزایی هستند که با هم ترکیب می شوند.
این تنها نمونه ای از محتویات برنامه dockerized است. ما همچنین دایرکتوری Docker را در اینجا می آوریم که در آن تنظیمات مورد نیاز برای تعاملات همه اجزا را پر می کنیم. یک README.md وجود دارد که به طور خلاصه نحوه اجرای پروژه را توضیح می دهد.
در اینجا ما دو فایل docker-compose را اعمال کرده ایم. این کار به این منظور انجام می شود که بتوان در مرحله اجرا کرد. هنگامی که یک توسعه دهنده با هسته کار می کند، او نیازی به اعلان های فشار ندارد، او به سادگی یک فایل docker-compose را راه اندازی می کند و بر این اساس، منبع ذخیره می شود.
اگر نیاز به ادغام با اعلانهای فشار وجود دارد، docker-compose.yaml و docker-compose-push.yaml راهاندازی میشوند.
از آنجایی که docker-compose.yaml و docker-compose-push.yaml در یک پوشه هستند، یک شبکه مجازی واحد به طور خودکار ایجاد می شود.
شرح اجزاء این یک فایل پیشرفته تر است که وظیفه جمع آوری کامپوننت ها را بر عهده دارد. چه چیزی در اینجا قابل توجه است؟ در اینجا مولفه متعادل کننده را معرفی می کنیم.
این یک تصویر داکر آماده است که nginx را اجرا می کند و برنامه ای است که در سوکت داکر گوش می دهد. پویا، با روشن و خاموش شدن کانتینرها، پیکربندی nginx را بازسازی می کند. ما مدیریت مؤلفه ها را با نام دامنه های سطح سوم توزیع می کنیم.
برای محیط توسعه، از دامنه .dev - api.informer.dev استفاده می کنیم. برنامه های کاربردی با دامنه .dev در ماشین محلی توسعه دهنده در دسترس هستند.
علاوه بر این، پیکربندی ها به هر پروژه منتقل می شوند و همه پروژه ها با هم راه اندازی می شوند.
از نظر گرافیکی، معلوم می شود که مشتری مرورگر ما یا ابزاری است که با آن از متعادل کننده درخواست می کنیم.
متعادل کننده نام دامنه تعیین می کند که با کدام ظرف تماس بگیرید.
این می تواند nginx باشد که به ادمین JS می دهد. این می تواند nginx باشد که API را می دهد یا فایل های ثابتی که به صورت آپلود تصویر به nginx داده می شود.
نمودار نشان می دهد که کانتینرها توسط یک شبکه مجازی متصل شده و در پشت یک پروکسی پنهان شده اند.
در دستگاه توسعه دهنده، می توانید با دانستن IP به کانتینر دسترسی پیدا کنید، اما در اصل ما از این استفاده نمی کنیم. عملا نیازی به دسترسی مستقیم نیست.
برای داکر کردن اپلیکیشن خود به کدام مثال نگاه کنیم؟ به نظر من، یک مثال خوب، تصویر رسمی docker برای MySQL است.
این کاملا چالش برانگیز است. نسخه های زیادی وجود دارد. اما عملکرد آن به شما امکان می دهد بسیاری از نیازهایی را که ممکن است در روند توسعه بیشتر ایجاد شود، پوشش دهید. اگر زمان بگذرانید و بفهمید که همه اینها چگونه تعامل دارند، فکر می کنم هیچ مشکلی در خود پیاده سازی نخواهید داشت.
Hub.docker.com معمولاً حاوی پیوندهایی به github.com است که حاوی داده های خام است که مستقیماً می توانید تصویر را از آن بسازید.
علاوه بر این در این مخزن یک اسکریپت docker-endpoint.sh وجود دارد که مسئول اولیه سازی اولیه و پردازش بیشتر راه اندازی برنامه است.
همچنین در این مثال، قابلیت پیکربندی با استفاده از متغیرهای محیطی وجود دارد. با تعریف متغیر محیطی هنگام اجرای یک کانتینر یا از طریق docker-compose، میتوان گفت که باید یک رمز عبور خالی برای روت کردن داکر در MySQL یا هر چیزی که میخواهیم تنظیم کنیم.
گزینه ای برای ایجاد رمز عبور تصادفی وجود دارد. ما می گوییم که به یک کاربر نیاز داریم، باید برای کاربر رمز عبور قرار دهیم و باید یک پایگاه داده ایجاد کنیم.
در پروژههایمان، Dockerfile را که مسئول مقداردهی اولیه است، کمی متحد کردیم. در آنجا ما آن را مطابق با نیازهای خود اصلاح کردیم تا آن را فقط به عنوان یک بسط حقوق کاربری که برنامه استفاده می کند تبدیل کنیم. این به ما اجازه داد تا بعداً به سادگی یک پایگاه داده از کنسول برنامه ایجاد کنیم. برنامه های روبی دستوری برای ایجاد، تغییر و حذف پایگاه داده دارند.
این نمونه ای از ظاهر یک نسخه خاص از MySQL در github.com است. می توانید Dockerfile را باز کنید و ببینید نصب در آنجا چگونه انجام می شود.
docker-endpoint.sh اسکریپت مسئول نقطه ورودی است. در طول مقداردهی اولیه، برخی مراحل آماده سازی مورد نیاز است، و تمام این اقدامات فقط در اسکریپت اولیه انجام می شود.
بریم سراغ قسمت دوم.
برای ذخیره کدهای منبع، به gitlab تغییر مکان دادیم. این یک سیستم نسبتا قدرتمند است که دارای یک رابط بصری است.
یکی از اجزای Gitlab Gitlab CI است. این به شما امکان می دهد دنباله ای از دستورات را توصیف کنید که بعداً برای سازماندهی یک سیستم تحویل کد یا اجرای آزمایش خودکار استفاده می شود.
بحث Gitlab CI 2
اکنون به آنچه برای فعال کردن Gitlab CI لازم است نگاه می کنیم. برای شروع Gitlab CI کافیست فایل .gitlab-ci.yml را در ریشه پروژه قرار دهیم.
در اینجا توضیح میدهیم که میخواهیم دنبالهای از حالتها را اجرا کنیم، مانند آزمایش، Deploy.
ما اسکریپت هایی را اجرا می کنیم که مستقیماً docker-compose را برای ساخت برنامه ما فراخوانی می کنند. این فقط یک مثال پشتیبان است.
در مرحله بعد می گوییم که برای تغییر پایگاه داده و اجرای تست ها باید migrations را اجرا کرد.
اگر اسکریپت ها به درستی اجرا شوند و کد خطا را برنگردانند، سیستم وارد مرحله دوم استقرار می شود.
مرحله استقرار در حال حاضر برای مرحله بندی اجرا شده است. ما یک راهاندازی مجدد بدون توقف سازماندهی نکردیم.
همه ظروف را به زور خاموش می کنیم و سپس همه ظروف را که در مرحله اول در حین آزمایش جمع آوری شده اند دوباره بالا می آوریم.
ما برای متغیر محیط فعلی مهاجرت های پایگاه داده را که توسط توسعه دهندگان نوشته شده است اجرا می کنیم.
نکته ای وجود دارد که این فقط برای شاخه اصلی اعمال می شود.
هنگامی که تغییر شاخه های دیگر اجرا نمی شود.
امکان سازماندهی rollout ها بر اساس شاخه ها وجود دارد.
برای سازماندهی بیشتر این موضوع، باید Gitlab Runner را نصب کنیم.
این ابزار به زبان Golang نوشته شده است. این یک فایل واحد است، همانطور که در دنیای Golang معمول است، که به هیچ گونه وابستگی نیاز ندارد.
هنگام راه اندازی، Gitlab Runner را ثبت می کنیم.
ما کلید را در رابط وب Gitlab دریافت می کنیم.
سپس دستور مقداردهی اولیه را در خط فرمان فراخوانی می کنیم.
راه اندازی Gitlab Runner به صورت تعاملی (Shell، Docker، VirtualBox، SSH)
کد موجود در Gitlab Runner بسته به تنظیمات gitlab-ci.yml در هر commit اجرا می شود.
چگونه از نظر بصری در Gitlab در رابط وب به نظر می رسد. بعد از اینکه Gitlab CI را متصل کردیم، یک پرچم داریم که وضعیت بیلد را در لحظه نشان می دهد.
می بینیم که 4 دقیقه پیش یک commit انجام شد که تمام تست ها را پشت سر گذاشت و مشکلی ایجاد نکرد.
میتوانیم نگاه دقیقتری به ساختها بیندازیم. در اینجا می بینیم که دو حالت قبلاً گذشته است. وضعیت آزمایش و وضعیت استقرار در مرحله استقرار.
اگر روی یک بیلد خاص کلیک کنیم، یک خروجی کنسول از دستوراتی که در این فرآیند مطابق gitlab-ci.yml اجرا شده اند، وجود خواهد داشت.
این چیزی است که تاریخچه محصول ما به نظر می رسد. می بینیم که تلاش های موفقیت آمیزی انجام شد. زمانی که تست ها ارسال می شود، به مرحله بعدی نمی رود و کد مرحله بندی به روز نمی شود.
هنگام اجرای docker چه وظایفی را در مرحله استیج حل کردیم؟ سیستم ما از اجزا تشکیل شده است و ما نیاز به راه اندازی مجدد داشتیم، فقط بخشی از مؤلفه هایی که در مخزن به روز شده بودند و نه کل سیستم.
برای انجام این کار، ما مجبور شدیم همه چیز را در پوشه های جداگانه خرد کنیم.
بعد از اینکه این کار را انجام دادیم، با این واقعیت که Docker-compose فضای شبکه خود را برای هر بابا ایجاد می کند و اجزای همسایه را نمی بیند، مشکل داشتیم.
به منظور دور زدن، شبکه را در Docker به صورت دستی ایجاد کردیم. در Docker-compose نوشته شده بود که از چنین شبکه ای برای این پروژه استفاده می کنید.
بنابراین، هر جزء که با این مش شروع می شود، اجزایی را در قسمت های دیگر سیستم می بیند.
مسئله بعدی، تقسیم صحنه سازی در چندین پروژه است.
از آنجایی که برای اینکه همه اینها زیبا به نظر برسند و تا حد ممکن به تولید نزدیک شوند، خوب است از پورت 80 یا 443 استفاده کنید که در همه جای WEB استفاده می شود.
چطور حلش کردیم؟ ما یک Gitlab Runner را به تمام پروژه های بزرگ اختصاص داده ایم.
Gitlab به شما امکان می دهد چندین Gitlab Runners توزیع شده را اجرا کنید، که به سادگی تمام وظایف را به نوبه خود به شیوه ای آشفته انجام می دهد و آنها را اجرا می کند.
برای اینکه خانه نداشته باشیم، گروه پروژه هایمان را به یک Gitlab Runner محدود کردیم که بدون مشکل با حجم های ما کنار می آید.
ما nginx-proxy را به یک اسکریپت راه اندازی جداگانه منتقل کردیم و شبکه هایی را برای همه پروژه های موجود در آن اضافه کردیم.
پروژه ما یک شبکه دارد و متعادل کننده چندین شبکه با نام پروژه دارد. این می تواند با نام دامنه بیشتر پروکسی کند.
درخواستهای ما از طریق دامنه در پورت 80 ارسال میشوند و در یک گروه کانتینری که این دامنه را ارائه میکند، حل میشوند.
چه مشکلات دیگری وجود داشت؟ این همان چیزی است که همه کانتینرها به صورت پیش فرض به صورت روت اجرا می شوند. این ریشه با میزبان ریشه سیستم نابرابر است.
اما اگر وارد کانتینر شوید، root می شود و فایلی که در این کانتینر ایجاد می کنیم، حقوق ریشه می گیرد.
اگر توسعهدهنده وارد کانتینر شده و دستوراتی را در آنجا ایجاد کرده است که فایلها را تولید میکند، سپس کانتینر را ترک میکند، در این صورت فایلی در فهرست کاری خود دارد که به آن دسترسی ندارد.
چگونه می توان آن را حل کرد؟ میتوانید کاربرانی را که در ظرف هستند اضافه کنید.
وقتی کاربر را اضافه کردیم چه مشکلاتی ایجاد شد؟
هنگام ایجاد یک کاربر، اغلب شناسه گروه (UID) و شناسه کاربر (GID) یکسان نداریم.
برای حل این مشکل در کانتینر از کاربران با شناسه 1000 استفاده می کنیم.
در مورد ما، این با این واقعیت مصادف شد که تقریباً همه توسعه دهندگان از سیستم عامل اوبونتو استفاده می کنند. و در اوبونتو، اولین کاربر دارای شناسه 1000 است.
آیا برنامه ای داریم؟
مستندات Docker را بخوانید. پروژه به طور فعال در حال توسعه است، اسناد در حال تغییر است. دادههایی که دو یا سه ماه پیش دریافت شدهاند کم کم قدیمی میشوند.
برخی از مشکلاتی که ما حل کردیم احتمالاً قبلاً با ابزارهای استاندارد حل شده اند.
بنابراین من می خواهم از قبل جلوتر بروم تا مستقیماً به ارکستراسیون بروم.
یک مثال مکانیزم داخلی Docker به نام Docker Swarm است که از جعبه خارج می شود. من می خواهم چیزی را بر اساس فناوری Docker Swarm اجرا کنم.
ظروف تخم ریزی کار با کنده ها را ناخوشایند می کند. اکنون سیاهههای مربوط جدا شده اند. آنها در ظروف پراکنده هستند. یکی از وظایف این است که از طریق رابط وب به لاگ ها دسترسی راحت داشته باشید.
منبع: www.habr.com