اجرای برنامههای فلسک با داکر
# داکرایز کردن فلسک
Docker یک برنامه منبع باز است که به مدیران اجازه می دهد تا برنامه ها را با استفاده از کانتینرها ایجاد، مدیریت، استقرار و تکثیر کنند. کانتینرها را می توان به عنوان بسته ای در نظر گرفت که وابستگی هایی را در خود جای می دهد که یک برنامه برای اجرا در سطح سیستم عامل به آن نیاز دارد. این بدان معناست که هر برنامه کاربردی که با استفاده از Docker مستقر شده است در محیطی مخصوص به خود زندگی می کند و نیازهای آن به طور جداگانه بررسی می شود.
Flask یک میکرو فریمورک وب است که بر روی پایتون ساخته شده است. به آن میکرو فریمورک می گویند زیرا برای اجرا به ابزار یا پلاگین خاصی نیاز ندارد. فریم ورک Flask سبک و انعطاف پذیر است، در عین حال ساختار بسیار بالایی دارد و آن را نسبت به سایر فریم ورک ها ترجیح می دهد.
استقرار یک برنامه Flask با Docker به شما این امکان را می دهد که برنامه را در سرورهای مختلف با حداقل پیکربندی مجدد تکرار کنید.
در این آموزش، شما یک اپلیکیشن Flask ایجاد کرده و آن را با Docker اجرا می کنید. این آموزش همچنین نحوه به روز رسانی یک برنامه پس از استقرار را پوشش می دهد.
برای اینکه بتوانید با این آموزش هماهنگ باشید، باید فلسک، داکر را بلد باشید. برای یادگیری این موارد میتوانید دوره آموزش داکر و دوره آموزش فلسک را مشاهده کنید.
# راه اندازی برنامه فلسک
برای شروع، یک دایرکتوری ایجاد خواهید کرد که برنامه Flask شما را نگه می دارد. این آموزش یک دایرکتوری به نام TestApp در /var/www ایجاد میکند، اما میتوانید دستور را تغییر دهید تا نام آن را هر چه میخواهید تغییر دهید.
sudo mkdir /var/www/TestApp
به دایرکتوری جدید TestApp بروید:
cd /var/www/TestApp
سپس، پوشه پایه را برای برنامه Flask ایجاد کنید:
sudo mkdir -p app/static app/templates
پرچم -p نشان می دهد که mkdir یک دایرکتوری و همه دایرکتوری های والد که وجود ندارند ایجاد می کند. در این حالت، mkdir دایرکتوری والد برنامه را در فرآیند ساخت دایرکتوری های استاتیک و قالب ها ایجاد می کند.
دایرکتوری app شامل تمام فایل های مربوط به برنامه Flask مانند views و blueprints آن خواهد بود. viewها کدهایی هستند که برای پاسخ به درخواست های برنامه خود می نویسید. بلوپرینت اجزای برنامه را ایجاد می کند و از الگوهای رایج در یک برنامه یا در چندین برنامه پشتیبانی می کند.
دایرکتوری static جایی است که دارایی هایی مانند تصاویر، CSS و فایل های جاوا اسکریپت در آن زندگی می کنند. دایرکتوری templates جایی است که شما قالب های HTML را برای پروژه خود قرار می دهید.
اکنون که ساختار پوشه پایه کامل شد، فایل های مورد نیاز برای اجرای برنامه Flask را ایجاد کنید. ابتدا یک فایل __init__.py در دایرکتوری app ایجاد کنید. این فایل به مفسر پایتون میگوید که دایرکتوری برنامه یک package است و باید با آن رفتار شود.
برای ایجاد فایل دستور زیر را اجرا کنید:
sudo touch app/__init__.py
packageهای موجود در پایتون به شما این امکان را میدهند که ماژولها را در فضای نام منطقی یا سلسله مراتب گروهبندی کنید. این رویکرد کد را قادر می سازد تا به بلوک های فردی و قابل مدیریت که عملکردهای خاصی را انجام می دهند، تجزیه شود.
در مرحله بعد، کدی را به __init__.py اضافه می کنید که یک نمونه Flask ایجاد می کند و منطق را از فایل views.py وارد می کند، که پس از ذخیره این فایل، آن را ایجاد می کنید. کد زیر را به فایل جدید خود اضافه کنید:
from flask import Flask
app = Flask(__name__)
from app import views
با ایجاد فایل __init__.py، آماده ایجاد فایل views.py در دایرکتوری app خود هستید. این فایل شامل بیشتر منطق برنامه شما خواهد بود.
sudo touch app/views.py
سپس کد را به فایل views.py خود اضافه کنید. این کد hello world را برمی گرداند! رشته به کاربرانی که از صفحه وب شما بازدید می کنند:
from app import app
@app.route('/')
def home():
return "hello world!"
خط @app.route بالای تابع، دکوراتور نامیده می شود. دکوراتورها تابعی را که به دنبال آن است تغییر می دهند. در این حالت، دکوراتور به Flask می گوید که کدام URL تابع home() را راه اندازی می کند. متن hello world که توسط تابع home برگردانده شده است در مرورگر به کاربر نمایش داده می شود.
با قرار دادن فایل views.py، آماده ایجاد فایل uwsgi.ini هستید. این فایل شامل تنظیمات uWSGI برای برنامه ما خواهد بود. uWSGI یک گزینه استقرار برای Nginx است که هم یک پروتکل و هم یک سرور برنامه است. سرور برنامه می تواند پروتکل های uWSGI، FastCGI و HTTP را ارائه دهد.
برای ایجاد این فایل، دستور زیر را اجرا کنید:
sudo touch uwsgi.ini
سپس محتوای زیر را به فایل خود اضافه کنید تا سرور uWSGI را پیکربندی کنید:
[uwsgi]
module = main
callable = app
master = true
این کد ماژولی را تعریف می کند که برنامه Flask از آن ارائه می شود. در این مورد، فایل main.py است که در اینجا به عنوان main ارجاع شده است. گزینه callable به uWSGI دستور می دهد از آبجکت app صادر شده توسط برنامه اصلی استفاده کند. گزینه master به برنامه شما اجازه می دهد تا به کار خود ادامه دهد، بنابراین حتی در هنگام بارگیری مجدد کل برنامه، خرابی کمی وجود دارد.
در مرحله بعد، فایل main.py را ایجاد کنید که نقطه ورود به برنامه است. نقطه ورود به uWSGI نحوه تعامل با برنامه را مشخص میکند.
sudo touch main.py
سپس موارد زیر را کپی و در فایل پیست کنید. این برنامه نمونه Flask با نام app را از بسته برنامه ای که قبلا ایجاد شده بود وارد می کند.
from app import app
در نهایت، یک فایل requirements.txt ایجاد کنید تا وابستگی هایی را که مدیر بسته pip در استقرار Docker شما نصب می کند، مشخص کنید:
sudo nano requirements.txt
خط زیر را برای اضافه کردن Flask به عنوان یک وابستگی اضافه کنید:
Flask==1.0.2
این نسخه فلسک را که قرار است نصب شود مشخص می کند. در زمان نوشتن این آموزش، 1.0.2 آخرین نسخه Flask است. میتوانید بهروزرسانیها را در وبسایت رسمی Flask بررسی کنید.
ذخیره کنید و فایل را ببندید. شما با موفقیت برنامه Flask خود را راه اندازی کرده اید و آماده راه اندازی Docker هستید.
ویدیو پیشنهادی: ویدیو آموزش حرفهای دکوراتورها در پایتون
# راه اندازی Docker
در این مرحله شما دو فایل Dockerfile و start.sh را برای ایجاد استقرار Docker خود ایجاد خواهید کرد. Dockerfile یک سند متنی است که حاوی دستورات مورد استفاده برای جمع آوری image است. فایل start.sh یک اسکریپت shell است که یک image می سازد و یک container از Dockerfile ایجاد می کند.
ابتدا Dockerfile را ایجاد کنید:
sudo touch Dockerfile
سپس پیکربندی مورد نظر خود را به Dockerfile اضافه کنید. این دستورات مشخص میکنند که image چگونه ساخته میشود و چه نیازهای اضافی را شامل میشود.
FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7
RUN apk --update add bash nano
ENV STATIC_URL /static
ENV STATIC_PATH /var/www/app/static
COPY ./requirements.txt /var/www/requirements.txt
RUN pip install -r /var/www/requirements.txt
در این مثال، image داکر از یک ایمیج موجود، tiangolo/uwsgi-nginx-flask ساخته میشود که میتوانید آن را در DockerHub پیدا کنید. این ایمیج خاص Docker انتخاب خوبی نسبت به سایرین است زیرا از طیف گسترده ای از نسخه های Python و ایمیج سیستم عامل پشتیبانی می کند.
دو خط اول image والد را مشخص می کند که از آن برای اجرای برنامه و نصب پردازنده فرمان bash و ویرایشگر متن نانو استفاده می کنید. همچنین سرویس گیرنده git را برای push و pull به سرویس های میزبانی کنترل نسخه مانند GitHub، GitLab و Bitbucket نصب می کند. ENV STATIC_URL /static یک متغیر محیطی مخصوص این image داکر است. این پوشه static را تعریف می کند که در آن همه دارایی ها مانند تصاویر، فایل های CSS و فایل های جاوا اسکریپت از آن ارائه می شوند.
دو خط آخر فایل requirements.txt را در کانتینر کپی می کند تا بتوان آن را اجرا کرد و سپس فایل requirements.txt را برای نصب وابستگی های مشخص شده تجزیه می کند.
پس از افزودن تنظیمات فایل را ذخیره کرده و ببندید.
با نصب Dockerfile، تقریباً آماده نوشتن اسکریپت start.sh خود هستید که کانتینر Docker را میسازد. قبل از نوشتن اسکریپت start.sh، ابتدا مطمئن شوید که یک پورت باز برای استفاده در پیکربندی دارید. برای بررسی رایگان بودن پورت، دستور زیر را اجرا کنید:
sudo nc localhost 56733 < /dev/null; echo $?
اگر خروجی دستور بالا 1 باشد، پورت رایگان و قابل استفاده است. در غیر این صورت، باید پورت دیگری را برای استفاده در فایل پیکربندی start.sh انتخاب کنید.
هنگامی که یک پورت باز برای استفاده پیدا کردید، اسکریپت start.sh را ایجاد کنید:
sudo nano start.sh
اسکریپت start.sh یک اسکریپت shell است که یک image از Dockerfile میسازد و یک کانتینر از ایمیج Docker ایجاد میکند. تنظیمات خود را به فایل جدید اضافه کنید:
#!/bin/bash
app="docker.test"
docker build -t ${app} .
docker run -d -p 56733:80 \
--name=${app} \
-v $PWD:/app ${app}
خط اول shebang نامیده می شود. مشخص می کند که این یک فایل bash است و به صورت دستور اجرا می شود. خط بعدی نامی را که میخواهید به image و container بدهید مشخص میکند و بهعنوان متغیری با نام app ذخیره میشود. خط بعدی به Docker دستور می دهد تا یک image از Dockerfile شما که در دایرکتوری فعلی قرار دارد بسازد. با این کار تصویری به نام docker.test در این مثال ایجاد می شود.
سه خط آخر یک کانتینر جدید به نام docker.test ایجاد می کند که در پورت 56733 در معرض دید قرار می گیرد. در نهایت، دایرکتوری حاضر را به فهرست /var/www کانتینر پیوند می دهد.
شما از پرچم -d برای شروع یک کانتینر در حالت daemon یا به عنوان یک فرآیند پسزمینه استفاده میکنید. شما پرچم -p را برای اتصال یک پورت روی سرور به یک پورت خاص در کانتینر Docker اضافه میکنید. در این حالت، پورت 56733 را به پورت 80 روی ظرف داکر متصل می کنید. پرچم -v یک volume داکر را مشخص میکند تا روی کانتینر نصب شود، و در این حالت، شما کل فهرست پروژه را در پوشه /var/www روی ظرف Docker قرار میدهید.
اسکریپت start.sh را برای ایجاد ایمیج Docker اجرا کنید و یک کانتینر از ایمیج حاصل بسازید:
sudo bash start.sh
پس از اتمام اجرای اسکریپت، از دستور زیر برای لیست کردن تمام کانتینرهای در حال اجرا استفاده کنید:
sudo docker ps
خروجی دریافت خواهید کرد که کانتینرها را نشان می دهد:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
58b05508f4dd docker.test "/entrypoint.sh /sta…" 12 seconds ago Up 3 seconds 443/tcp, 0.0.0.0:56733->80/tcp docker.test
متوجه خواهید شد که کانتینر docker.test در حال اجرا است. اکنون که در حال اجرا است، به آدرس IP در پورت مشخص شده در مرورگر خود مراجعه کنید: http://ip-address:56733
صفحه ای شبیه به زیر می بینید:
در این مرحله شما با موفقیت برنامه Flask خود را در Docker مستقر کرده اید. در مرحله بعد از قالب هایی برای نمایش محتوا به کاربران استفاده خواهید کرد.
دوره پیشنهادی: دوره آموزش shell scripting
# ارائه فایلهای template
قالب ها فایل هایی هستند که محتوای ایستا و پویا را برای کاربرانی که از برنامه شما بازدید می کنند نمایش می دهند. در این مرحله شما یک قالب HTML برای ایجاد صفحه اصلی برای اپلیکیشن ایجاد می کنید.
با ایجاد یک فایل home.html در دایرکتوری app/templates شروع کنید:
sudo touch app/templates/home.html
کد قالب خود را اضافه کنید. این کد یک صفحه HTML5 ایجاد می کند که حاوی یک عنوان و مقداری متن است.
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Welcome home</title>
</head>
<body>
<h1>Home Page</h1>
<p>This is the home page of our application.</p>
</body>
</html>
سپس، فایل app/views.py را تغییر دهید تا فایل جدید ایجاد شده را ارائه دهد:
sudo nano app/views.py
خط زیر را در ابتدای فایل خود اضافه کنید تا متد render_template از Flask وارد شود. این روش یک فایل HTML را برای ارائه یک صفحه وب به کاربر تجزیه می کند.
from flask import render_template
...
در پایان فایل، یک مسیر جدید نیز برای رندر فایل قالب اضافه خواهید کرد. این کد مشخص می کند که هر زمان که کاربران از مسیر template / در برنامه شما بازدید می کنند، محتویات فایل home.html ارائه می شود.
...
@app.route('/template')
def template():
return render_template('home.html')
فایل app/views.py به روز شده به شکل زیر خواهد بود:
from flask import render_template
from app import app
@app.route('/')
def home():
return "Hello world!"
@app.route('/template')
def template():
return render_template('home.html')
برای اعمال این تغییرات، باید کانتینرهای Docker را متوقف کرده و مجددا راه اندازی کنید. دستور زیر را برای بازسازی کانتینر اجرا کنید:
sudo docker stop docker.test && sudo docker start docker.test
برای مشاهده template جدید در حال ارائه به برنامه خود در http://your-ip-address:56733/template مراجعه کنید.
در این مورد شما یک فایل قالب داکر را ایجاد کرده اید تا به بازدیدکنندگان برنامه خود خدمات ارائه دهد. در مرحله بعدی خواهید دید که چگونه تغییراتی که در برنامه خود ایجاد می کنید می توانند بدون نیاز به راه اندازی مجدد کانتینر Docker اعمال شوند.
مقاله پیشنهادی: دوره آموزش پایتون (python)
# بروزرسانی برنامه
گاهی اوقات شما نیاز به ایجاد تغییرات در برنامه دارید، خواه در مورد نصب نیازمندی های جدید، به روز رسانی کانتینر Docker یا تغییرات HTML و منطقی باشد. در این بخش، touch-reload را پیکربندی میکنید تا این تغییرات را بدون نیاز به راهاندازی مجدد کانتینر Docker انجام دهید.
autoreloading پایتون کل سیستم فایل را برای تغییرات مشاهده می کند و زمانی که برنامه تغییری را تشخیص می دهد، آن را به روز می کند. بارگذاری مجدد خودکار در production منع می شود زیرا می تواند خیلی سریع به منابع فشرده تبدیل شود. در این مرحله، از touch-reload برای مشاهده تغییرات در یک فایل خاص استفاده میکنید و زمانی که فایل بهروزرسانی یا جایگزین میشود، آن را بارگیری مجدد میکنید.
برای پیاده سازی این، با باز کردن فایل uwsgi.ini خود شروع کنید:
sudo nano uwsgi.ini
سپس خط آخر را به انتهای فایل اضافه کنید:
module = main
callable = app
master = true
touch-reload = /app/uwsgi.ini
این فایلی را مشخص میکند که برای راهاندازی مجدد کل برنامه تغییر میکند. پس از ایجاد تغییرات، فایل را ذخیره و ببندید.
برای نشان دادن این موضوع، یک تغییر کوچک در برنامه خود ایجاد کنید. با باز کردن فایل app/views.py خود شروع کنید:
sudo nano app/views.py
رشته برگشتی توسط تابع home را جایگزین کنید:
from flask import render_template
from app import app
@app.route('/')
def home():
return "<b>There has been a change</b>" # <-- changed
@app.route('/template')
def template():
return render_template('home.html')
در مرحله بعد، اگر صفحه اصلی برنامه خود را در http://ip-address:56733 باز کنید، متوجه خواهید شد که تغییرات منعکس نمی شوند. دلیلش این است که شرط بارگذاری مجدد، تغییر در فایل uwsgi.ini است. برای بارگیری مجدد برنامه، از touch
برای فعال کردن شرایط استفاده کنید:
sudo touch uwsgi.ini
صفحه اصلی برنامه را دوباره در مرورگر خود بارگیری کنید. متوجه خواهید شد که برنامه تغییرات زیر را در خود جای داده است:
مقاله پیشنهادی: نحوه عیب یابی خطای رایج HTTP
# نتیجه گیری
در این آموزش، شما یک برنامه Flask را در یک کانتینر Docker ایجاد و مستقر کرده اید. شما همچنین touch-reload را برای بازخوانی برنامه خود بدون نیاز به راه اندازی مجدد ظرف پیکربندی کرده اید.