تقریبا در تمام پروژه ها از فایل های .env استفاده می کنیم. این فایل ها می توانند مقادیر مختلفی را در بر داشته باشند. مثلا مقادیری که برای تنظیمات پروژه مورد نیاز هستند یا مقادیری که برای تنظیمات امنیتی یا اتصال به دیتابیس استفاده میشه.

در ترکیب استفاده از این فایل با Docker به نکات ریز و جالبی برخورد خواهیم کرد. برای مثال سناریویی را در نظر بگیرید که نیاز داریم یک پروژه NextJS را داکرایز کرده ٬ آن را یک بار Build کنیم و سپس در Pod های مختلف با تنظیمات گوناگون مستقر کنیم.

از نظر فنی داکر می تواند با استفاده از آپشن --env-file یک فایل .env برای زمان اجرا تعریف کند.

docker run --rm --env-file .env -p 3000:3000 -d YOUR_CONTAINER_TAG

مشکل چیه ؟

از اونجایی که Environment در حین زمان ساخت در کانتینر تنظیم میشه و NextJS دارای یک سیستم بهینه سازی خودکار سایت است ٬ صفحات از پیش رندر شده را برای رندر Server-Side در حین ساخت تولید می کند.

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

حل مشکل

در سناریوی ما برای مدیریت تنظیمات Environment از Envault استفاده می کنیم. از آنجایی که ایمیج های داکر توسط Jenkins ساخته میشن هربار فایل .env مورد نظر دریافت خواهد شد.

برای شروع باید چنین Dockerfile داشته باشیم :

ARG DB_USER
ARG DD_SVC
ENV DB_USER=$DB_USER
ENV DD_SVC=$ARG DD_SVC

این بدان معنا است که دستور ساخت باید همراه با --build-arg اجرا شود. این آپشن باید برای هر متغیر تنظیم شود پس مسلما انجام دادن این کار به طور دستی زیاد درست و تمیز نیست 😁 چرا ؟ فرض کنید پروژه شما بیشتر از ۱۰ تا متغیر داشته باشه ٬ همه اون ها رو قراره دستی اضافه کنید؟ خب نه

برای خوندن این داده ها از فایل .env میشه یه اسکریپت ساده نوشت :

$(for i in `cat .env`; do out+="--build-arg $i " ; done; echo $out;out="")

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

docker build -f Dockerfile -t YOUR_CONTAINER_TAG $(for i in `cat .env`; do out+="--build-arg $i " ; done; echo $out;out="") .

استفاده در Makefile

بیاید قبول کنیم که هیچکس دستور بالا رو نمیخواد تایپ کنه 😁 و خب منطقی هم نیست برای پروژه های مختلف چنین دستور هایی رو جایی کپی کرده و از اون ها استفاده کنیم.

پس بریم سراغ Makefile دوست داشتنی خودمون. استفاده مستقیم از اسکریپت قبل در Makefile کار چندان جالبی نیست٬ در نتیجه به این صورت پیاده سازی بشه بهتره:

SHELL := /bin/bash
DECONARGS = $(shell echo "$$(for i in `cat .env`; do out+="--build-arg $$i " ; done; echo $$out;out="")")
GEN_ARGS = $(eval BARGS=$(DECONARGS))

build:
    @echo "Running docker build for PROD ..."
    $(GEN_ARGS)
    docker build -f Dockerfile -t tag $(BARGS) .

.PHONY: build

حالا کافیه با اجرای دستور make build به چیزی که میخواستیم برسیم.


راه بهتر و خفن تری سراغ دارید؟ به اشتراک بگذارید