مشاور زیرساخت. موسس سایت آموزشی DockerMe.ir
چطور بتونیم کامپوزفایل بنویسیم.
خوب امروز در مورد نحوهی نوشتن کامپوز فایل میخوایم صحبت کنیم.
داکر کامپوز چیه و چی کار میکنه؟
همانطور که قبلا در موردش صحبت کردیم داکر کامپوز ابزاری است که میتوان با استفاده از آن چند تا کانتینر را راهاندازی کرد و تمام موارد مربوط به راهاندازی آنها را در آن لحاظ کرد. داکر کامپوز با استفاده از یک YAML فایل تمام موارد مربوط به راهاندازی سرویس ما را دریافت و بر اساس آن سرویس که میتواند شامل چندین کانتینر باشد را با یک دستور راهاندازی میکند. از داکر کامپوز میتوان در تمام محیطهای کاری اعم از production, staging, development, testing و محیطهای CI/CD استفاده کرد.
برخی از مزایای استفاده از داکرکامپوز:
- با استفاده از آن میتوان بر روی یک هاست چند تا محیط ایزوله با یکدیگر داشت.
- در زمان ایجاد تغییر کانتینرها را مجدد ایجاد نماید.
- با استفاده از متغیرهای که تعریف میشود میتوان سرویس را در محیطهای مختلف پیادهسازی کرد.
- اطلاعات کانتینرها را حسب نیاز بر روی volumeهایی که ایجاد میکند قرار دهد.
- داکر کامپوز میتواند به خوبی با سرویسهای CI/CD ادغام شود و تمام موارد مورد نیاز را به صورت خودکار انجام دهد.
سناریوی پیادهسازی سرویس:
معمولا این سناریو در راهاندازی سرویسها انجام میشود. ابتدا داکرفایل برای ایجاد ایمیجها آماده میشود. قبلا در این اینجا به صورت کامل در مورد ایجاد داکرفایل صبحت کردیم. سپس با توجه به نیاز موجود برای راهاندازی سرویس و ارتباطات و عملکرد آنها با هم یک کامپوز فایل آماده میگردد. سپس با استفاده از دستورات داکرکامپوز و با توجه به کامپوز فایل سرویس با تمام شرایط مد نظر راهاندازی و در اختیار قرار میگیرد. میتوان برای کل سرویس و یا هر جزئی از آن نیز تست نوشت و تمام موارد را تست کرد.
حالا ما در این مستند گریزی هر چند کوتاه اما مفید بر نگارش کامپوز فایل خواهیم داشت.
دستورالعملهای کامپوزفایل:
در ادامه در مورد دستورالعملهای کامپوز فایل صحبت میکنیم. نسخهی ۳ کامپوزفایل بررسی خواهد شد که در زمان نگارش این داکیومنت جدیدترین نسخهی آن میباشد. در مورد هر دستورالعمل به اختصار صحبت میشود و اطلاعات بیشتر را بهتر است در اینجا مطالعه نمایید. شما میتوانید در اینجا در مورد نسخههای مختلف کامپوزفایل و ارتباط آنها با نسخهی سرویس داکر را نیز بررسی کنید.
دستورالعمل services:
تنها دستورالعملهای services, networks و volumes به صورت مسیر پیشفرض در کامپوزفایل میباشند. البته دستورالعملهای configs و secrets نیز از سری هستند اما آنها تنها در قسمت swarm کاربرد دارند. همانطور که میدونید yaml به جای دستورالعملها حساس میباشد از این رو در زمان ایجاد yaml file میبایست به موقعیت مکانی تمام دستورالعملها دقت کرد زیرا اگر در جای درستی قرار نگرفته باشند خطا داده و فایل شما اجرا نخواهد شد. در ضمن پسوند فایل میتواند yml. یا yaml. باشد و هر دو تای آن درست میباشد.
زمانی که یک کامپوزفایل اجرا میشود همانند این است که با دستورات مختلف ایمیج دریافت و یا ساخته شود و یا اینکه کانتینر با استفاده از تنظیماتی که قرار داده شده است ایجاد شود و یا اینکه شبکه با کانفیگ مشخص ایجاد شود. در واقع تمام آپشنها و دستورالعملهایی که در کامپوزفایل مورد استفاده قرار میگیرد همان دستورات داکر است که در حال استفاده میباشد.
دستورالعمل build:
با استفاده از این دستورالعمل میتوان تنظیمات مربوط به ساخت ایمیج در زمان اجرای سرویس را داد. میتوان مسیر و اسم داکرفایل را مشخص کرد و آپشنهای زمان build همانند arg را در آن قرار داد و یا اینکه ایمیج با چه نامی ساخته شود. دستورالعملهای مهم زیر مجموعهی build عبارتند از:
دستورالعمل context: مسیری که داکرفایل در آنجا قرار دارد و یا آدرس ریپوی git آن را مشخص میکند.
دستورالعمل dockerfile: داکرفایل اگر با نام Dockerfile داخل مسیری که اشاره شد وجود ندارد و نام دیگری دارد با این آپشن مشخص میکند.
دستورالعمل args: دقیقا همان arg داخل داکرفایل است که میتوان در زمان ساخت ایمیج آن را قرار داد.
دستورالعمل labels: در زمان ساخت ایمیج به آن لیبل داده میشود. (از نسخهی ۳.۳ به بعد)
دستورالعمل command: دستورالعمل پیشفرض کانتینر را جایگذاری میکند.
دستورالعمل container_name:
اسم کانتینر را مشخص میکند. اگر اسم برای کانتینر انتخاب نشود ترکیبی از اسم سرویس به همراه دایرکتوری آن قرار میدهد.
دستورالعمل depends_on:
این دستورالعمل بسیار کاربردی میباشد و اگر بین سرویسهای داخل کامپوز فایل اولویت زمانی در راهاندازی اهمیت داشته باشد با استفاده از این دستورالعمل میتوان سرویسی را به سرویس دیگری وابسته کرد. در تصویر زیر برای اینکه سرویس web راهاندازی شود نیاز است تا ابتدا سرویس db و سرویس redis راهاندازی شود. تازمانی که هر دو سرویس راهاندازی نشوند سرویس web راهاندازی نخواهد شد.
دستورالعمل deploy:
فقط در نسخهی ۳ کار میکند. میتوان با استفاده از آن موارد مربوط به پیادهسازی سرویس را مشخص کرد. این دستورالعمل تنها در زمان استفاده از swarm و با دستورالعمل docker stack deploy قابل استفاده میباشد. اگر با دستور docker compose استفاده شود این قسمت به صورت کلی نادیده گرفته میشود. حالا بعدا در مستندی به صورت کامل swarm و نحوهی کار با آن و آپشنهای کنار آن رو توضیح میدهیم.
برخی از آپشنهای زیرمجموعهی این دستورالعمل توضیح داده میشود.
دستورالعمل endpoint_mode: تنها در نسخهی ۳.۳ قابل استفاده است. برای زمانی که کاربر از بیرون کلاستر بخواهد به آن متصل شود کاربرد دارد. دو حالت دارد که در ادامه توضیح داده میشود:
- حالت vip: کلایت تنها یک ip به صورت VIP مشاهده میکند و تمام درخواستهای او به سمت همان IP میرود و کاربر اصلا متوجه نمیشود تعداد سرویسهای پشت آن نخواهد شد. به صورت پیشفرض این روش همواره تنظیم شده است.
- حالت dnsrr: به صورت round-robin و از طریق DNS انجام میشود و در این روش از تک VIP استفاده نمیشود. در این روش به ازای هر نام تعداد زیادی IP قرار داده میشود و به صورت round-robin به یکی از آنها متصل میشود.
دستورالعمل mode: اگر به صورت global تنظیم شود به ازای هر نود در کلاستر swarm یک کانتینر ایجاد خواهد شد. به صورت پیشفرض replicated تنظیم شده است که به تعداد مشخصی از کانتینر دیپلوی میشود.
دستورالعمل replicas: با استفاده از آن تعداد مشخص کانتینر رو برای ایجاد کردن مشخص میکند.
دستورالعمل resources: با استفاده از این دستورالعمل میتوان منابعی که این کانتینر استفاده میکند را مشخص و محدودیتهای مربوط به آن را تنظیم نمود. به مثال زیر توجه کنید.
دستورالعمل restart_policy: تنظیمات مربوط به restart کانتینر میباشد. این کانفیگ تنظیمات مربوط به restart را جایگزین میکند. در مثال زیر زمانی که موضوعی باعث fail کانتینر شود با ۵ ثانیه تاخیر ۳ بار تلاش میکند تا کانتینر را ران کند.
دستورالعمل dns و dns_search:
با استفاده از این دستور العملها میتوان برای کانتینر DNS تنظیم کرد. به مثالهای زیر توجه کنید.
dns: 8.8.8.8
dns:
- 8.8.8.8
- 9.9.9.9
dns_search: example.com
dns_search:
- dc1.example.com
- dc2.example.com
دستورالعمل entrypoint:
با استفاده از آن دستورالعمل entrypoint داخل ایمیج را در این سرویس جایگذاری میکند و این به جای آن اجرا میشود. به صورت زیر میتوان از آن استفاده کرد.
entrypoint: /code/entrypoint.sh
entrypoint:
- php
- -d
- zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
- -d
- memory_limit=-1
- vendor/bin/phpunit
دستورالعمل env_file:
اضافه کردن متغیرهای محلی با استفاده از فایل که میتواند شامل یک متغیر و یا لیستی از آنها باشد. به مثالهای زیر توجه کنید.
env_file: .env
env_file:
- ./common.env
- ./apps/web.env
- /opt/secrets.env
در فایلهای متغیرها رو به صورت VAR=VAL میبایست قرار داد. اگر از # استفاده شود به صورت comment خواهد بود و خط خالی نیز نادیده گرفته میشود.
# Set Rails/Rack environment
RACK_ENV=development
اگر نیاز باشد متغیری تنها در زمان build مورد استفاده قرار گیرد میبایست از arg استفاده کرد. اگر چند تا فایل متغیر باهم لود بشن و داخل آنها متغیر یکسان وجود داشته باشد همواره متغیرهای فایل آخر مرجع میباشد. یعنی آخرین مقداری که متغیر گرفته باشد معتبر است. نکتهی مهمی است که بهش دقت کنید.
دستورالعمل environment:
از این دستورالعمل برای زمانی که بخواهیم یک یا چند متغیر را در کانتینر مقداردهی کنیم استفاده میکنیم. تفاوت در این است که تمام متغیرها داخل خود کامپوزفایل تعریف خواهد شد و فایل دیگهای لود نخواهد شد. به هر دو صورت زیر از آن استفاده میشود.
environment:
RACK_ENV: development
SHOW: 'true'
SESSION_SECRET:
environment:
- RACK_ENV=development
- SHOW=true
- SESSION_SECRET
دستورالعمل expose:
برای expose کردن پورت داخل کانتیر استفاده میشود. این به معنای در دسترس قرار دادن آن پورت در داکرهاست نمیباشد. به آن عمل publish میگویند که دستورالعمل مخصوص خودش را دارد. معمولا از expose برای ارتباط داخلی بین کانتینرها و زمانی که آنها بین هم link میشوند استفاده میشود.
expose:
- "3000"
- "8000"
حواستون به تفاوت بین expose و publish باشه که این دو تا باهم متفاوت هستند. اینجا در موردشون صحبت کردیم.
دستورالعمل external_links:
برای زمانی که نیاز است تا با کانتینری خارج از این docker-compose.yml ارتباط برقرار کرد استفاده میشود. به صورت CONTAINER:ALIAS نیز استفاده میشود. به مثال زیر توجه کنید.
external_links:
- redis_1
- project_db_1:mysql
- project_db_1:postgresql
دستورالعمل extra_hosts:
با استفاده از آن میتوان داخل etc/hosts/ کانتینر اطلاعاتی که لازم داریم را وارد کنیم و اصتلاحا به آن host اضافه کنیم.
extra_hosts:
- "somehost:162.242.195.82"
- "otherhost:50.31.209.229"
دستورالعمل healthcheck:
میتوان وضعیت سلامت سرویس داخل کانتینر رو بررسی کرد که دارای ۳ تا وضعیت میباشد که قبلا در داکرفایل آنها را توضیح دادیم. تمام مواردی که در این دستورالعمل مورد استفاده قرار میگیرد دقیقا همانند داکرفایل میباشد با این تفاوت که در داکرفایل داخل ایمیج این موارد تنظیم میشد و اینجا برای خود کانتینر تنظیم میگردد.
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 1m30s
timeout: 10s
retries: 3
start_period: 40s
در صورتی که نیاز داشته باشید که healthcheck مربوط به ایمیج را نیز غیر فعال کنید میتواند از دستور زیر استفاده کنید.
healthcheck:
disable: true
دستورالعمل image:
ایمیج مورد استفاده را مشخص میکند و کانتینر از روی این ایمیج آماده میشود. البته میتوان با استفاده از دستورالعمل build ایمیج مورد استفاده را از روی داکرفایل نیز ایجاد کرد.
دستورالعمل labels:
با استفاده از آن میتوان metadata کانتیرها را تغییر داد. گاهی با استفاده از این اطلاعات که به کانتینرها اضافه میشود میتوان سرویسهای مختلفی را دریافت کرد. برای همین این موضوع اهمیت زیادی دارد.
دستورالعمل logging:
با استفاده از آن میتوان سرویس logging مربوط به کانتینر را پیکربندی کرد. همانطور که میدانید و قبلا نیز توضیح داده شد سرویس logging داخل داکر و برای کانتیرها دارای درایورهای مختلفی میباشد از این رو میتوان نوع درایور و تنظیمات آن را در این دستورالعمل مشخص کرد. به مثال زیر توجه کنید.
logging:
driver: syslog
options:
syslog-address: "tcp://192.168.0.42:123"
به صورت پیشفرض ۳ تا درایور برای لاگ کانتیرهای داکر وجود دارد که عبارت است از:
driver: "json-file"
driver: "syslog"
driver: "none"
که درایور json-file به صورت پیشفرض میباشد و تمام آن را میتوان در دستور docker-compose logs مشاهده کرد. یه نکتهی مهم اینکه این آپشن و دستورالعمل وابسته به کانفیگ مربوط به logging driver سرویس داکر شما میباشد و درایورهایی رو میتوانید استفاده کنید که در آنها تعریف کرده باشید.
دستورالعمل network_mode:
برای مشخص کردن شبکه کانتینر مورد استفاده قرار میگیرد. برای زمانی کاربرد دارد که شما بخواهید از modeهای مختلفی به عنوان مثال host و یا none استفاده نمایید.
دستورالعمل networks:
با استفاده از آن میتوان تنظیمات مربوط به شبکهی کامپوزفایل و کانتینرهای آن را تعیین کرد. این دستورالعمل چند تا زیرمجموعهی مهم دارد که در ادامه توضیح داده میشود.
دستورالعمل aliases: با استفاده از آن برای کانتیرها aliase تعریف میشود و میتوان داخل آن network کانتینر را علاوه بر اسم و id آن با این aliase نیز صدا کرد.
دستورالعمل ipv4_address, ipv6_address: با استفاده از آن میتوان ip به هر کانتیر اختصاص داد.
version: '3'
services:
some-service:
networks:
some-network:
aliases:
- alias1
- alias3
ipv4_address: 172.16.238.10
ipv6_address: 2001:3984:3989::
دستورالعمل pid:
میتوان pid داخل کانیتر را با host یکی کرد که برای این کار از این دستورالعمل استفاده میشود.
دستورالعمل ports:
که با استفاده از آن میتوان پورتها رو از داخل کانتیر به هاست publish کرد. به صورت اختصار به صورت HOST:CONTAINER استفاده میشود. برای مثال پورت ۸۰ کانتیر به پورت ۸۰۸۰ هاست مپ میشود.
ports:
- "8080:80"
میتوان تنها پورت کانتیر را قرار داد که آنگاه سرویس داکر آن را بر روی یکی از رندم پورتهای هاست مپ میکند. و میتوان به صورت اختصاصی مشخص کرد که این پورت بر روی کدام پورت و ip سروس هاست bind شود و یا اینکه در چه پروتکلی قرار داشته باشد. در مثالهای زیر تمام موارد آورده شده است.
ports:
- "3000"
- "3000-3005"
- "8000:8000"
- "9090-9091:8080-8081"
- "49100:22"
- "127.0.0.1:8001:8001"
- "127.0.0.1:5000-5010:5000-5010"
- "6060:6060/udp"
اما به گونهای دیگر نیز پورت را تعریف کرد که دارای توضیحات زیاد و روش طولانی آن میباشد. در مثال زیر پورت ۸۰ داخل کانتینر را به پورت ۸۰۸۰ داخل هاست مپ میکند. این نوع فرمت در نسخه ۳.۲ به بعد میباشد.
ports:
- target: 80
published: 8080
protocol: tcp
mode: host
دستورالعمل restart:
این دستورالعمل برای سیاست restart کانتینر مورد استفاده قرار میگیرد و به صورت پیشفرض برای همهی کانتینرها no میباشد. این دستورالعمل تنها در زمان استفاده غیر swarm کاربرد دارد. اگر از آپشن always استفاده شود همواره بعد از هر اتفاقی حتی اگر کانفیگ کانتینر مشکل داشته باشد مدام تلاش میکند که آن را استارت کند. آپشن on-failure برای زمانی است که به دلیل خطایی کانتینر استاپ شده باشد که آن را مجدد استارت میکند. آپشن unless-stopped که بسیار شبیه always میباشد اما اگر کانتیر به صورت دستی stop شود بعد از restart سرویس داکر کانتیر را استارت نمیکند اما در always این کار را انجام میدهد.
دستورالعمل sysctls:
با استفاده از آن میتوانید آپشنهای مربوط به sysctl داخل کانتیر ایجاد و اجرا کنید. به دو صورت زیر مورد استفاده قرار میگیرد.
sysctls:
net.core.somaxconn: 1024
net.ipv4.tcp_syncookies: 0
sysctls:
- net.core.somaxconn=1024
- net.ipv4.tcp_syncookies=0
دستورالعمل ulimits:
با استفاده از آن آپشنهای مربوط به limit.conf را میتوان در کانتیر تغییر داد و اجازه استفاده بیشتر و بهینهتر از منابع سیستمعامل را به آن داد.
ulimits:
nproc: 65535
nofile:
soft: 20000
hard: 40000
دستورالعمل volumes:
به دو روش یکی قرار دادن بر روی مسیری از دایرکتوری هاست و دیگری ایجاد والیوم با استفاده از درایورهای مختلف میتوان دادههای کانتینر را بر روی هاست ذخیره کرد. در استفاده از والیوم نیز میتوان به صورت مختصر یعنی HOST:CONTAINER استفاده کرد یا به صورت طولانیتر تمام هر قسمت را توضیح داد. در مثال زیر چند نمونه از استفادهی مختصر آن آورده شده است.
volumes:
# Just specify a path and let the Engine create a volume
- /var/lib/mysql
# Specify an absolute path mapping
- /opt/data:/var/lib/mysql
# Path on the host, relative to the Compose file
- ./cache:/tmp/cache
# User-relative path
- ~/configs:/etc/configs/:ro
# Named volume
- datavolume:/var/lib/mysql
معمولا این روش بسیار مرسومتر است و روش توضیح بیشتر آن کمتر استفاده میشود.
دستورالعمل domainname:
میتوان با استفاده از آن domainname را برای کانتینر تعریف کرد.
دستورالعمل hostname:
با استفاده از آن hostname برای کانتینر تعریف میکنیم.
دستورالعمل privileged:
اگر در کانتینر نیاز به سطح دسترسی بیشتری هستیم آن را با privileged اجرا خواهیم کرد. این موضوع نکتهی امنیتی دارد و بهتر است که استفاده نشود.
دستورالعمل user:
کاربر کانتینر در زمان اجرا را مشخص میکند.
دستورالعمل working_dir:
دایرکتوری کاری کانتینر را مشخص میکند.
دستورالعمل Volume configuration reference:
والیومی که در قسمت بالاتر توضیح داده شد مربوط به قسمت سرویس میباشد اما این قسمت برای تعریف والیوم میباشد. این قسمت هم ردیف قسمت سرویس در کامپوز فایل قرار داده میشود. این دستورالعمل شامل چند زیرمجموعه میباشد که عبارتند از:
دستورالعمل driver: با استفاده از آن میتوانیم درایور مربوط به والیوم را مشخص کنیم. به صورت پیشفرض درایور local استفاده میشود.
دستورالعمل driver_opts: با استفاده از این دستورالعمل میتوان لیست آپشنهای مربوط به درایور والیوم را مشخص و تنظیم کرد. به عنوان مثال میتوان برای والیوم خود محدودیت حجم در نظر گرفت.
دستورالعمل external: اگر این آپشن true باشد یعنی والیوم بیرون از کامپوز فایل تعریف میشود و وجود خواهد داشت و باید از آن استفاده کند. معمولا این آپشن مواقعی که از stack استفاده میشود کاربرد دارد.
دستورالعمل labels: با استفاده از آن میتوان metadata والیومها را تغییر داد.
دستورالعمل name: برای کانتینر اسم انتخاب کرد. (از نسخهی ۳.۴ به بعد)
دستورالعمل Network configuration reference:
قبلا درباره network که زیرمجموعه سرویس بود صحبت کردیم. این قسمت هم ردیف سرویس در کامپوز فایل بوده و برای معرفی شبکهی مورد استفاده کاربرد دارد. این دستورالعمل چندین زیرمجموعه دارد که در ادامه به آنها اشاره میشود:
دستورالعمل driver: با استفاده از آن درایور شبکه مورد نظر را مشخص میکند که به صورت پیشفرض bridge میباشد.
دستورالعمل driver_opts: با استفاده از آن میتوانیم آپشنهای مربوط به درایور را مشخص کنیم که این موارد به صورت key-value تنظیم میگردد.
دستورالعمل attachable: میتوان یک کانتینر را به شبکهی overlay متصل کرد.
دستورالعمل enable_ipv6: نسخهی ipv6 را برای این شبکه فعال میکند.
دستورالعمل ipam: برای اینکه بتوان درایور ipam را تغییر داد از آن استفاده میشود. به عنوان مثال میتوان subnet و .. را تغییر داد و آنها را کانفیگ کرد.
دستورالعمل internal: به صورت پیشفرض تنظیم شده است. به معنای اینکه شبکه داخل کامپوزفایل ایجاد می شود و داخل آن استفاده میشود.
دستورالعمل external: به معنای آن میباشد که این شبکه بیرون از کامپوز فایل تعریف شده است و میبایست قبل از اجرای کامپوز فایل آن را ایجاد نمایید.
دستورالعمل labels: با استفاده از آن میتوان metadata مربوط به شبکه را کاملتر کرد.
دستورالعمل name: برای شبکهای که ساخته میشود اسم انتخاب میکند.
نحوهی استفاده از متغیرها در خود کانفیگ فایل:
در زمان آماده سازی کامپوز فایل میتوان برخی از مقادیر را به صورت متغیر تعریف کرد. نحوهی استفاده از متغییرها به صورت زیر میباشد.
$VARIABLE
${VARIABLE}
تمام این متغیرها و مقادیر آنها در یک env. فایل باید باشد تا در کامپوز فایل مورد استفاده قرار گیرد.
برخی از موارد دیگه همانند configs و secrets باقیمانده است که آنها را در زمانی که میخواهیم از swarm استفاده کنیم توضیح خواهیم داد.
منبع
مطلبی دیگر از این انتشارات
خیلی ساده رجیستری خودتون رو داشته باشید
مطلبی دیگر از این انتشارات
توضیح دستورات داکر – این قسمت docker info
مطلبی دیگر از این انتشارات
توضیح دستورات داکر – این قسمت docker images