Wprowadzenie
Docker to otwarta platforma kontenerowa. Jest to lekkie, zwirtualizowane, przenośne, zdefiniowane programowo i standaryzowane środowisko, które pozwala oprogramowaniu działać w izolacji od innego oprogramowania uruchomionego na fizycznej maszynie hosta. Docker oferuje lekką alternatywę dla maszyn wirtualnych. Jednocześnie zapewnia przenośność, wydajność, elastyczność i skalowalność aplikacji. Aby uzyskać wyczerpujący przewodnik po ekosystemie Docker, zapoznaj się z naszym szczegółowym omówieniem konteneryzacji z użyciem Dockera.
Flask to otwartoźródłowy, minimalistyczny framework webowy zbudowany w języku Python. Do najważniejszych zalet Flask należy to, że jest lekki, elastyczny i wysoce ustrukturyzowany. Ponadto nie wymaga do działania żadnych konkretnych narzędzi ani wtyczek.
Połączenie Flask i Docker daje lekką, elastyczną i skalowalną aplikację. Możesz ją wdrożyć na wielu serwerach i infrastrukturach dzięki przenośności skonteneryzowanych aplikacji Dockera. Celem tego samouczka jest pokazanie, jak wdrożyć aplikację Flask za pomocą Dockera. Zademonstrujemy również, jak upewnić się, że przyszłe aktualizacje aplikacji wejdą w życie.
Wymagania wstępne
To będzie praktyczny samouczek, dlatego należy przygotować środowisko, które umożliwi wykonywanie kolejnych kroków:
- Powinieneś mieć zainstalowany system Ubuntu 20.04 jako początkowe środowisko operacyjne. Musisz również utworzyć użytkownika niebędącego rootem z uprawnieniami sudo.
- Dodatkowo musisz zainstalować Dockera. Mamy samouczek na temat tego, jak zainstalować i obsługiwać Dockera na Ubuntu. Wykonaj kroki 1, 2, 3 i 4. Powinno to działać na każdej dystrybucji Ubuntu.
- Na koniec musisz mieć zainstalowany Nginx. Postępuj zgodnie z naszym samouczkiem dotyczącym instalacji Nginx na Ubuntu.
Zaczynajmy!
Krok 1: Przygotowanie aplikacji Flask
Zaczniemy od utworzenia katalogu, w którym będzie znajdować się nasza aplikacja Flask. Możesz wybrać dowolną nazwę katalogu. Jednak na potrzeby tego samouczka nazwiemy go flask_demo. Pliki projektu zapiszemy wewnątrz katalogu /var/www, który jest zazwyczaj katalogiem, do którego Ubuntu domyślnie zezwala na dostęp z publicznego internetu. Najpierw wykonaj następujące polecenia, aby utworzyć katalog i do niego przejść:
|
1 2 3 |
sudo mkdir /var/www/flask_demo cd /var/www/flask_demo |
Wewnątrz tego głównego katalogu naszego projektu utworzymy podstawową strukturę folderów aplikacji Flask. Następnie wykonaj poniższe polecenie, aby utworzyć tę strukturę, dodając flagę -p, aby utworzyć po drodze wszystkie foldery nadrzędne:
|
1 |
sudo mkdir -p app/static app/templates |
Folder app zawiera wszystkie pliki powiązane z aplikacją Flask, w tym views oraz blueprints. Widoki (views) zawierają kod, który piszesz, aby odpowiadać na żądania trafiające do Twojej aplikacji. Blueprints pomagają w tworzeniu komponentów aplikacji i wspierają typowe wzorce w aplikacjach Flask.
Trafnie nazwany folder static przechowuje statyczne zasoby, takie jak obrazy, pliki CSS i JavaScript. Katalog templates zawiera wszystkie szablony HTML dla projektu.
Now możemy zacząć pisać pliki potrzebne do zainicjowania aplikacji Flask. Zacznij od utworzenia pliku o nazwie __init__.py wewnątrz katalogu app, aby poinformować interpreter Pythona o tym, że katalog app powinien być traktowany jako pakiet. Wykonaj następujące polecenie w terminalu, aby otworzyć plik w edytorze nano:
|
1 |
sudo nano app/__init__.py |
Pakiety w Pythonie służą do grupowania modułów w logiczne przestrzenie nazw lub hierarchie. Modularyzacja pozwala na podział kodu na pojedyncze i łatwe w zarządzaniu bloki, które wykonują określone funkcje.
Następnie, wewnątrz pliku __init__.py otwartego w edytorze, dodaj poniższy fragment kodu, aby uruchomić instancję Flask i zaimportować logikę z pliku views.py, który utworzysz w kolejnych krokach:
|
1 2 3 4 5 |
from flask import Flask app = Flask(__name__) from app import views |
Po zakończeniu naciśnij Ctrl + O oraz ENTER aby zapisać plik, a następnie zamknąć go za pomocą Ctrl + X. Następnie utwórzmy views.py wewnątrz app katalogu. Plik views.py będzie zawierał większość logiki aplikacji:
|
1 |
sudo nano app/views.py |
Wewnątrz pliku dodaj następujący fragment kodu. Ten kod wyświetli prosty ciąg znaków, aby pokazać, że Twoja aplikacja działa, gdy użytkownicy odwiedzają Twoją witrynę:
|
1 2 3 4 5 |
from app import app @app.route('/') def home(): return "Our Flask application is running!" |
W tym pliku zaczynamy od zaimportowania instancji aplikacji Flask. Następnie musimy dodać linię definiującą trasę: @app.route(/). Linia @app.route(/) jest określana jako dekorator w Flasku. Możesz używać dekoratorów do wstrzykiwania dodatkowych funkcjonalności do jednej lub większej liczby funkcji. W tym przypadku przekazujemy wywołanie trasy / do funkcji home. Gdy użytkownik odwiedzi tę trasę, zobaczy tekst: "Our Flask application is running!".
Następnie utworzysz plik uwsgi.ini zawierający konfiguracje uWSGI dla aplikacji. uWSGI to opcja wdrożeniowa dla Nginx, która służy jako protokół i serwer aplikacji. Uruchom następujące polecenie, aby utworzyć plik w katalogu głównym projektu za pomocą edytora nano:
|
1 |
sudo nano uwsgi.ini |
Wewnątrz otwartego pliku dodaj następujący fragment kodu:
|
1 2 3 4 |
[uwsgi] module = main callable = app master = true |
Ten plik zawiera kilka dyrektyw. Poniżej definiujemy ich cel:
- module – definiuje moduł, z którego będzie obsługiwana aplikacja Flask. Ustawiliśmy moduł jako main, odwołując się do pliku main.py w katalogu głównym. Utworzymy ten plik w następnym kroku.
- callable – kieruje uWSGI do użycia instancji app wyeksportowanej z aplikacji.
- master – zapewnia, że aplikacja działa nieprzerwanie, aby zminimalizować przestój podczas ponownego ładowania całej aplikacji.
Zapisz i zamknij plik, gdy skończysz.
Teraz możesz utworzyć plik main.py określający punkt wejścia do aplikacji. uWSGI odczyta ten plik, aby dowiedzieć się, jak wchodzić w interakcję z aplikacją. Uruchom następujące polecenie, aby utworzyć plik main.py za pomocą nano wewnątrz głównego katalogu swojego projektu:
|
1 |
sudo nano main.py |
Wewnątrz pliku dodaj następującą linię, która zaimportuje instancję Flask utworzoną w pakiecie aplikacji:
|
1 |
from app import app |
Ostatnią rzeczą, którą zrobisz w tym kroku, jest zdefiniowanie zależności niezbędnych do działania aplikacji. Zdefiniujemy te zależności w pliku o nazwie dependencies.txt. Gdy Docker buduje obraz Twojej aplikacji, wykona polecenie menedżera (pakietów pip) w celu zainstalowania zależności. Otwórz plik w katalogu głównym za pomocą następującego polecenia:
|
1 |
sudo nano dependencies.txt |
Do tego momentu w naszym projekcie chcemy tylko jednej zależności: Flask. Dlatego możemy dodać następującą linię, aby odwołać się do odpowiedniej wersji Flask, którą chcemy dla naszego projektu:
|
1 |
Flask==2.0.1 |
Decydujemy się na wersję Flask 2.0.1 jako zależność. Jest to najnowsza wersja w momencie pisania tego samouczka. Więcej informacji o różnych wersjach można znaleźć na stronie Flask Changes page. To kończy konfigurację aplikacji Flask. Teraz przygotujmy konfiguracje Dockera do wdrożenia.
Step 2: Configure Docker
Aby skonfigurować wdrożenie Dockera, utworzymy dwa pliki, Dockerfile oraz start.sh. Plik Dockerfile zawiera deklaratywne linie, które tworzą obraz Dockera. Plik start.sh to podstawowy skrypt powłoki służący do budowania obrazu i uruchamiania kontenera z Dockerfile. Będąc w katalogu głównym projektu, wykonaj następujące polecenie, aby utworzyć Dockerfile:
|
1 |
sudo nano Dockerfile |
Ten plik zawiera niezbędne konfiguracje dla obrazu Dockera. Następnie dodaj poniższy fragment kodu, aby określić zależności i sposób budowania obrazu:
|
1 2 3 4 5 6 7 8 9 10 11 |
FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7 RUN apk --update add bash nano git ENV STATIC_URL /static ENV STATIC_PATH /var/www/app/static COPY ./dependencies.txt /var/www/dependencies.txt RUN pip install -r /var/www/dependencies.txt |
Pierwsza linia w Dockerfile definiuje obraz bazowy, na podstawie którego budujemy nasz obraz. W tym przypadku będziemy budować w oparciu o tiangolo/uwsgi-nginx-flask, dostępny z DockerHub. Wybraliśmy ten konkretny obraz, ponieważ obsługuje on wiele wersji Pythona.
Określamy również, że chcemy zaktualizować obraz. Następnie musimy dodać procesor bash poleceń processo , nano edytor tekstowy, oraz git klienta do pobierania i wysyłania kodu źródłowego z repozytoriów kontroli wersji, takich jak GitHub, Bitbucket, lub Gitlab. Linie z ENV określają zmienne środowiskowe, które mają być użyte w kontenerze.
Polecenie COPY kopiuje zależności do kontenera. Polecenie RUN wywołuje pip menedżer pakietów w celu przeanalizowania pliku dependencies.txt i zainstalowania zależności. Zapisz i zamknij plik po zakończeniu edycji.
Następnie utworzysz skrypt start.sh. Ten skrypt będzie zawierał polecenia Dockera do zbudowania i uruchomienia obrazu. Chociaż możesz wykonywać te polecenia stopniowo w terminalu, pomyśleliśmy, że czystszym rozwiązaniem będzie dodanie ich do skryptu powłoki i wywołanie go z terminala za pomocą jednego polecenia.
Zanim będziemy mogli zdefiniować zawartość tego pliku, musimy najpierw ustalić wolny port, którego nie używają inne usługi. Będziemy używać portu 45644. Możesz jednak wybrać inny port. Wykonaj poniższe polecenie, aby sprawdzić, czy port jest wolny:
|
1 |
sudo nc localhost 45644 < /dev/null; echo $? |
W zależności od wybranego portu, jeśli wynikiem powyższego polecenia jest 1, oznacza to, że jest on wolny. W przeciwnym razie może być konieczne wybranie innego portu i ponowne wypróbowanie polecenia:

Po ustaleniu wolnego portu możemy teraz utworzyć plik za pomocą nano w katalogu głównym projektu, uruchamiając następujące polecenie:
|
1 |
sudo nano start.sh |
Wewnątrz tego pliku dodaj następujący fragment kodu:
|
1 2 3 4 5 6 7 |
#!/bin/bash app_name="docker-flask-demo" docker build -t ${app_name} . docker run -d -p 45644:80 --name=${app_name} -v $PWD:/app ${app_name} |
Pierwsza linia, określana jako shebang, określa, że jest to plik bash i powinien być wykonywany jako polecenia. Druga linia deklaruje zmienną o nazwie app_name. Używamy tej zmiennej do ustawienia nazw obrazu i kontenera. Trzecia linia instruuje Dockera, aby zbudował obraz na podstawie definicji Dockerfile w bieżącym katalogu. Obraz będzie się nazywał docker-flask-demo zgodnie ze zmienną.
Ostatnia linia tworzy kontener o nazwie docker-flask-demo zgodnie ze zdefiniowaną przez nas zmienną. Flaga -d utrzymuje kontener działający w tle w stanie odłączonym po zakończeniu wykonywania polecenia. Flaga -p powiązuje port na serwerze z określonym portem w kontenerze. W tym przypadku montujemy port 45644 na maszynie hosta do portu 80, który Docker udostępni w kontenerze.
Używamy flagi -v do określenia wolumenu Dockera do zamontowania w kontenerze. Zmienna $PWD to domyślna zmienna systemu Linux, która przechowuje ścieżkę do bieżącego katalogu, w którym się aktualnie znajdujesz:

W naszym przypadku montujemy cały katalog projektu do katalogu /var/www kontenera. Konfiguracja Dockera jest już gotowa. Możesz zbudować obraz i uruchomić kontener na podstawie zbudowanego obrazu, wykonując następujące polecenie:
|
1 |
sudo bash start.sh |
Poczekaj na zakończenie działania skryptu, a następnie wykonaj następujące polecenie platformy Docker, aby wyświetlić listę wszystkich uruchomionych kontenerów:
|
1 |
sudo docker ps |
Dane wyjściowe wyświetlą uruchomione kontenery:

Powinieneś zobaczyć nasz kontener o nazwie docker-flask-demo na liście uruchomionych kontenerów. Znajdź publiczny adres IP swojego serwera i uzyskaj do niego dostęp w przeglądarce na określonym porcie: http://your-server-public-ip:45644.
Powinieneś zobaczyć podobny wynik:

Jeśli widzisz powyższe w swojej przeglądarce, oznacza to, że pomyślnie wdrożyłeś aplikację Flask. Następnie będziemy modyfikować pliki i udostępniać zawartość użytkownikom za pomocą szablonów.
Krok 3: Udostępnianie zawartości za pomocą plików szablonów
We Flasku, Szablony są używane do wyświetlania statycznej i dynamicznej zawartości odwiedzającym witrynę. Pokażemy Ci, jak utworzyć szablon HTML i udostępnić go użytkownikom, gdy odwiedzą określoną ścieżkę. Na przykład może to być strona główna lub strona O nas.
Wykonaj następujące polecenie w terminalu, aby utworzyć plik index.html w katalogu app/templates :
|
1 |
sudo nano app/templates/index.html |
Następnie dodaj do pliku następujący fragment kodu:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Flask Demo</title> </head> <body> <h2>Jesteś na stronie głównej</h2> <p>Witaj na stronie demonstracyjnej Flask z DockeremPage</p> </body> </html> |
Zapisz i zamknij plik po zakończeniu. Utwórz również kolejną stronę, nazwijmy ją stroną O nas, za pomocą następującego polecenia:
|
1 |
sudo nano app/templates/about.html |
Dodaj do pliku następujący fragment kodu:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>O Flask Demo</title> </head> <body> <h2>Strona O nas</h2> <p>To był projekt demonstracyjny. Pokazuje . jak zbudować aplikację Flask z Dockerem i app with Docker and Nginx.</p> <p>Możesz dodać tyle stron i plików, ile chceszas you like</p> </body> </html> |
Zapisz i zamknij plik po zakończeniu. Następnie zmodyfikuj plik app/views.py , aby odwołać się do szablonów, a także tras dla rzeczywistych stron:
|
1 |
sudo nano app/views.py |
Zmodyfikuj plik, aby wyglądał następująco:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from flask import render_template from app import app @app.route('/') def home(): return "Nasza aplikacja Flask działa!" @app.route('/index') def index(): return render_template('index.html') @app.route('/about') def about(): return render_template('about.html') |
Zapisz i zamknij plik po zakończeniu. Wprowadzone zmiany nie wejdą w życie, dopóki nie zatrzymasz i nie uruchomisz ponownie kontenera. Uruchom następujące polecenia platformy Docker, aby zatrzymać i uruchomić kontener. Zwróć uwagę na nazwę kontenera, którą zdefiniowaliśmy wcześniej:
|
1 |
sudo docker stop docker-flask-demo && sudo docker start docker-flask-demo |
Gdy kontener zostanie uruchomiony i zacznie działać, odwiedź stronę główną i stronę O nas, aby zobaczyć nową zawartość:
|
1 |
Strona główna: http://your-server-public-ip:45644/index |

