وبلاگ نت‌آرامآموزش، تجربه و راهکارهای زیرساخت

متغیر محیطی در Docker Compose خالی است؛ از فایل env تا داخل کانتینر

تشخیص تفاوت interpolation و env_file، اولویت متغیرهای محیطی و اعمال تنظیم درست در کانتینر Docker Compose.

انتشار:
توسط تیم فنی نت‌آرام
۸ دقیقه زمان مطالعه
۰ دیدگاه
محتوای تخصصی، ساده و کاربردی
هماهنگ با هویت حرفه‌ای نت‌آرام
بازگشت به لیست مقالات
تصویر شاخص مقاله متغیر محیطی در Docker Compose خالی است؛ از فایل env تا داخل کانتینر در وبلاگ نت‌آرام
محتوای آموزشی وبلاگ نت‌آرام
در فایل .env یک مقدار گذاشته‌اید، اما برنامه داخل کانتینر می‌گوید متغیر خالی است یا وجود ندارد. گاهی مقدار در ترمینال شما تنظیم شده، ولی کانتینر هنوز با تنظیم قبلی ساخته شده است. گاهی هم Docker Compose برای ساخت فایل تنظیمات به متغیر دسترسی دارد، ولی شما آن را به محیط برنامه داخل کانتینر نداده‌اید.
این دو مرحله را جدا می‌کنیم: اول Compose فایل پیکربندی را می‌خواند و جای متغیرها را پر می‌کند؛ بعد تنظیم‌های سرویس مشخص می‌کنند چه چیزی به کانتینر می‌رسد. با یک مثال غیرمحرمانه مسیر را از ابتدا تا داخل کانتینر دنبال می‌کنیم.
این آموزش برای Docker Compose جدید با دستور docker compose است. در نسخه قدیمی ممکن است دستور docker-compose یا بعضی گزینه‌ها متفاوت باشند. web نام نمونه سرویس و APP_MESSAGE یک متغیر آزمایشی است؛ رمز یا کلید واقعی را در دستور، تصویر، تیکت یا خروجی عمومی قرار ندهید.

۱. سرویس و محل پروژه را مشخص کنید

در سرور، به پوشه پروژه بروید و نسخه Compose را ببینید:
کد / دستورdocker compose version
سرویس‌های پروژه و وضعیت آن‌ها:
کد / دستورdocker compose ps
اگر از -f، --project-directory یا --env-file استفاده می‌کنید، هنگام همه آزمایش‌ها همان گزینه‌ها را به کار ببرید. اجرای دستور در پوشه‌ای دیگر ممکن است پروژه یا فایل دیگری را انتخاب کند. برای دیدن پوشه فعلی:
کد / دستورpwd
پیش از بررسی متغیرهای حساس بدانید docker compose config، docker compose config --environment، docker inspect و printenv می‌توانند مقدار رمز و کلید را نمایش دهند. خروجی کامل آن‌ها را در تیکت نفرستید. برای تمرین از مقدار غیرمحرمانه استفاده می‌کنیم.

۲. مثال: مقدار در فایل .env است اما باید به سرویس هم داده شود

