مقدمه
Node.js یک زمان اجرا جاوا اسکریپت است که در سال های گذشته برای ساخت برنامه های سمت سرور محبوب شده است.
این آموزش نحوه استقرار یک برنامه Node.js را در سرور ابری از طریق Docker، Docker Hub و Docker Compose نشان می دهد.
پیش نیازها
- این آموزش فرض می کند که Docker را روی سیستم محلی خود نصب کرده اید. اگر آن را ندارید، می توانید دستورالعمل نصب آن را در اسناد رسمی بیابید.
- شما همچنین باید یک سرور ابری با توزیع لینوکس، ترجیحا اوبونتو 24.04 داشته باشید. اگر از توزیع دیگری استفاده می کنید، ممکن است مجبور شوید به دنبال دستورالعمل های خاصی باشید که زمان نصب Docker بر روی سرور است.
- برخی از مراحل همچنین مستلزم داشتن حساب Docker Hub (رایگان) برای آپلود تصویر Docker برای برنامه است.
- اگر تجربه قبلی Docker ندارید، خوب است، این آموزش بسیار ابتدایی است و مفاهیم اصلی را در مورد کاری که ما انجام می دهیم توضیح می دهد.
- شما به یک برنامه Node.js نیاز دارید که بتوانید آن را مستقر کنید.
درباره داکر
در صورتی که به تازگی با Docker شروع به کار کرده اید، در اینجا برخی از اصطلاحات وجود دارد که ارزش بررسی دارند تا مطمئن شوید که ما در یک مسیر هستیم.
- تصاویر: در داکر، تصاویر «عکسهای فوری» یا الگوهای یک سیستم فایل هستند و شامل هر چیزی است که برای راهاندازی یک برنامه لازم است.
- Containers: اینها نمونه های در حال اجرا واقعی برنامه هستند. آنها با گرفتن یک الگو (یک تصویر) و تبدیل آن به چیزی که می تواند شروع شود و حالت دارد ایجاد می شود.
- لایه ها عناصری هستند که یک تصویر داکر را تشکیل می دهند. هر لایه بر روی لایه ای دیگر ساخته شده است و به شما امکان می دهد قابلیتی به نام ذخیره لایه را ارائه دهد. این بدان معناست که وقتی تنها یکی از لایههای یک تصویر تغییر میکند، نیازی به ساخت مجدد یا بارگیری مجدد تمام لایههای یک تصویر ندارید.
- رجیستریها مکانی هستند که در آن تصاویر را آپلود میکنید (فشار میدهید) تا آنها را در دسترس جهانیان قرار دهید یا برای کسانی که اعتبار دسترسی به آن را دارند. در این آموزش، ما قصد داریم از Docker Hub استفاده کنیم، اما جایگزین هایی نیز توسط GCP، AWS، Azure، GitHub و دیگران ارائه شده است.
مرحله 1 – یک Dockerfile ایجاد کنید
فایلی به نام Dockerfile با محتوای زیر در ریشه دایرکتوری پروژه Node.js خود ایجاد کنید:
FROM node:20.17
ENV NODE_ENV=production
WORKDIR /app
COPY package*.json .
RUN npm ci
COPY . .
EXPOSE 8080
CMD [ "node", "src/index.js" ]
Dockerfile جایی است که دستورالعملهایی را قرار میدهید که به Docker اجازه میدهد یک تصویر بسازد. هر دستورالعمل نشان دهنده ایجاد یک لایه است که اصلاحی در سیستم فایل تصویری در حال ایجاد است.
در این مورد، ما تصویر خود را با شروع از یک الگو، که گاهی اوقات تصویر پایه نامیده میشود، میسازیم که در این مورد node:20.17 است. این یک تصویر رسمی است که توسط شرکت Docker ارائه شده است و می توانید اطلاعات بیشتری در مورد آن در اینجا بیابید.
مرحله بعدی متغیر محیطی NODE_ENV را روی تولید تنظیم می کند. اثر اصلی در اینجا اجتناب از نصب بستههای توسعه در هنگام اجرای نصب npm زیر است، اما اغلب میتواند منجر به بهینهسازی بهتر در ماژولهایی شود که ممکن است به آنها تکیه کنید.
با دستور WORKDIR، دایرکتوری فعلی را به /app منتقل می کنیم، که در نتیجه تبدیل به دایرکتوری می شود که دستورالعمل های زیر در آن اجرا می شوند.
خط بسته COPY*.json . فایل های package.json و package-lock.json را در پوشه /app سیستم فایل تصویری Docker کپی می کند. توجه داشته باشید که نقطه انتهایی برای نشان دادن دایرکتوری فعلی مورد نیاز است.
اکنون با استفاده از دستور npm ci (ci مخفف پاک نصب است و برای استفاده در محیط های خودکار طراحی شده است) از دستورالعمل RUN برای نصب وابستگی های تولید استفاده می کنیم.
نکته ای که در این مرحله باید به آن توجه کرد این است که تا به حال به جای کل فهرست پروژه، فقط فایل های package*.json را در بیلد کپی می کردیم. این اجازه می دهد تا از کش کردن لایه های Docker استفاده کنید، به طوری که اگر بسته های وابسته بدون تغییر باشند، می توان لایه ها را بدون بازسازی مجدد مورد استفاده قرار داد.
خط زیر (COPY . .) فایل های باقی مانده در تصویر را کپی می کند.
به صورت اختیاری، میتوانیم تعیین کنیم که میخواهیم یک پورت شبکه خاص از کانتینر را در معرض دید قرار دهیم تا بتوان از طریق آن به یک برنامه وب دسترسی داشت. توجه داشته باشید که دستورالعمل EXPOSE در واقع پورت را آشکار نمی کند: همانطور که مستندات می گوید، «به عنوان یک نوع سند بین شخصی که تصویر را می سازد و شخصی که کانتینر را اجرا می کند، عمل می کند که در مورد پورت هایی که در نظر گرفته شده است منتشر شود» .
در نهایت، آخرین دستورالعمل دستوری را مشخص می کند که باید توسط Docker برای اجرای برنامه در هنگام شروع کانتینر استفاده شود. در این مورد، ما فرض می کنیم که نقطه ورودی برنامه، فایل index.js است.
معمولاً ایده خوبی است که همراه با Dockerfile یک فایل به نام .dockerignore نیز ایجاد کنید. این اطمینان حاصل می کند که وقتی COPY را اجرا می کنید. .، فایل های بی فایده از رایانه شما در داخل تصویر کپی نمی شوند:
.git
Dockerfile
node_modules
در این مورد، ما علاقه ای نداریم که نسخه های توسعه دایرکتوری هایی مانند git. یا node_modules در قالبی که می سازیم در دسترس باشد.
مرحله 2 – تصویر را بسازید
اکنون که یک Dockerfile داریم، میتوانیم به Docker بگوییم که از آن برای ساخت یک تصویر استفاده کند.
دستور اصلی برای انجام این کار شبیه دستور زیر است و باید در پوشه اصلی پروژه اجرا شود:
docker build -t myproject .
اگر با خطای “/bin/sh -c npm ci” با موفقیت کامل نشد، npm ci را در Dockerfile با npm install جایگزین کنید و دوباره امتحان کنید.
گزینه -t نام تصویر، در این مورد myproject را مشخص می کند. . در انتهای خط باید به Docker بگویید که به دنبال Dockerfile در فهرست فعلی بگردد.
توجه: اولین باری که بیلد را اجرا می کنید، مدتی طول می کشد زیرا داکر باید تمام لایه های تصویر پایه را دانلود کند (در این مورد Node.js 20.17).
از آنجایی که قصد داریم این تصویر را در رجیستری آنلاین Docker Hub آپلود کنیم (برای دسترسی به آن از سرور خود)، باید با استفاده از یک قرارداد خاص نام تصویر را نامگذاری کنیم.
بنابراین دستور بالا به شکل زیر خواهد بود:
docker build -t username/myproject:latest .
جایی که نام کاربری نام کاربری Docker Hub شما است و آخرین آن برچسب تصویر است. یک تصویر میتواند چندین تگ داشته باشد، بنابراین گاهی اوقات گردش کاری مشابه این را میبینید:
docker build -t myproject .
docker tag myproject username/myproject:latest
docker tag myproject username/myproject:20240905
این دستورات یک تصویر را می سازند و سپس آن را با برچسب های آخرین و 20240904 تگ می کنند (تاریخ آخرین به روز رسانی این آموزش).
Docker Hub به طور پیشفرض تصاویر قدیمی را حذف نمیکند، بنابراین این امکان را به شما میدهد تا تاریخچهای از تمام تصاویری که به رجیستری فشار دادهاید داشته باشید. تصویر با آخرین برچسب همیشه همانی است که اخیرا ساخته شده است، در حالی که عکس های قدیمی تر با تاریخ برچسب گذاری می شوند.
مرحله 3 – تصویر را فشار دهید
اکنون که تصویر را داریم، باید آن را به رجیستری فشار دهیم. اول از همه، دستور زیر را اجرا کنید تا مطمئن شوید که نمونه Docker شما با Docker Hub احراز هویت شده است:
docker login
سپس docker push را برای آپلود تصویر همراه با تمام تگ ها اجرا کنید.
docker push username/myproject
اگر برنامه شما کوچک است، این دستور باید سریع تکمیل شود، زیرا فقط باید لایه های مربوط به برنامه Node.js و وابستگی های جاوا اسکریپت آن را آپلود کند.
هنگامی که نسخه جدیدی از تصویر دارید، باید دستور فشار را دوباره اجرا کنید تا مطمئن شوید که در Docker Hub آپلود شده است.
مرحله 4 – Docker را در اوبونتو 24.04 نصب کنید
اکنون می توانیم برای نصب Docker و Docker Compose به سرور برویم. همانطور که در پیش نیازها ذکر شد، فرض در اینجا این است که شما یک سرور اوبونتو 24.04 دارید که در حال حاضر راه اندازی شده است.
اول از همه، نصب Docker به برخی از وابستگیهای سیستمی نیاز دارد که با دستورات زیر قابل نصب هستند:
sudo apt-get update
sudo apt-get install ca-certificates curl
اکنون کلید رسمی Docker GPG را اضافه کنید و یک مخزن سفارشی apt را پیکربندی کنید:
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
در نهایت، دوباره فهرست apt را بهروزرسانی کنید و Docker Community Edition را نصب کنید:
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
دستور بالا همچنین Docker Compose را نصب می کند، ابزاری که مدیریت کانتینرها و چرخه عمر آنها را بسیار ساده می کند.
آخرین مرحله مفید شامل افزودن کاربر فعلی اوبونتو به گروه docker است تا بتوانیم دستورات Docker را مستقیماً از آن اجرا کنیم.
این کار به راحتی با دستور زیر قابل انجام است:
sudo gpasswd -a myuser docker
با اجرای دستورات زیر مطمئن شوید که همه چیز خوب پیش رفته است:
docker --version
docker ps
docker compose version
اگر هیچ خطایی یا اخطاری مشاهده نکردید، خوب هستید که بروید.
مرحله 5 – کانتینر را با Docker Compose اجرا کنید
فایلی به نام docker-compose.yml با محتوای زیر در سرور خود ایجاد کنید:
services:
myproject:
container_name: 'myproject'
image: 'username/myproject'
restart: unless-stopped
این یک فایل بسیار ابتدایی Docker Compose است که یک ظرف واحد به نام myproject را بر اساس نام کاربری/تصویر myproject از Docker Hub پیکربندی میکند. اگر برچسبی را مشخص نکنید، به طور پیشفرض روی آخرین خواهد بود، اما در صورت تمایل میتوانید یک برچسب خاص را نیز تنظیم کنید:
services:
myproject:
container_name: 'myproject'
image: 'username/myproject:20240904'
restart: unless-stopped
در نهایت، ویژگی restart نشان می دهد که کانتینر باید به طور خودکار در هنگام خرابی مجدد راه اندازی شود، مگر اینکه به صورت دستی متوقف شود.
اگر اکنون این دستور Compose را اجرا کنید، تصویر Docker از رجیستری خارج می شود و برنامه شما امیدوار است اجرا شود:
docker compose -f docker-compose.yml up
این دستور یک کانتینر ایجاد می کند و آن را اجرا می کند. خروجی کانتینر توسط داکر گرفته می شود و در کنسول به شما ارائه می شود. CTRL + C (یا CMD + C) را فشار دهید و چند ثانیه صبر کنید تا ظرف متوقف شود.
اگر همه چیز خوب پیش رفت، اکنون آماده راهاندازی کانتینر بهعنوان یک شبح هستید، به طوری که در پسزمینه به کار خود ادامه میدهد تا زمانی که متوقف شود. این را می توان با افزودن گزینه -d به دستور به دست آورد:
docker compose -f docker-compose.yml up -d
بوم، گره! (اوه، منظورم تمام شد)
مطمئن شوید که نگاهی سریع به مستندات مرجع فایل Compose بیندازید، جایی که میتوانید ویژگیهای مفیدی مانند نگاشت پورتهای شبکه بین سرور و کانتینر را بیابید. در اینجا یک مثال سریع وجود دارد که درگاه خارجی 80 را به درگاه داخلی 8080 نگاشت می کند:
services:
myproject:
container_name: 'myproject'
image: 'username/myproject'
restart: unless-stopped
ports:
- '80:8080'
مرحله 6 – یک نسخه جدید را نصب کنید
فرض کنید باید تغییری در برنامه خود منتشر کنید. مگر اینکه ساختهای خودکار را فعال کرده باشید، باید مراحل 2 و 3 را تکرار کنید تا یک تصویر جدید در Docker Hub ظاهر شود.
سپس، در سرور خود، باید تصویر جدید را به صورت دستی بکشید، مانند این:
docker compose -f docker-compose.yml pull
و ظرف را با تصویر جدید راه اندازی مجدد کنید:
docker compose -f docker-compose.yml up -d --force-recreate
نتیجه
عالی، شما آن را انجام دادید! این مقدمه اولیه برای استقرار یک برنامه Node.js در اوبونتو 24.04 با استفاده از Docker، Docker Hub و Docker Compose بود.
ما دیدیم که چگونه یک Dockerfile ساده بنویسیم، چگونه تصویر را بسازیم، آن را فشار دهیم و آن را بر روی سرور مستقر کنیم.
چیزهای بیشتری در مورد Docker وجود دارد که توسط این آموزش پوشش داده نمی شود، بنابراین مطمئن شوید که نگاهی به مستندات Docker و Docker Compose بیندازید تا در مورد مفاهیم و ویژگی ها بیشتر بدانید.