|
1 |
Strona o nas: http://your-server-public-ip:45644/about |

Do tej pory utworzyłeś aplikację Flask, która może serwować zawartość odwiedzającym Twoją stronę internetową. Oto struktura plików projektu:

Prawdopodobnie zauważyłeś, że musieliśmy zrestartować kontener Docker, aby uwzględnić nowe zmiany. W następnym kroku zautomatyzujemy to, aby zapewnić krótszy czas przestoju.
Krok 4: Skonfiguruj automatyczne przeładowywanie aktualizacji plików aplikacji
Co jakiś czas wprowadzamy zmiany w aplikacji, aby ulepszyć logikę, interfejsy użytkownika lub dodać pewne zależności. Aby takie zmiany weszły w życie, może być konieczne ponowne uruchomienie kontenera Docker. Na szczęście, uWSGI ma funkcję o nazwie touch-reload służącą do przeładowywania skryptu Python bez ponownego uruchamiania kontenera.
Domyślnie Python posiada funkcję automatycznego-przeładowywania , która monitoruje cały system plików pod kątem zmian i odświeża aplikację, gdy nastąpi zmiana. Chociaż automatyczne przeładowywanie jest dobre do minimalizowania przestojów, może być zasobożerne. Dlatego nie jest zalecane w środowiskach produkcyjnych.
Zobaczmy, jak można użyć touch-reload do monitorowania zmian w konkretnym pliku i przeładowywania aplikacji w przypadku ich wystąpienia. Zmodyfikuj plik uwsgi.ini za pomocą edytora nano:
|
1 |
sudo nano uwsgi.ini |
Dodaj wyróżnioną linię, aby wyglądała tak:
|
1 2 3 4 5 |
[uwsgi] module = main callable = app master = true touch-reload = /app/uwsgi.ini |
Zapisz i zamknij plik po zakończeniu. Dodana linia określa plik, którego modyfikacja spowoduje przeładowanie aplikacji. Jednak aby ten warunek został aktywowany dla przyszłych modyfikacji, musisz najpierw zrestartować kontener:
|
1 |
sudo docker stop docker-flask-demo && sudo docker start docker-flask-demo |
Możesz teraz zmodyfikować plik app/views.py aby zademonstrować, jak działa automatyczne przeładowywanie:
|
1 |
sudo nano app/views.py |
Zmień ciąg znaków zwracany przez funkcję home, tak jak wyróżniono:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from flask import render_template from app import app @app.route('/') def home(): return "<h3>Some changes to Our Flask application to auto reload!</h3>" @app.route('/index') def index(): return render_template('index.html') @app.route('/about') def about(): return render_template('about.html') |
Po zakończeniu zapisz i zamknij plik.
Otwórz stronę główną swojej aplikacji w przeglądarce: http://your-server-public-ip:45644.
Nie zobaczysz jeszcze żadnych zmian. Dzieje się tak, ponieważ warunek touch-reload wykrywa zmianę w pliku uwsgi.ini. Możesz użyć polecenia touch aby aktywować ten warunek, a tym samym przeładować całą aplikację za pomocą następującego polecenia:
|
1 |
sudo touch uwsgi.ini |
Teraz, jeśli odświeżysz stronę główną, zobaczysz wyświetlone nowe zmiany:

W przyszłości, jeśli wprowadzisz jakiekolwiek kolejne zmiany, wystarczy uruchomić polecenie sudo touch uwsgi.ini i cała aplikacja zostanie przeładowana przy krótszym przestoju. To prowadzi nas do końca tego samouczka.
Podsumowanie
W tym samouczku zaimplementowałeś i wdrożyłeś aplikację Flask za pomocą obrazów i kontenerów Docker. Aby zminimalizować przestój poprzez uniknięcie konieczności ponownego uruchamiania kontenera, skonfigurowałeś touch-reload do nasłuchiwania zmian w określonym pliku i automatycznego przeładowywania całej aplikacji. Na koniec przetestowałeś to wszystko w przeglądarce, aby upewnić się, że działa.
Docker zapewnia szybsze wdrażanie i pozwala na łatwe skalowanie aplikacji. Jeśli chcesz dowiedzieć się więcej o różnych poleceniach Dockera, zapoznaj się z tym samouczkiem na temat jak zainstalować i używać Dockera na Ubuntu.
Więcej zasobów dotyczących Dockera na naszym blogu, możesz sprawdzić następujące pozycje:
- Technologia konteneryzacji: rodzaje i zastosowania różnych kontenerów na platformie PaaS CloudSigma
- Jak udostępniać dane między kontenerem Dockera a hostem
- Instalacja i konfiguracja Dockera na CentOS 7
- Wdrażanie Laravel, Nginx i MySQL za pomocą Docker Compose
- Czyszczenie zasobów Dockera – obrazy, kontenery i wolumeny
Miłego korzystania z komputera!
Komentarze
Brak komentarzy. Bądź pierwszy.