همه‌ی آن چیزی که باید در مورد داکرفایل بدانید.

Dockerfile
Dockerfile

تو این مستند در مورد نحوه‌ی نوشتن داکرفایل می‌خواهیم صحبت کنیم و اینکه چطور می‌توان یک داکرفایل نوشت و از روی آن ایمیج آماده کرد.

ابتدا چند تا نکته‌ی مهم:

  • داکرفایل بهترین روش برای آماده‌ کردن ایمیج‌ می‌باشد.
  • داکرفایل یک فایل متنی است که تمام مراحل آماده‌سازی ایمیج داخل آن قرار داده می‌شود.
  • با استفاده از داکرفایل می‌توان فرآیند ایجاد ایمیج را به صورت خودکار انجام داد.
  • کار با داکرفایل بسیار ساده می‌باشد و به راحتی می‌توان با استفاده از آن ایمیج‌های مورد نیاز را آماده کرد.
  • با استفاده از دستور docker build می‌توان از روی داکرفایل یک ایمیج داکر آماده کرد.
  • فرقی نمی‌کند که سینتکس‌های داکرفایل را با حروف بزرگ بنویسید و یا کوچک اما بهتر است که UPPERCASE باشد تا با مابقی موارد داکرفایل تفکیک شود. یعنی اینکه داکرفایل case-sensitive نیست.
  • حتما برای ادیتور خودتون Add-on لازم رو نصب کنید که سینتکس‌های مربوط به داکرفایل رو برای شما highlighting کند تا کار با آن ساده‌تر باشد. بسته به ایدتور مورد استفاده شما روش‌های مختلفی وجود دارد.
  • اگر از داکرفایل استفاده کنید به خوبی می‌توانید Version Tracking را رعایت کنید و تمام نسخ ایمیج‌های خود را داشته باشید و هر زمان که لازم بود به یکی از آنها رجوع کنید.
  • با استفاده از # می‌توان در داکرفایل کامنت قرار داد.
  • با استفاده از دستور docker history می‌توان تمام اقدامات انجام شده بر روی ایمیج را مشاهده کنید. در اصل تمام مراحل داکرفایل را می‌توانید مشاهده کنید.
dockerfile
dockerfile

دستورالعمل‌های داکرفایل:

در ادامه دستورالعمل‌های (Syntax) داکرفایل توضیح داده می‌شود.

دستورالعمل FROM:

همواره یک داکرفایل با FROM آغاز می‌شود. تنها دستورالعملی که می‌تواند جلوتر از FROM باشد ARG می‌باشد که در ادامه توضیح داده خواهد شد. با استفاده از FROM می‌توان Base Image را مشخص کرد که مابقی موارد بر روی اون ایمیج انجام خواهد شد. می‌توان چند تا FROM در یک داکرفایل داشت و از همه‌ی آنها به عنوان Base Image استفاده می‌کند. به مثال زیر توجه کنید.

ARG  CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD  /code/run-app

FROM extras:${CODE_VERSION}
CMD  /code/run-extras

همان‌طور که مشاهده می‌کنید از دو تا base image استفاده شده است و تنها دستورالعملی که قبل from قرار گرفته است ARG می‌باشد.

دستورالعمل RUN:

همان دستورالعمل‌های اجرای داخل shell Linux و یا cmd windows می‌باشند. با هر RUN یک لایه ایمیج بر روی base image ایجاد می‌شود و در انتهای آن commit انجام می‌شود و یک لایه‌‌ی جدید شامل تمام تغییرات و موارد اجرایی دستور RUN ایجاد می‌شود. می‌توان در دستور RUN مشخص کرد که از چه shell استفاده نماید. هر لایه‌ای که ایجاد خواهد شد همواره کش می‌شود تا کلا فرآیند build با سرعت بیشتری پیش برود. اگر نیاز بود که بدون کش کردن این فرآیند انجام شود می‌توانید از آپشن no-cache-- استفاده نمایید. اگر ایمیج شما ۱۰ لایه باشد و در ساختن آن در لایه ۹ اختلالی ایجاد شود با استفاده از کش ۸ لایه قبلی مجدد ساخته نمی‌شود و این موضوع در سرعت ساختن ایمیج اهمیت فراوانی خواهد داشت.

دستورالعمل CMD:

این دستورالعمل دارای ۳ فرم استفاده می‌باشد.

فرم اول: دستورالعمل اجرایی به همراه پارامتر اول و پارامتر دوم که این روش بهترین نوع CMD است.

فرم دوم: پارامتر اول و پارامتر دوم که فقط پارامترها را ایجاد می‌کند.

فرم سوم: دستورات کامند لاین استفاده شود به همراه پارامتر اول و پارامتر دوم که به صورت خط فرمان می‌باشد.

