آموزش استفاده از Docker Exec برای دسترسی و مدیریت کانتینرها

آموزش استفاده از Docker Exec برای دسترسی و مدیریت کانتینرها

Docker یک ابزار کانتینری‌سازی است که به توسعه‌دهندگان کمک می‌کند کانتینرهای لینوکسی قابل‌حمل و سازگار ایجاد و مدیریت کنند.

هنگام توسعه یا استقرار کانتینرها، اغلب نیاز دارید که داخل یک کانتینر در حال اجرا نگاه بیندازید تا وضعیت فعلی آن را بررسی کرده یا مشکلی را دیباگ کنید. برای این منظور، Docker دستور docker exec را ارائه می‌دهد تا برنامه‌هایی را در کانتینرهای در حال اجرا اجرا کنید.

در این آموزش، با دستور docker exec و نحوه استفاده از آن برای اجرای دستورات و دریافت یک شل تعاملی در یک کانتینر Docker آشنا خواهیم شد.

پیش‌نیازها

این آموزش فرض می‌کند که Docker قبلاً نصب شده و کاربر شما اجازه اجرای دستورات Docker را دارد. اگر نیاز دارید دستورات Docker را به عنوان کاربر ریشه (root) اجرا کنید، لطفاً به یاد داشته باشید که قبل از دستورات این آموزش sudo اضافه کنید.

برای اطلاعات بیشتر درباره استفاده از Docker بدون دسترسی sudo، لطفاً به بخش «اجرای دستور Docker بدون sudo» در آموزش «نحوه نصب Docker» مراجعه کنید.

راه‌اندازی یک کانتینر آزمایشی

برای استفاده از دستور docker exec، نیاز به یک کانتینر در حال اجرای Docker دارید. اگر در حال حاضر کانتینری ندارید، می‌توانید با استفاده از دستور زیر یک کانتینر آزمایشی راه‌اندازی کنید:

docker run -d --name container-name alpine watch "date >> /var/log/date.log"

این دستور یک کانتینر جدید از ایمیج رسمی Alpine ایجاد می‌کند. این یک ایمیج کانتینری لینوکسی محبوب است که از Alpine Linux استفاده می‌کند؛ توزیعی کم‌حجم و مینیمال از لینوکس.

ما از گزینه -d برای جدا کردن کانتینر از ترمینال و اجرای آن در پس‌زمینه استفاده می‌کنیم. --name container-name نام کانتینر را container-name قرار می‌دهد. می‌توانید هر نامی را به دلخواه وارد کنید یا این قسمت را حذف کنید تا Docker به‌طور خودکار یک نام یکتا تولید کند.

در ادامه alpine را داریم، که مشخص می‌کند از چه ایمیجی برای کانتینر استفاده شود.

در نهایت، watch "date >> /var/log/date.log" دستوری است که می‌خواهیم در کانتینر اجرا شود. دستور watch به طور مکرر دستور داده‌شده را، به‌طور پیش‌فرض هر دو ثانیه یک‌بار، اجرا می‌کند. در اینجا، دستوری که watch اجرا می‌کند این است: date >> /var/log/date.log.

دستور date تاریخ و زمان فعلی را چاپ می‌کند، مثلاً:

Fri Jul 23 14:57:05 UTC 2021

قسمت >> /var/log/date.log خروجی دستور date را به فایل /var/log/date.log هدایت کرده و به انتهای آن اضافه می‌کند. هر دو ثانیه یک خط جدید به فایل اضافه می‌شود و پس از چند ثانیه فایل چیزی شبیه این خواهد شد:

Fri Jul 23 15:00:26 UTC 2021  
Fri Jul 23 15:00:28 UTC 2021  
Fri Jul 23 15:00:30 UTC 2021  
Fri Jul 23 15:00:32 UTC 2021  
Fri Jul 23 15:00:34 UTC 2021

در مرحله بعد، یاد می‌گیریم که چگونه نام کانتینرهای Docker را پیدا کنیم. این زمانی مفید است که قبلاً کانتینری دارید که می‌خواهید روی آن کار کنید اما از نام آن مطمئن نیستید.