فرض کنید در پوشه پروژه فایلی به نام .env دارید:
کد / دستورAPP_MESSAGE=hello
اگر می‌خواهید همین مقدار به کانتینر web برسد، بخشی از compose.yaml می‌تواند این باشد:
کد / دستورservices: web: image: myapp:example environment: APP_MESSAGE: ${APP_MESSAGE:?APP_MESSAGE is required}
این فقط بخشی از فایل نمونه است؛ image و سایر تنظیمات برنامه خود را جایگزین نکنید. Compose مقدار را در مرحله خواندن فایل جایگزین می‌کند و بخش environment آن را به سرویس می‌دهد. عبارت :? در این مثال باعث می‌شود اگر متغیر تنظیم نشده یا خالی باشد، Compose خطا بدهد؛ با ? بدون دونقطه، خالی بودن و تنظیم‌نشدن رفتار متفاوتی دارند.
اگر متغیری فقط در .env باشد و هیچ تنظیمی آن را به محیط سرویس منتقل نکند، قرار گرفتنش در کنار فایل Compose به‌تنهایی به معنی موجود بودن داخل کانتینر نیست.
برای بررسی ساختار بدون چاپ تنظیمات:
کد / دستورdocker compose config --quiet
اگر متغیر اجباری غایب باشد، باید پیام خطا بگیرید. این آزمون صحت مقدار واقعی یا کارکرد برنامه را اثبات نمی‌کند. در نسخه‌ای که گزینه --environment دارد، می‌توانید منابع مورد استفاده برای جایگذاری را ببینید:
کد / دستورdocker compose config --environment
این خروجی ممکن است همه مقدارهای محرمانه را نشان دهد. فقط در نشست خصوصی خود بخوانید و منتشر نکنید. در پروژه واقعی برای بررسی وجود نام، بدون چاپ عمدی مقدارها می‌توانید نام‌ها را جدا کنید:
کد / دستورdocker compose config --environment | cut -d= -f1
حتی در این حالت هشدارهای دیگر یا نام متغیرها ممکن است حساس باشند. اگر گزینه موجود نیست، نسخه Compose و مستند همان نسخه را بررسی کنید.

۳. اولویت shell و فایل env را بشناسید

اگر یک نام در چند جا مقدار داشته باشد، محیط shell اجرای Compose برای جایگذاری معمولاً بر فایل .env اولویت دارد. مثال: اگر در فایل APP_MESSAGE=hello باشد ولی در ترمینال همان نام با مقدار خالی export شده باشد، ممکن است مقدار خالی shell استفاده شود و عبارت اجباری خطا بدهد.
برای متغیر آزمایشی غیرمحرمانه در Linux:
کد / دستورprintf 'APP_MESSAGE=<%s>\n' "$APP_MESSAGE"
برای تشخیص تنظیم‌نشدن از خالی بودن:
کد / دستورif [ "${APP_MESSAGE+x}" = x ]; then echo 'set in shell'; else echo 'not set in shell'; fi
اگر فقط در همین نشست یک مقدار آزمایشی اشتباه export کرده‌اید، می‌توانید آن را از محیط همان shell بردارید:
کد / دستورunset APP_MESSAGE
این دستور فایل .env را ویرایش نمی‌کند و بر shellهای دیگر اثر ندارد. سپس docker compose config --quiet را تکرار کنید. متغیرهای واقعی سازمانی را بدون دانستن محل استفاده unset نکنید. در PowerShell دستورها و دامنه متغیر محیطی متفاوت‌اند.
بدون --env-file، Compose معمولاً فایل .env پروژه را برای جایگذاری می‌خواند. محل پروژه به گزینه --project-directory، فایل اول -f و سپس پوشه جاری وابسته است. اگر به‌صراحت فایل دیگری می‌خواهید:
کد / دستورdocker compose --env-file ./config/app.env config --quiet
مسیر نمونه باید وجود داشته باشد و نسبت به پوشه‌ای که فرمان را اجرا می‌کنید تفسیر می‌شود. در نسخه‌های جدید می‌توان چند --env-file داد و فایل‌های بعدی بر موارد قبلی اثر می‌گذارند؛ محیط shell همچنان ممکن است اولویت بالاتری داشته باشد.

۴. تفاوت --env-file و env_file سرویس

--env-file یک گزینه فرمان Compose برای تأمین مقادیر جایگذاری پیکربندی است. در مقابل، env_file: زیر یک سرویس، متغیرهای فایل را به محیط آن کانتینر می‌دهد. این دو نقش را یکی ندانید.
مثلاً اگر فایل web.env شامل APP_MESSAGE=hello است:
کد / دستورservices: web: image: myapp:example env_file: - ./web.env
مسیر env_file سرویس نسبت به محل فایل Compose تفسیر می‌شود. اگر هم‌زمان در بخش environment همان نام را با مقدار خالی تعیین کنید، آن مقدار می‌تواند مقدار env_file را بازنویسی کند. بنابراین هر دو بخش را با هم بخوانید و تعریف تکراری اشتباه را فقط پس از شناخت منبع درست اصلاح کنید.
فایل web.env سرویس را با فایل جایگذاری پروژه اشتباه نگیرید؛ صرف تعریف آن زیر env_file تضمین نمی‌کند همان مقدار برای جایگذاری $&#123;APP_MESSAGE&#125; در کل فایل Compose استفاده شود. اگر هر دو نیاز را دارید، هر نقش را صریح و طبق مستندات تنظیم کنید.