شما می‌توانید یک CMD در داکرفایل خود داشته باشید اما اگر بیش از آن داشته باشید تنها آخرین CMD اجرا خواهد شد. هدف اصلی CMD این است که دستورالعمل اجرایی پیش‌فرض کانتینر را ایجاد کند. اگر این موضوع انجام نشود می‌بایست با استفاده از ENTRYPOINT دستورالعمل اجرایی کانتینر را ایجاد نمایید.

دقت کنید که CMD را با RUN اشتباه نکنید. RUN دستورات اجرایی را داخل ایمیج انجام داده و نتایج آن را commit می‌کند اما دستورات CMD حین ساخت ایمیج انجام نمی‌شود و در زمان راه‌اندازی ایمیج و استفاده از آن به عنوان کانتینر انجام می‌گردد.

دستورالعمل LABEL:

با استفاده از این دستورالعمل metadata به ایمیج اضافه می‌کنند. یعنی به ایمیج اطلاعات اضافه می‌کنند. هر لیبل به صورت key-value می‌باشد. با استفاده از دستور docker inspect می‌توان لیبل‌های یک ایمیج را مشاهده کرد.

به چند مثال توجه کنید.

LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."

دستورالعمل MAINTAINER:

استفاده از این دستورالعمل دیگه منسوخ شده است اما مورد استفاده از آن این بود که نویسنده‌ی داکرفایل یعنی کسی که آن را آماده کرده است را مشخص نماید. در نسخه‌های جدید از لیبل برای مشخص کردن نویسنده‌ی داکرفایل استفاده می‌کنند. در مثال زیر لیبل مربوط به نویسنده‌ی داکرفایل آورده شده است.

LABEL maintainer="DockerMe.ir <<rafiee1001@gmail.com>>"

دستورالعمل EXPOSE:

با استفاده از این دستورالعمل کانتینر در زمان اجرای خود این پورت شبکه را listen می‌کند. می‌توانید TCP و یا UDP بودن آن را نیز مشخص نمایید. expose کردن یک پورت در کانتینر به منزله‌ی Publish کردن آن نمی‌باشد. به صورت زیر می‌توان پورت‌ها را در داکرفایل expose کرد. برای Publish کردن نیاز است که شما کانتینر را اجرا کرده و با آپشن p- پورت آن را publish کنید.

EXPOSE 80/tcp
EXPOSE 80/udp

دستورالعمل ENV:

با این دستورالعمل می‌توان در داکرفایل environment variables تعریف کرد و هر زمان که نیاز بود از آن در داکرفایل استفاده کرد. به این صورت variable_name$ یا {variable_name}$ می‌توان از آن استفاده کرد. متغیر‌ها به صورت key-value تنظیم می‌شوند. می‌توان به صورت یک env در هر خط آنها را تعریف کرد یا اینکه در یک خط تمام key-value های مورد نیاز را تعریف کرد. به مثال زیر توجه کنید.

نیاز است تا ۳ عدد متغیر در داکرفایل تعریف کنیم. می‌توانیم در یک ENV آنها را بنویسیم.

ENV myName="John Doe" myDog=Rex\ The\ Dog \
    myCat=fluffy

یا به صورت ۳ تا ENV آنها را تعریف کنیم.

ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat fluffy

دستورالعمل ADD:

با استفاده از این آپشن می‌توان فایل و یا دایرکتوری رو از روی هاست یا به صورت URL از یک لینک به ایمیج خود اضافه کرد. پترن استفاده از آن به صورت زیر می‌باشد.

ADD [--chown=<user>:<group>] <src>... <dest> 
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"] 

آپشن [<chown=<user>:<group--] تنها برای کانتینر‌های Linux قابل استفاده می‌باشد و برای Windows این آپشن کار نمی‌کند. از این آپشن می‌توان به خوبی برای مشخص کردن سطح دستور کاربر و گروه به فایل استفاده کرد. اگر کاربر و گروهی را که انتخاب می‌کنید داخل کانتینر و در مسیر‌های etc/passwd/ و etc/group/ نباشد فرآیند ساخت ایمیج خطا داده و متوقف می‌شود.

اگر از URL استفاده می‌کنید که نیاز به Authentication دارد می‌بایست از RUN به همراه wget و یا curl استفاده کنید که بتوانید کاربر و پسورد آن را وارد کنید. اما اگر بدون Authentication می‌باشد می‌توانید از دستورالعمل ADD استفاده کنید.

اگر در مقصد دایرکتوری که فایل به آن منتقل می‌شود وجود نداشته باشد آن فایل را در مقصد ایجاد می‌کند. با استفاده از ADD می‌توان فایل‌های فشرده‌ی tar را نیز منتقل کرد.

دستورالعمل COPY:

این دستورالعمل همانند دستورالعمل ADD می‌باشد با این تفاوت که نمی‌تواند از URL دریافت کند و بعد اینکه tar را پشتیبانی نمی‌کند اما معمولا برای جابجایی فایل و دایرکتوری از هاست به ایمیج از این دستورالعمل استفاده می‌کنند.