پیدا کردن نام یا شناسه (ID) کانتینرهای در حال اجرا

اگر قبلاً یک یا چند کانتینر در حال اجرا دارید و می‌خواهید نام یا شناسه آن‌ها را پیدا کنید تا از دستور docker exec استفاده کنید، می‌توانید دستور زیر را اجرا کنید:

docker ps

این دستور فهرستی از تمام کانتینرهای در حال اجرا را همراه با جزئیات زیر نمایش می‌دهد:

  • شناسه کانتینر (CONTAINER ID)
  • اییج مورد استفاده (IMAGE)
  • دستوری که کانتینر با آن اجرا شده (COMMAND)
  • مدت زمان اجرا (CREATED)
  • مدت زمانی که در حال اجراست (STATUS)
  • پورت‌های نگاشت شده (PORTS)
  • نام اختصاص داده شده به کانتینر (NAMES)

برای نمونه:

OutputCONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAMES
76aded7112d4   alpine    "watch 'date >> /var…"   11 seconds ago   Up 10 seconds             container-name

در این مثال، نام کانتینر ما container-name است که می‌توانیم برای اجرای دستور docker exec از آن استفاده کنیم.

اگر مایل باشید نام کانتینر خود را تغییر دهید، از دستور docker rename استفاده کنید:

docker rename container-name new-name

در ادامه، چندین مثال از استفاده از دستور docker exec برای اجرای دستورات در یک کانتینر داکر را بررسی خواهیم کرد.

اجرای یک شِل تعاملی در داخل یک کانتینر داکر

اگر نیاز دارید یک شِل تعاملی (Interactive Shell) را در داخل یک کانتینر داکر اجرا کنید—مثلاً برای بررسی سیستم فایل یا اشکال‌زدایی پردازش‌های در حال اجرا—از دستور docker exec همراه با دو گزینه‌ی -i و -t استفاده کنید.

گزینه‌ی -i ورودی را برای کانتینر باز نگه می‌دارد و گزینه‌ی -t یک ترمینال مجازی (pseudo-terminal) ایجاد می‌کند تا شِل بتواند به آن متصل شود. این دو گزینه را می‌توان به‌صورت زیر ترکیب کرد:

docker exec -it container-name sh

این دستور شِل sh را در کانتینر مشخص‌شده اجرا می‌کند و یک پرامپت ساده‌ی شِل در اختیار شما قرار می‌دهد. برای خروج از کانتینر، کافی است دستور exit را وارد کرده و ENTER را بزنید:

exit

اگر ایمیج کانتینر شما شامل یک شِل پیشرفته‌تر مانند bash باشد، می‌توانید به‌جای sh از bash استفاده کنید.

اجرای دستور غیرتعاملی در یک کانتینر داکر

اگر نیاز دارید یک دستور را در داخل یک کانتینر در حال اجرای داکر اجرا کنید، ولی نیازی به تعامل (ورودی کاربر) ندارید، می‌توانید از دستور docker exec بدون هیچ گزینه‌ای استفاده کنید:

docker exec container-name tail /var/log/date.log

این دستور، فرمان tail /var/log/date.log را در کانتینری با نام container-name اجرا می‌کند و خروجی آن را نمایش می‌دهد. به‌طور پیش‌فرض، دستور tail ده خط آخر فایل را چاپ می‌کند. اگر در حال اجرای کانتینر دمو هستید که در بخش اول تنظیم کرده‌ایم، خروجی چیزی شبیه به این خواهد بود:

Mon Jul 26 14:39:33 UTC 2021  
Mon Jul 26 14:39:35 UTC 2021  
Mon Jul 26 14:39:37 UTC 2021  
Mon Jul 26 14:39:39 UTC 2021  
Mon Jul 26 14:39:41 UTC 2021  
Mon Jul 26 14:39:43 UTC 2021  
Mon Jul 26 14:39:45 UTC 2021  
Mon Jul 26 14:39:47 UTC 2021  
Mon Jul 26 14:39:49 UTC 2021  
Mon Jul 26 14:39:51 UTC 2021

