Timezoneها، یک موضوع گیج کننده رایج هنگام ایجاد یک برنامه هستند. بدین معنی که همواره این نگرانی وجود دارد که آیا cronهای برنامه در زمان مناسب اجرا می‌شود؟ کانتینرهای داکر timezone میزبان را به ارث نمی‌برند؛ بنابراین، ممکن است با برنامه ریزی‌های غیرمنتظره‌ای روبرو شوید که باعث خرابی برنامه شما می‌شود.

 

به عنوان مثال، دستور date در میزبان اوبونتو 20.04 در تابستان انگلستان خروجی زیر را خواهد داشت:

 

 

در حالیکه همان دستور در یکی از کانتینرهای اصلاح نشده (ubuntu: 20.04) آن میزبان به صورت زیر خواهد بود:

 

 

container از timezone UTC استفاده می‌کند که یک ساعت تفاوت بین دو زمان ایجاد کرده است.

 

Timezone لینوکس چگونه کار می‌کند؟

اکثر توزیع‌های لینوکس از بسته tzdata برای ارائه اطلاعات timezone استفاده می‌کنند. چنانچه tzdata نصب شده باشد، شما می‌توانید با خواندن فایل /etc /timezone timezone فعلی را بازرسی کنید:

 

 

همچنین یک فایل /etc /localtime خواهید داشت. این فایل، یک لینک به پایگاه داده timezone صحیح برای مکان انتخاب شده است:

 

 

اگر timezone را تغییر دهید (با استفاده از dpkg-configure tzdata)، لینک /etc /localtime به روز می‌شود تا به پایگاه داده جدید اشاره کند. خروجی دستوراتی مانند date به گونه‌ای تنظیم شده است که شامل offset timezone فعال باشد.

 

مشکل container

چالش در مورد containerها از تنظیم timezone در وهله اول ناشی می‌شود. timezone باید به عنوان بخشی از نصب سیستم عامل در همان ابتدا تنظیم شود. هنگامی‌که یک container جدیدی را اجرا می‌کنید، بلافاصله بدون هیچ مرحله‌ای "نصب" شروع می‌شود و فرصتی برای انتخاب timezone مناسب وجود ندارد.

از لحاظ تئوری، runtime کانتینر می‌تواند وراثت خودکار timezone میزبان را ارائه دهد. با این حال، چنین اتفاقی نمی‌افتد؛ زیرا ممکن است هنگام استقرار در محیط‌های ریموت به نتایج غیر منتظره‌ای منجر شود. زمانی که برنامه cron شما روی دستگاه محلی تان کار می‌کند، به راحتی می‌توان آن را نادیده گرفت؛ اگرچه به صورت غیرمنتظره در یک کلاستر Kubernetes مدیریت شده با استفاده از زمان UTC اجرا می‌شود.

imageهای کانتینر به جای آن با یک baked-in timezone ارسال می‌شوند. برای اکثر imageهای محبوب، این UTC خواهد بود. بسیاری از imageهای اصلی (به ویژه کوچک‌ترین آن‌ها) حتی شامل بسته tzdata نمی‌شوند. بنابراین، شما هیچ کدام از فایل‌های /etc/zonezone یا /etc/localtime را نخواهید داشت.

 

افزودن Timezone به container

اولین مرحله برای تنظیم timezone مناسب این است که مطمئن شوید tzdata در سیستم شما نصب شده است. اگر image شما آن را ندارد، باید بسته را به صورت دستی به عنوان بخشی از Dockerfile خود اضافه کنید.

FROM ubuntu:latest
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y tzdata

هنگام نصب tzdata، معمولاً یک پیغام دریافت می‌کنید که به شما امکان می‌دهد timezone صحیح را از یک منو انتخاب کنید. وقتی به طور برنامه ریزی شده Docker container می‌سازید، این کار مفید نخواهند بود؛ چراکه تنظیم متغیر محیطی DEBIAN_FRONTEND، درخواست را حذف کرده و timezone را به صورت پیش فرض برروی UTC تنظیم می‌نماید.

هنگامی‌که tzdata را در image خود دریافت کردید، آماده پیکربندی timezone مناسب برای برنامه خود خواهید بود. ساده‌ترین رویکرد این است که متغیر محیطی TZ را در timezone مورد نظر خود قرار دهید:

FROM ubuntu:latest
ENV TZ=Europe/London
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y tzdata

 

این مطلب نیز ممکن است برای شما مفید باشد: تغییر timezone (منطقه زمانی) در اوبونتو

 

در صورت تمایل، شما می‌توانید متغیر TZ را هنگام راه‌اندازی containerها تنظیم کنید. بدین معنی که آن را به عنوان متغیر محیطی برای اجرای docker ارسال کنید. این به شما امکان می‌دهد timezone پیش فرض image را نادیده بگیرید (به شرط آنکه در سیستم شما بسته tzdata نصب باشد.)

docker run -e TZ=Europe/London -it ubuntu:latest

یک جایگزین برای متغیرهای محیطی، فایل /etc/zonezone است. شما می‌توانید timezone مورد نیاز را به عنوان بخشی از Dockerfile خود بنویسید. اگر از این روش استفاده می‌کنید، باید tzdata را با استفاده از ابزار مدیریت بسته خود مجدداً پیکربندی کنید. به یاد داشته باشید که از حالت غیر تعاملی استفاده کنید، در غیر این صورت دوباره پیغام timezone گرافیکی را دریافت خواهید کرد.

FROM ubuntu:latest
RUN echo "Europe/London" > /etc/timezone
RUN dpkg-reconfigure -f noninteractive tzdata

 

تکنیک‌های دیگر

اگر می‌خواهید همگام سازی timezone را با میزبان تضمین کنید، شما می‌توانید فایل‌های tzdata محلی‌تان را در containerهای خود نصب کنید. به منظور عملکرد صحیح، شما هنوز به tzdata در داخل container نیاز دارید.

docker run -v /etc/timezone:/etc/timezone -v /etc/localtime:/etc/localtime -it ubuntu:latest

اگرچه Docker هیچ پشتیبانی داخلی برای Timezone ارائه نمی‌دهد؛ اما در مورد همه موتورهای کانتینری صادق نیست. Podman دارای یک پرچم --tz است که به شما امکان می‌دهد، هنگام ایجاد یک کانتینر جدید timezone را تنظیم کنید:

podman run --tz=Europe/London -it ubuntu:latest

در پشت صحنه، Podman یک فایل مناسب /etc/localtime را برای شما mount می‌کند. timezone مشخص شده تا پایان عمر container باقی می‌ماند.

Podman همچنین به شما امکان می‌دهد، یک timezone پیش فرض برای containerهای ایجاد شده بدون پرچم --tz تنظیم کنید. بدین منظور لازم است .config/container/containers.conf را در دایرکتوری home خود ایجاد یا ویرایش کنید. سپس یک تنظیم tz را روی یک خط جدید در فایل اضافه کنید:

# Used when no --tz flag is given
tz = "Europe/London"

ادغام timezone بومی Podman، کار کردن با Docker را آسان‌تر می‌کند. از آنجایی که CLI Podman با Docker سازگار است، اگر اغلب با containerها در Timezoneهای مختلف کار می‌کنید، جابجایی بین آن‌ها قابل توجه است.

 

 

 

منبع:

cloudsavvyit