استقرار یک برنامه MERN در AWS Elastic Beanstalk با CI/CD

در مقاله قبلی «استقرار خودکار برنامه MERN با GitHub Actions CI/CD»، تا فشار دادن تصاویر به هاب داکر یاد گرفتیم. تا اینجا شما کار بسیار خوبی انجام داده اید! اما این کافی نیست. ما اکنون به سروری نیاز داریم که کانتینرهای ما را 24 ساعت شبانه روز و هفت روز هفته اجرا کند و برای هر کسی که به اینترنت متصل است قابل دسترسی باشد. راه اندازی سرور خود ایده خوبی نیست 😅. بنابراین ما باید یک سرور اجاره کنیم. در این مقاله خواهید آموخت که چه کسی سرور اجاره ای را به ما می دهد و چگونه آن را راه اندازی کنیم.
بیا شروع کنیم
پیش نیازها
- اگر آموزش های قبلی این مجموعه را دنبال نکرده اید، کد منبع را از اینجا دریافت کنید.
- مقالات قبلی این مجموعه را بخوانید تا دچار سردرگمی نشوید.
-
حساب AWS.
- تمام سرویسهای AWS که در این آموزش استفاده میکنیم رایگان هستند اما برای ایجاد حساب کاربری به کارت اعتباری/دبیت نیاز دارید.
قبل از ادامه، توجه داشته باشید که برنامه بهره وری فوق العاده ساده ما به AWS نیاز ندارد. این فقط برای اهداف یادگیری است.
⚠️ هشدار: فراموش نکنید که به محض اتمام این آموزش، هر نمونه و محیط در حال اجرا را خاموش کنید تا از دریافت صورتحساب جلوگیری کنید.
AWS چیست؟
همانطور که در ابتدا ذکر کردم، ما به شخصی نیاز داریم که به ما اجازه دهد سرور اجاره کنیم و AWS در مورد آن است. نه از نظر فیزیکی مانند یک اتاق و دستهای از جعبهها، اما در فضای ابری به این معنی است که میتوانید سرورها را از هر نقطهای در جهان اجاره کنید.
اگر سرورهای خود را به صورت فیزیکی راه اندازی کنید اینگونه به نظر می رسد 😂:
اگر زیر یک سنگ زندگی نکرده اید، احتمالاً نام AWS را شنیده اید. مخفف آن است آمرد دبلیوeb اسخدمات AWS (توسط آمازون) طیف گسترده ای از خدمات رایانش ابری، مانند محاسبات، ذخیره سازی، پایگاه داده، تجزیه و تحلیل، یادگیری ماشینی، شبکه، موبایل، ابزارهای توسعه دهنده، امنیت و برنامه های کاربردی سازمانی را ارائه می دهد. برای همه نیازهای شما، نیازی به راه اندازی سرورهای خود را از بین می برد. این یک زیرساخت انعطافپذیر و مقیاسپذیر را فراهم میکند که میتواند برای نیازهای منحصربهفرد هر کاربر تنظیم شود، و به طور گستردهای به عنوان یکی از پلتفرمهای ابری پیشرو در دسترس امروزی در نظر گرفته میشود. Google Cloud (توسط گوگل) و Azure (توسط مایکروسافت) هر دو رقبای اصلی AWS هستند.
زمان بزرگ مغز 💡: اگر از ابتدا دنبال میکنید، در اولین مقاله «بیایید یک برنامه وب MERN را با پشته کامل بسازیم و مستقر کنیم»، برنامه frontend خود را در Netlify و بکاند را در Heroku مستقر کردیم. اینها خوب هستند اما اکثر شرکت ها به IaaS (زیرساخت به عنوان سرور) از PaaS (پلتفرم به عنوان سرور) نیاز دارند.
زیرساخت به عنوان یک سرویس (IaaS) در مقابل پلت فرم به عنوان یک سرویس (PaaS)
این تصویر به وضوح تفاوت بین Iaas و PaaS را نشان می دهد:
راه اندازی NGINX
NGINX یک وب سرور محبوب است که اغلب به عنوان متعادل کننده بار، پروکسی معکوس و کش HTTP استفاده می شود. آن را یک کنترل کننده ترافیک در نظر بگیرید که ترافیک را در چندین سرور بر اساس میزان اشغال یک سرور مدیریت می کند.
به عنوان یک پروکسی معکوس، NGINX به عنوان یک رابط بین مشتری و سرور عمل می کند. هنگامی که شما (کلاینت) درخواستی را به سرور ارسال می کنید، از طریق پروکسی معکوس و سپس به وب سرور هدایت می شود. این پراکسی معکوس از چند جهت مفید است: میتواند درخواستها را در چندین سرور توزیع کند، محتوای درخواستی مکرر را حافظه پنهان کند، زمان پاسخ را کاهش دهد و در برابر درخواستهای مخرب محافظت کند.
اگر میخواهید درباره NGINX بیشتر بدانید، توصیه میکنم «راهنمای NGINX» نوشته فرهان حسن چاودری را در freeCodeCamp بخوانید.
باشه! چرا ما اهمیت می دهیم؟ به جای استقرار فرانت اند و باطن به طور جداگانه، می توانیم به سادگی از یک متعادل کننده بار مانند NGINX استفاده کنیم تا هر دو فرانت اند و باطن را در یک وب سرور ترکیب کنیم، که سپس می تواند درخواست های دریافتی را بر اساس نوع درخواست و بار سرور به سرور مناسب توزیع کند. این فرآیند استقرار را ساده می کند و به اطمینان از عملکرد بهتر و مقیاس پذیری برنامه کمک می کند.
پیکربندی NGINX
پروژه را در ویرایشگر کد خود باز کنید. در root یک پوشه به نام ایجاد کنید nginx
.
در آن پوشه، یک فایل به نام ایجاد کنید nginx.conf
و این کد را قرار دهید.
# Defining a server group called `client` that has one server in it called `client` on port `3000`.
upstream client {
server client:3000;
}
# Defining a server group called `server` that has one server in it called `server` on port `5000`.
upstream server {
server server:5000;
}
# Listening on port 80 and redirecting requests to the client and server.
server {
listen 80;
listen [::]:80;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
location / {
proxy_pass http://client;
}
location /server {
rewrite /server/(.*) /$1 break;
proxy_pass http://server;
}
}
- را
upstream
دستورالعمل برای تعریف گروه های سرور، یکی برایclient
در بندر3000
و دیگری برایserver
در بندر5000
. - را
server
دستورالعمل برای تعریف سروری که در پورت گوش می دهد استفاده می شود80
برای درخواست های دریافتی راlisten
دستورالعمل پورت وproxy_http_version
،proxy_set_header
، وproxy_cache_bypass
دستورالعمل ها برای پیکربندی تنظیمات پراکسی استفاده می شوند. - را
location
دستورالعمل برای تعریف مسیرهای URL که به هر گروه سرور هدایت می شوند استفاده می شود. اولینlocation /
دستورالعمل همه درخواست ها را بهclient
گروه سرور دومینlocation /server
دستورالعمل هر درخواستی را با مسیر مطابقت می دهد/server
و استفاده می کندrewrite
بخشنامه حذف/server
از مسیر قبل از تغییر مسیر بهserver
گروه سرور با استفاده ازproxy_pass
بخشنامه
حتی من برای اولین بار از NGINX استفاده می کنم، بنابراین لطفاً مقاله ای را که در بالا ذکر کردم بخوانید تا به وضوح نحوه نوشتن فایل های پیکربندی NGINX را درک کنید.
اکنون، Dockerfile را در همان پوشه ایجاد کنید و آن را Paste کنید.
FROM nginx:stable-alpine
RUN rm /etc/nginx/conf.d/*
COPY ./nginx.conf /etc/nginx/conf.d/
CMD [ "nginx", "-g", "daemon off;" ]
راه اندازی AWS
ما قصد داریم از سه سرویس AWS استفاده کنیم:
1) Elastic Beanstalk – یک سرویس کاملاً مدیریت شده که استقرار برنامه ها را آسان می کند.
2) EC2 – Elastic Compute یک سرویس محاسباتی است که ظرفیت محاسباتی مقیاس پذیر را ارائه می دهد. شما می توانید به سرعت یک ماشین مجازی را با تنظیمات دلخواه خود مانند سیستم عامل، نرم افزار، ذخیره سازی و غیره راه اندازی کنید.
3) سطل S3 – یک سرویس ذخیره سازی بسیار مقیاس پذیر. تمام داده های برنامه شما در اینجا ذخیره می شود.
فقط Elastic Beanstalk باید پیکربندی شود. دو مورد دیگر به طور خودکار پیکربندی می شوند.
بنابراین، پیش بروید و وارد کنسول مدیریت AWS خود شوید.
یک کاربر ایجاد کنید
برای شروع، باید کاربری ایجاد کنیم که منابع ابری را مدیریت کند. از آنجایی که ما در حال خودکار کردن استقرار با GitHub Actions هستیم، به روشی برای Actions نیاز داریم تا منابع ما را تغییر دهد، مانند استقرار کد در AWS، و این همان چیزی است که این کاربر برای آن است. مطمئن شوید که مجوزهای مناسب را اعطا کرده اید.
در نوار جستجو، “IAM” (Identity and Access Management) را تایپ کرده و روی آن کلیک کنید کاربران زیر مدیریت دسترسی.
را کلیک کنید کاربران را اضافه کنید و به کاربر خود یک نام بدهید -> کلیک کنید بعد.
که در مجوزها را تنظیم کنید انتخاب کنید خط مشی ها را مستقیماً ضمیمه کنید -> بررسی کنید AdministratorAccess-AWSElasticBeanstalk -> کلیک کنید بعد -> در نهایت کلیک کنید کاربر ایجاد کنید.
برنامه ای را در Elastic Beanstalk ایجاد و پیکربندی کنید
دوباره در نوار جستجو، “Elastic Beanstalk” را تایپ کنید.
کلیک ایجاد اپلیکیشن.
به درخواست خود یک نام بدهید، ترک کنید برچسب های برنامه خالی، “Docker” را به عنوان انتخاب کنید سکوو بقیه را پیش فرض بگذارید. کلیک ایجاد اپلیکیشن.
تبریک 🎊! برنامه شما ایجاد شده است. می توانید با کلیک روی URL نشان داده شده در محیط برنامه از آن بازدید کنید. این یک نمونه برنامه ارائه شده توسط EB است.
پیکربندی متغیرهای محیطی
قبل از استقرار برنامه خود، باید متغیرهای محیطی را در EB اضافه کنیم.
برای انجام این کار، به برنامه بروید صفحه پیکربندی و کلیک کنید ویرایش کنید زیر نرم افزار دسته بندی.
به پایین صفحه -> زیر بروید متغیرهای محیطی و متغیرهای env زیر را اضافه کنید.
REACT_APP_BACKEND_URL = /server
MONGODB_URI = your MongoDB URI
TOKEN_KEY = random string
EMAIL = email
PASSWORD = password
خودشه! اکنون زمان آن است که مرحله استقرار را به خط لوله CI/CD خود اضافه کنیم.
استقرار برنامه MERN در AWS با CI/CD
باز کن pipeline.yml
و این مرحله را درست در زیر فشار دادن تصاویر به مرحله داکر هاب اضافه کنید.
# This is the step that is deploying the application to Elastic Beanstalk.
- name: Deploy to Elastic Beanstalk
uses: einaregilsson/beanstalk-deploy@v21
with:
aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
application_name: ${{ secrets.EB_APP_NAME }}
environment_name: ${{ secrets.EB_ENV_NAME }}
region: ${{ secrets.EB_REGION }}
version_label: "version-${{ github.run_number }}"
deployment_package: docker-compose.yml
- در اینجا ما از یک اکشن GitHub از پیش تعریف شده استفاده می کنیم
einaregilsson/beanstalk-deploy@v21
تا نیازی به نوشتن از ابتدا نداشته باشیم. نیازی به توضیح نیست، خیلی ساده است. - اضافه کردن
AWS_ACCESS_KEY_ID
،AWS_SECRET_ACCESS_KEY
به اسرار GitHub. می توانید اینها را از داشبورد IAM دریافت کنید. فقط روی کاربری که ایجاد کردید کلیک کنید و به آن بروید مدارک امنیتی را برگه و از آنجا کپی کنید. -
EB_APP_NAME
نام برنامه EB شما است وEB_ENV_NAME
نام محیط برنامه شما است (به “-env” ختم می شود، در مورد من “Productivityapp-env” است). -
EB_REGION
منطقه ای است که به شما اختصاص داده شده است.
از آنجایی که docker-compose نمیتواند متغیرهای محیط GitHub را بخواند، اکنون در حال ایجاد یک تصویر دوم با کلمه “آخرین” در انتهای تگ تصویر به جای github.run_number
. این فایل نهایی YAML است. (در صورت تمایل می توانید یک تصویر واحد بسازید، فقط برچسب را با آن حذف کنید github.run_number
)
# The name of the workflow.
name: Build and Deploy
# Run the workflow when code is pushed to the main branch
on:
push:
branches:
- main
# Set environment variables
env:
MONGODB_URI: ${{ secrets.MONGODB_URI }}
TOKEN_KEY: ${{ secrets.TOKEN_KEY }}
EMAIL: ${{ secrets.EMAIL }}
PASSWORD: ${{ secrets.PASSWORD }}
# This is the workflow that is being run.
jobs:
build-and-deploy:
# This is telling GitHub to run the workflow on the latest version of Ubuntu.
runs-on: ubuntu-latest
steps:
# Checkout the code from the GitHub repository
- name: Checkout code
uses: actions/checkout@v3
# Install dependencies and run tests for the client application
- name: Install and Test Client
working-directory: ./client
run: |
npm install
npm run test
# Install dependencies, export environment variables to be used by application and run tests for the server application
- name: Install and Test Server
working-directory: ./server
run: |
npm install
export MONGODB_URI=$MONGODB_URI
export TOKEN_KEY=$TOKEN_KEY
export EMAIL=$EMAIL
export PASSWORD=$PASSWORD
npm run test
# Build a Docker image for the client application
- name: Build Client Docker Image
working-directory: ./client
# Build image with tag rakeshpotnuru/productivity-app:client
run: |
docker build -t rakeshpotnuru/productivity-app:client-${{github.run_number}} -t rakeshpotnuru/productivity-app:client-latest .
# Build a Docker image for the server application
- name: Build Server Docker Image
working-directory:
./server
# Build image with tag rakeshpotnuru/productivity-app:server
run: |
docker build -t rakeshpotnuru/productivity-app:server-${{github.run_number}} -t rakeshpotnuru/productivity-app:server-latest .
# Build a Docker image for the NGINX reverse proxy
- name: Build NGINX Docker Image
working-directory: ./nginx
# Build image with tag rakeshpotnuru/productivity-app:nginx
run: |
docker build -t rakeshpotnuru/productivity-app:nginx-${{github.run_number}} -t rakeshpotnuru/productivity-app:nginx-latest .
# Login to Docker Hub using credentials from repository secrets
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
# Push the Docker images to Docker Hub
- name: Push Docker Images to Docker Hub
run: |
docker push rakeshpotnuru/productivity-app:client-${{github.run_number}}
docker push rakeshpotnuru/productivity-app:server-${{github.run_number}}
docker push rakeshpotnuru/productivity-app:nginx-${{github.run_number}}
docker push rakeshpotnuru/productivity-app:client-latest
docker push rakeshpotnuru/productivity-app:server-latest
docker push rakeshpotnuru/productivity-app:nginx-latest
# This is the step that is deploying the application to Elastic Beanstalk.
- name: Deploy to Elastic Beanstalk
uses: einaregilsson/beanstalk-deploy@v21
with:
aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
application_name: ${{ secrets.EB_APP_NAME }}
environment_name: ${{ secrets.EB_ENV_NAME }}
region: ${{ secrets.EB_REGION }}
version_label: "version-${{ github.run_number }}"
deployment_package: docker-compose.yml
deployment_package
دو راه وجود دارد که می توانید یک بسته برای استقرار بسته ارائه دهید – 1. فایل فشرده یا 2. فایل docker-compose. از آنجایی که ما تصاویر را به هاب docker هل می دهیم، از آن استفاده خواهیم کرد docker-compose.yml
فایل.
نام قبلی را تغییر دهید docker-compose.yml
فایل به عنوان docker-compose.dev.yml
و جدید ایجاد کنید docker-compose.yml
فایل. این کد را جایگذاری کنید.
version: "3.8"
services:
nginx:
image: rakeshpotnuru/productivity-app:nginx-latest
restart: always
depends_on:
- client
- server
ports:
- "80:80"
client:
image: rakeshpotnuru/productivity-app:client-latest
environment:
- CHOKIDAR_USEPOLLING=true
- REACT_APP_BACKEND_URL=${REACT_APP_BACKEND_URL}
server:
image: rakeshpotnuru/productivity-app:server-latest
environment:
- MONGODB_URI=${MONGODB_URI}
- TOKEN_KEY=${TOKEN_KEY}
- EMAIL=${EMAIL}
- PASSWORD=${PASSWORD}
- به جای ساخت مجدد تصاویر Docker با Dockerfile، تصاویر از پیش ساخته شده را از Docker Hub می کشیم. و آن متغیرهای محیطی از متغیرهایی که قبلاً در محیط برنامه EB تعریف کردیم مشتق شدهاند.
همین! کد را به GitHub فشار دهید و اجازه دهید تمام بررسی ها در گردش کار GitHub Actions عبور کنند. شما می توانید برنامه خود را در عمل ببینید 🎉🚀🤩.
پایان دادن به محیط زیست
فراموش نکنید که پس از اتمام این آموزش، اگر دیگر از آن برنامه استفاده نمی کنید، محیط را خاتمه دهید.
برای خاتمه، به محیط ها -> محیطی را که می خواهید خاتمه دهید انتخاب کنید -> کلیک کنید اقدامات -> کلیک کنید محیط را خاتمه دهید. این کار همچنین هر نمونه ای را که توسط برنامه شما ایجاد شده بود، خاتمه می دهد.
اگر تا این حد از «بیایید یک برنامه وب MERN را با پشته کامل بسازیم و مستقر کنیم» فاصله گرفتهاید، آفرین. به خود شانه بزنید.
این پایان ماجرا نیست. بسیاری از مقالات هیجان انگیز در راه است! برای اطلاعات بیشتر من را دنبال کنید – به بعد و بالاتر 🚀!