این دستور در اصل همان کاری را می‌کند که در مرحله قبل با اجرای شِل تعاملی (docker exec -it container-name sh) انجام دادیم و سپس در آن شِل، فرمان tail /var/log/date.log را اجرا کردیم. اما در این حالت بدون نیاز به باز کردن شِل مجازی (pseudo-terminal)، مستقیماً خروجی دستور را در یک مرحله به ما می‌دهد.

اجرای دستورات در یک دایرکتوری دیگر در کانتینر داکر

برای اجرای یک دستور در یک دایرکتوری مشخص در کانتینر، می‌توانید از گزینه --workdir استفاده کنید تا دایرکتوری کاری را تعیین کنید:

docker exec --workdir /tmp container-name pwd

در این مثال، دایرکتوری /tmp به‌عنوان دایرکتوری کاری (working directory) تعیین می‌شود، سپس دستور pwd اجرا می‌شود که دایرکتوری فعلی را چاپ می‌کند:

/tmp

دستور pwd تأیید می‌کند که دایرکتوری کاری کنونی /tmp است.

اجرای دستورات به عنوان کاربر متفاوت در کانتینر داکر
برای اجرای یک دستور به عنوان یک کاربر متفاوت داخل کانتینر، می‌توانید از گزینه --user استفاده کنید:

docker exec --user guest container-name whoami

این دستور، فرمان whoami را به عنوان کاربر guest در کانتینر اجرا می‌کند. دستور whoami نام کاربری جاری را چاپ می‌کند:

Output
guest

این خروجی تأیید می‌کند که کاربر فعلی در کانتینر، guest است.

 

ارسال متغیرهای محیطی (Environment Variables) به کانتینر داکر
گاهی نیاز است متغیرهای محیطی را همراه دستور به کانتینر ارسال کنید. برای این کار، گزینه -e به شما امکان می‌دهد یک متغیر محیطی مشخص کنید:

docker exec -e TEST=sammy container-name env

این دستور متغیر محیطی TEST را با مقدار sammy تنظیم کرده و سپس دستور env را در کانتینر اجرا می‌کند. دستور env تمام متغیرهای محیطی را نمایش می‌دهد:

Output
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=76aded7112d4
TEST=sammy
HOME=/root

در خروجی مشاهده می‌شود که متغیر TEST برابر sammy تنظیم شده است.

برای تنظیم چند متغیر، می‌توانید گزینه -e را برای هر متغیر تکرار کنید:

docker exec -e TEST=sammy -e ENVIRONMENT=prod container-name env

ارسال فایل متغیرهای محیطی به کانتینر
اگر بخواهید فایل حاوی چند متغیر محیطی را به کانتینر ارسال کنید، از گزینه --env-file استفاده کنید.

ابتدا فایل متنی حاوی متغیرها را بسازید. مثلاً با ویرایشگر nano:

nano .env

نام .env رایج است چون برای مدیریت تنظیمات خارج از کنترل نسخه استفاده می‌شود.

داخل فایل، متغیرها را به شکل KEY=value، هر خط یک متغیر، بنویسید:

.env
TEST=sammy
ENVIRONMENT=prod

فایل را ذخیره و ببندید (در nano، CTRL+O سپس ENTER برای ذخیره و CTRL+X برای خروج).

سپس دستور زیر را اجرا کنید تا فایل به کانتینر ارسال شود:

docker exec --env-file .env container-name env

خروجی:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=76aded7112d4
TEST=sammy
ENVIRONMENT=prod
HOME=/root

متغیرهای داخل فایل به درستی تنظیم شده‌اند.

 

نکته: می‌توانید چند فایل را با استفاده از چند بار گزینه --env-file مشخص کنید. اگر متغیرهای چند فایل همپوشانی داشتند، فایل آخر اولویت خواهد داشت و متغیرهای آن جایگزین قبلی‌ها می‌شوند.