dockerfile
dockerfile

دستورالعمل ENTRYPOINT:

با استفاده از این دستورالعمل می‌توان فایل اجرایی و یا همان پروسه‌ی لازم را در کانتینر اجرا کرد. نکته‌ی مهم اینکه در زمان راه‌اندازی کانتینر با دستور run می‌توان entrypoint داخل ایمیج را نیز با آپشن مخصوص آن override کرد. با استفاده از entrypoint می‌توان یک پروسه را در foreground کانتینر اجرا کرد و اون پروسه باعث می‌شود که کانتینر ران بماند و عملکرد خود را انجام دهد.

معمولا برای entrypoint یک اسکریپت آماده می‌کنند که تمام موارد مد نظر را در کانتینر انجام می‌دهد. با استفاده از entrypoint پروسه‌ها به صورت pid 1 راه‌اندازی می‌شوند که این موضوع در برخی از سرویس‌ها اهمیت فراوانی دارد.

dockerfile
dockerfile

دستورالعمل‌های CMD و ENTRYPOINT:

  • هر دوتای این دستورالعمل‌ها برای اجرا کردن یک کامند یا پروسه در هنگام ران‌ شدن کانتینر هستند.
  • در داکرفایل باید مشخص شود که CMD و یا ENTRYPOINT چه چیزی باشد.
  • همواره ENTRYPOINT باید به صورت اجرایی در داخل کانتینر معرفی شود.
  • معمولا از CMD به عنوان راهی برای مشخص کرد ورودی لازم برای دستور اجرایی ENTRYPOINT داخل کانتینر استفاده می‌شود.
  • معمولا CMD با ورودی‌های کانتینر در حال کار جایگزاری خواهد شد.

گاهی پیش می‌آید که این موضوع باعث اشتباه کاربران می‌شود از این رو توجه شما رو به جدول زیر جلب می‌کنم.

CMD / ENTRYPOINT combinations
CMD / ENTRYPOINT combinations

یک نکته‌ی مهم دیگه اینکه اگر CMD داخل base image تنظیم شده باشد ENTRYPOINT مقدار آن را خالی می‌کند در این سناریو CMD در ایمیج فعلی دارای مقدار خواهد شد.

دستورالعمل VOLUME:

والیوم یک نقطه‌ی اتصال با نام مشخص در داکرفایل ایجاد می‌کند. این مقدار می‌تواند به صورت JSON یا به صورت String باشد. چند تا نکته‌ی مهم:

  • والیوم در ویندوز بیس کانتینرها یکی از دو مسیر غیر از درایور C و یا اینکه فایل وجود نداشته باشد و یا کلا خالی باشد انجام می‌شود.
  • اگر تغییری در داخل داکرفایل و والیوم آن بعد از ساختن ایمیج اتفاق بیافتد اون تغییر از دست می‌رود.
  • به دلیل امکان قابل حمل بودن ایمیج‌ها والیوم قسمت هاست داخل داکرفایل کانفیگ نمی‌شود. زیرا ایمیج در هاست‌های مختلف می‌بایست اجرا شود از این رو این قسمت به ازای هر هاست بر روی آن پیکربندی می‌شود.

دستورالعمل USER:

با استفاده از این دستورالعمل می‌توان برای ایمیج خود در زمان اجرا User یا UID و به صورت اختیاری Group یا GID تنظیم کرد. این موضوع در کانتینر‌هایی که بیس آنها ویندوز می‌باشد متفاوت بوده و با دستور net user می‌توانند کاربر داخل ایمیج را مشخص کنند.

دستورالعمل WORKDIR:

با این دستورالعمل می‌توان دایرکتوری که تمام دستورات بعدی در آن ران می‌شود را مشخص کرد. در ضمن بعد از راه‌اندازی کانتینر همواره پروسه‌ی جاری در همان مسیر WORKDIR اجرا خواهد شد. از این دستورالعمل می‌توان به دفعات در داکرفایل استفاده کرد. این دستورالعمل می‌تواند از متغیرهای محلی نیز استفاده کند. به مثال زیر توجه کنید.

ENV DIRPATH /path 
WORKDIR $DIRPATH/$DIRNAME 
RUN pwd

پاسخ این مثال path/$DIRNAME/ می‌باشد.

دستورالعمل ARG:

از این دستورالعمل برای پاس دادن متغیر در زمان ساختن ایمیج استفاده می‌شود. برای استفاده از آن باید از آپشن <build-arg <varname>=<value-- در زمان ساختن ایمیج استفاده کرد. اگر در زمان ساخت ایمیج متغییر برای آن در نظر گرفته نشود این موضوع رو تحت یک اخطار اطلاع رسانی می‌کند البته این متغیر می‌تواند همواره یک مقدار پیش‌فرض نیز داشته باشد. اگر در زمان ساخت ایمیج مقدار متغیر در نظر گرفته نشود از مقدار پیش‌فرض که در داکرفایل وجود دارد استفاده می‌کند. معمولا متغیرهایی که با دستورالعمل ENV ایجاد می‌شوند دستورالعمل‌های ARG را جایگذاری می‌کنند. داکر به صورت پیش‌فرض یک‌سری متغییرهای ARG از پیش تعریف شده دارد که شما بدون معرفی آنها توسط ARG می‌توانید در داکرفایل از آنها استفاده کنید.

  • HTTP_PROXY
  • http_proxy
  • HTTPS_PROXY
  • https_proxy
  • FTP_PROXY
  • ftp_proxy
  • NO_PROXY
  • no_proxy

دستورالعمل ONBUILD:

برای زمانی استفاده می‌شود که بخواهیم از این ایمیج به عنوان پایه‌ی ایمیج‌های دیگه استفاده کنیم و موارد آن در زمانی که بعنوان base image استفاده می‌شود فعال می‌گردد.

دستورالعمل STOPSIGNAL:

با استفاده از این دستورالعمل می‌توان سیگنال خروج کانتینر را مشخص کرد.

دستورالعمل HEALTHCHECK:

با استفاده از این دستورالعمل به داکر می‌گوییم که چطور این کانتینر را تست کند. داکر در یک حلقه‌ی بینهایت کانتینر را مدام تست و بررسی می‌کند. بعد از فعال کردن این دستور‌العمل در کانتینر ۳ حالت خواهد داشت. حالت اول که ابتدای راه‌اندازی کانتینر است به صورت starting می‌باشد و بعد از راه‌اندازی آن را بررسی می‌کند که اگر اوکی بود آن را healthy و اگر نتیجه‌ی بررسی درست نبود آن را unhealthy قرار می‌دهد. برای اینکه از این قابلیت در ایمیج خود استفاده کنید نیاز است که برخی از کانفیگ‌ها انجام شود.

  • --interval=DURATION (default: 30s)
  • --timeout=DURATION (default: 30s)
  • --start-period=DURATION (default: 0s)
  • --retries=N (default: 3)

بعد از راه‌اندازی کانتینر و گذشت اولین بازه‌ی زمانی پروسه‌ی health check انجام می‌شود. اگر در بازه‌ی زمانی تست انجام شد و زمان timeout گذشت نتیجه تست fail می‌شود و حالت کانتینر به unhealthy تغییر می‌کند.

دستورالعمل SHELL:

با استفاده از این دستورالعمل می توان SHELL پیشفرض را تغییر داد. shell پیش‌فرض برای لینوکس ["/bin/sh", "-c"] و برای ویندوز ["cmd", "/S", "/C"] می‌باشد. می‌توان از shellهایی مانند zsh, csh, powershell و موارد دیگه استفاده کرد.

فایل dockerignore.:

همانند gitignore برای داکرفایل عمل می‌کند و مواردی که در پوشه داکرفایل می‌باشد اما در داکرفایل مورد استفاده قرار نمی‌گیرد را در آن لیست می‌کنند. همواره باید در root دایرکتوری خود داکرفایل قرار داشته باشد. داخل این فایل با استفاده از خط جدید جداسازی صورت می‌گیرد. در ادامه یک نمونه dockerignore را مشاهده می‌کنید.

1    # comment
2    */temp*
3    */*/temp*
4    temp?

طی مثال بالا برای هر خط این موارد انجام می‌شود.

خط ۱: این خط به صورت کامل نادیده گرفته خواهد شد

خط ۲: کلا هر دایرکتوری و یا فایلی که داخل اسم آن temp باشد نادیده گرفته می‌شود. مثلا temporary.txt و یا دایرکتوری‌های که نام آنها با temp شروع شود نادیده گرفته می‌شود. این موضوع فقط در دایرکتوری اصلی و یک subdirectory آن اعمال می‌شود.

خط ۳: همانند خط ۲ اما در دو مرحله subdirectory آن این کار را انجام می‌دهد.

خط ۴: در دایرکتوری اصلی هر فایل و یا دایرکتوری که با temp و یک حرف اضافه تر آن باشد را نادیده می‌گیرد. به عنوان مثال tempt و یا tempd را نادیده می‌گیرد.

نکته‌ی آخر:

هر زمان که خواستید از ایمیجی استفاده کنید حتما قبلش داکرفایل آن را با دقت مطالعه کنید و اگر مشکل خاصی در داکرفایل وجود نداشت از روی آن ایمیج خود را بسازید و از آن استفاده کنید.

منبع


آموزش داکر و پلتفرم
آموزش داکر و پلتفرم
https://dockerme.ir/