۵. آیا کانتینر هنوز تنظیم قدیمی دارد؟

تغییر فایل روی دیسک به‌تنهایی محیط پردازشِ از قبل اجراشده را عوض نمی‌کند. بعد از اصلاح فایل و تأیید پیش‌نمایش، در زمان مجاز سرویس مربوط را دوباره با Compose اعمال کنید:
کد / دستورdocker compose up -d --no-deps web
این کار ممکن است کانتینر web را بازسازی کند و قطع کوتاه ایجاد شود؛ مسیر داده، volume و روش برگشت را از قبل بررسی کنید. نام سرویس واقعی را جایگزین کنید و اگر پروژه چند فایل یا --env-file دارد، همان گزینه‌های استقرار را در این دستور هم وارد کنید.
برای مثال غیرمحرمانه، پس از بالا آمدن سرویس:
کد / دستورdocker compose exec web printenv APP_MESSAGE
باید مقدار مورد انتظار مثل hello نمایش داده شود. اگر image ابزار printenv یا shell ندارد، از روش تشخیصی خود برنامه استفاده کنید. برای رمز واقعی مقدار را چاپ نکنید؛ با امکان تشخیص وجود یا خالی نبودن مقدار، و بدون افشای آن، صحت را در محیط مجاز بسنجید. بعضی برنامه‌ها تنظیم را از فایل یا secret می‌خوانند، نه از متغیر محیطی.

۶. اگر هنوز مقدار خالی است

نام متغیر را از نظر حروف کوچک و بزرگ دقیق مقایسه کنید: APP_MESSAGE با app_message یکی نیست. بررسی کنید برنامه همان نام را می‌خواند و مقدار در بخش سرویس درست قرار گرفته است. اگر چند فایل Compose با -f ترکیب می‌شوند، ممکن است فایل بعدی تنظیم سرویس را تغییر دهد.
در فایل‌های env، کوتیشن و علامت $ هم مهم‌اند. برای نمونه در فایل .env، مقدار تک‌کوتیشن‌شده مانند VALUE='$OTHER' به شکل literal در نظر گرفته می‌شود؛ در مقدارهای بدون کوتیشن یا با کوتیشن دوتایی، قواعد جایگذاری Compose می‌توانند اعمال شوند. اگر لازم است یک علامت دلار به فرمان داخل کانتینر برسد و Compose آن را جایگذاری نکند، در فایل Compose اغلب از $$ استفاده می‌شود؛ بعد رفتار فرمان را در محیط آزمایشی تأیید کنید.
برای اسرار، از فایل یا secret با مجوز مناسب و راهکار مدیریت اسرار سازگار با برنامه استفاده کنید. حتی متغیر محیطی کانتینر هم ممکن است برای افرادی که به Docker دسترسی دارند قابل مشاهده باشد. قرار دادن رمز در repository عمومی یا چاپ آن برای عیب‌یابی امن نیست.
پس از اصلاح، علاوه بر مقدار آزمایشی، عملکرد واقعی برنامه را بررسی کنید؛ مثلاً اگر متغیر مربوط به اتصال دیتابیس است، از داخل برنامه اتصال مجاز و نتیجه را امتحان کنید. اگر سرویس بالا است اما وضعیت سلامت آن شکست می‌خورد، راهنمای unhealthy در Docker را هم ببینید.
این مراحل برای Docker روی سرور مجازی ایران و سرور اختصاصی ایران کاربرد دارند. تفاوت منابع و تقدم آن‌ها در مستند جایگذاری متغیرهای Compose و مستند اولویت متغیرها توضیح داده شده است.
اشتراک‌گذاری:
لینکدینتلگرامایکس
مقاله قبلی
مقاله قبلی وجود ندارد.

دیدگاه‌ها (۰)

دیدگاه‌های تاییدشده و پاسخ‌های تیم نت‌آرام