خطاهای رایج و رفع آنها هنگام استفاده از دستور docker exec

خطاهای رایج و اشکال‌زدایی

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

خطا: “Container not found”

Error: No such container: container-name

این خطا به این معناست که کانتینری با نام مشخص شده وجود ندارد و احتمالاً نام کانتینر اشتباه تایپ شده است. برای مشاهده کانتینرهای در حال اجرا از دستور زیر استفاده کنید و نام کانتینر را دوباره بررسی کنید:

docker ps

خطا: “Permission denied”

Error response from daemon: Permission denied

این خطا معمولاً زمانی رخ می‌دهد که کاربری که دستور docker exec را اجرا می‌کند، دسترسی کافی برای دسترسی به کانتینر ندارد. مطمئن شوید کاربر مجوزهای لازم را دارد یا دستور را با sudo اجرا کنید.

خطا: “Container is not running”

Error response from daemon: Container <container_id> is not running

این خطا نشان می‌دهد کانتینر مشخص شده وجود دارد اما در حال حاضر در حال اجرا نیست (متوقف شده یا کرش کرده). برای رفع این مشکل، کانتینر را با دستور زیر دوباره اجرا کنید:

docker start container-name

سپس می‌توانید با دستور docker exec به داخل کانتینر دستور بفرستید.

خطا: “Container is paused”

Error response from daemon: Container container-name is paused, unpause the container before exec

این خطا نشان می‌دهد که کانتینر در حالت pause است؛ یعنی متوقف نشده اما در حال اجرا هم نیست. قبل از اجرای دستور، باید کانتینر را از حالت pause خارج کنید:

docker unpause container-name

راهکارهای رفع مشکلات رایج هنگام استفاده از docker exec

  • مطمئن شوید نام کانتینر صحیح است و کانتینر در حال اجراست.
  • کاربری که دستور را اجرا می‌کند دسترسی کافی دارد.
  • کانتینر در حالت pause نیست.
  • دستور و گزینه‌ها به درستی نوشته شده‌اند.

نکات بهینه‌سازی عملکرد هنگام اجرای دستورهای سنگین با docker exec

وقتی دستورهای سنگین داخل کانتینر اجرا می‌کنید، مهم است که این عملیات باعث کند شدن کانتینر نشود. چند توصیه:

  • استفاده از گزینه --detach
    برای اجرای دستوری که زمان زیادی می‌برد، از این گزینه استفاده کنید تا دستور در پس‌زمینه اجرا شود و ترمینال شما آزاد بماند:
docker exec --detach container-name command
  • محدود کردن منابع مصرفی
    با استفاده از گزینه‌های --cpu-shares و --memory میزان منابع CPU و رم اختصاص یافته به دستور را محدود کنید:
docker exec --cpu-shares 512 --memory 512m container-name command
  • بهینه‌سازی دستور
    دستور را بهینه کنید تا سریع‌تر اجرا شود، مثلاً تقسیم کار بزرگ به بخش‌های کوچکتر یا استفاده از الگوریتم‌های بهتر:
docker exec container-name optimized-command
  • استفاده از کانتینر جداگانه برای کارهای سنگین
    اگر کاری منابع زیادی مصرف می‌کند، آن را در یک کانتینر جداگانه اجرا کنید تا روی عملکرد کانتینر اصلی تاثیر نگذارد:
docker run --name heavy-task-container heavy-task-image
  • نظارت بر عملکرد کانتینر
    با دستور زیر می‌توانید عملکرد کانتینر را بررسی و مشکلات احتمالی را شناسایی کنید:
docker stats container-name
  • اجتناب از اجرای دستورات غیرضروری
    فقط دستورات ضروری را اجرا کنید و از اجرای دستورات اضافی که ممکن است کندی ایجاد کنند، خودداری کنید:
docker exec container-name necessary-command
  • استفاده از امکانات داخلی داکر برای بهینه‌سازی
    مثلاً گزینه --oom-kill-disable برای جلوگیری از کشته شدن کانتینر به خاطر کمبود حافظه:
docker run --oom-kill-disable container-name

با رعایت این نکات، اجرای دستورات سنگین داخل کانتینرها با docker exec به گونه‌ای خواهد بود که تاثیر منفی روی عملکرد کل کانتینر نگذارد.

سوالات متداول (FAQs)

دستور docker exec چیست؟

دستور docker exec یک فرمان داکر است که به شما اجازه می‌دهد یک دستور را داخل یک کانتینر داکر در حال اجرا اجرا کنید. این امکان را می‌دهد که بدون نیاز به ساخت کانتینر جدید، فرمانی را در یک کانتینر فعال اجرا کنید. این قابلیت برای اشکال‌زدایی، بررسی یا تغییر وضعیت کانتینر بسیار مفید است.

مثلاً برای اجرای دستور ساده ls داخل کانتینر در حال اجرا، از دستور زیر استفاده می‌شود:

docker exec <container-name> ls

این دستور محتویات دایرکتوری جاری کانتینر را نشان می‌دهد و خروجی آن در ترمینال شما نمایش داده می‌شود.

چگونه با docker exec به شل کانتینر در حال اجرا دسترسی پیدا کنم؟

برای دسترسی به شل یک کانتینر در حال اجرا با docker exec، از گزینه‌های -it استفاده می‌کنیم.

  • -i باعث می‌شود ورودی به کانتینر باز بماند.
  • -t یک ترمینال مجازی (pseudo-TTY) به کانتینر متصل می‌کند.

مثال:

docker exec -it <container-name> bash

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

آیا می‌توانم دستورات را به عنوان کاربر خاصی در کانتینر اجرا کنم؟

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

مثال اجرای دستور به عنوان کاربر root:

docker exec --user root <container-name> command

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

چگونه چندین دستور را داخل کانتینر با docker exec اجرا کنم؟

برای اجرای چند دستور به صورت پشت سر هم، می‌توانید دستورات را با ; از هم جدا کنید و آنها را داخل گزینه -c قرار دهید.

مثال:

docker exec <container-name> -c "command1; command2; command3"

این دستور به ترتیب command1، سپس command2 و در نهایت command3 را داخل کانتینر اجرا می‌کند.

اگر docker exec کار نکرد، چه کنم؟

اگر دستور docker exec به درستی اجرا نشد، این موارد را بررسی کنید:

  • وضعیت کانتینر: با docker ps بررسی کنید که کانتینر در حال اجرا باشد. اگر نه، با docker start آن را راه‌اندازی کنید.
  • نام کانتینر: مطمئن شوید نام یا شناسه کانتینر درست وارد شده است.
  • درستی دستور: اطمینان یابید دستور به درستی و با قالب درست نوشته شده باشد.
  • پیکربندی کانتینر: ممکن است دستور نیاز به دسترسی یا مجوز خاصی داشته باشد؛ تنظیمات کانتینر را بررسی کنید.
  • نسخه داکر: مطمئن شوید نسخه داکر نصب شده با دستوری که می‌خواهید اجرا کنید سازگار است (با docker --version بررسی کنید).

اگر هیچ‌کدام از این موارد مشکل را حل نکرد، مستندات داکر را مطالعه کنید یا از یک متخصص داکر کمک بگیرید.

نتیجه‌گیری

در این آموزش، یاد گرفتید که چگونه از دستور docker exec برای اجرای دستورات در یک کانتینر در حال اجرا استفاده کنید. همچنین نحوه اجرای دستورات ساده و نحوه ورود به یک شل تعاملی درون کانتینر را دیدید.

این ابزار ابزاری حیاتی برای دیباگ و مدیریت کانتینرهاست، به‌ویژه زمانی که در حال توسعه برنامه‌های تحت Docker یا عیب‌یابی آن‌ها هستید.

 

منبع: DigitalOcean

۱۱۶
۱۴۰۴/۳/۳۰