A previous version of this tutorial was written by Kathleen Juell.
Introductie
In deze handleiding ga je een Python-toepassing bouwen met behulp van het Flask-microframework op Ubuntu 22.04. Het grootste deel van deze tutorial zal gaan over hoe je de Gunicorn-toepassingsserver kunt instellen en hoe je de toepassing kunt starten en Nginx kunt configureren om als een front-end omgekeerde proxy te fungeren.
Vereisten
Voordat je aan deze handleiding begint, moet je het volgende hebben:
-
Een server met Ubuntu 22.04 geïnstalleerd en een niet-root gebruiker met sudo-rechten. Volg onze handleiding voor de initiële serverconfiguratie voor begeleiding.
-
Nginx geïnstalleerd, volgens Stappen 1 en 2 van Hoe Nginx te installeren op Ubuntu 22.04.
-
Een domeinnaam geconfigureerd om naar uw server te wijzen. U kunt er een kopen op Namecheap of er een gratis krijgen op Freenom. U kunt leren hoe u domeinen naar DigitalOcean kunt verwijzen door de relevante documentatie over domeinen en DNS te volgen. Zorg ervoor dat u de volgende DNS-records aanmaakt:
- Een A-record met
uw_domein
dat wijst naar het publieke IP-adres van uw server. - Een A-record met
www.uw_domein
dat wijst naar het publieke IP-adres van uw server.
- Een A-record met
-
Bekendheid met de WSGI-specificatie, die de Gunicorn-server zal gebruiken om te communiceren met uw Flask-toepassing. Dit gesprek behandelt WSGI meer in detail.
Stap 1 — Het installeren van de componenten uit de Ubuntu Repositories
De eerste stap is het installeren van alle vereiste onderdelen uit de Ubuntu-repositories. Dit omvat pip
, de Python-pakketbeheerder, die de Python-componenten zal beheren. Je zult ook de Python-ontwikkelingsbestanden krijgen die nodig zijn om sommige van de Gunicorn-componenten te bouwen.
Eerst, update de lokale pakketindex en installeer de pakketten die je in staat stellen om je Python-omgeving op te bouwen. Deze zullen python3-pip
omvatten, samen met nog een paar meer pakketten en ontwikkelingstools die nodig zijn voor een robuuste programmeeromgeving:
Met deze pakketten op hun plaats is de volgende stap het creëren van een virtuele omgeving voor je project.
Stap 2 — Het creëren van een Python Virtuele Omgeving
Vervolgens zul je een virtuele omgeving opzetten om de Flask-toepassing te isoleren van de andere Python-bestanden op je systeem.
Begin met het installeren van het python3-venv
-pakket, dat de venv
-module zal installeren:
Maak vervolgens een hoofdmap voor je Flask-project. Ga naar de map met het cd
commando nadat je deze hebt aangemaakt:
Maak een virtuele omgeving aan om de Python-vereisten van je Flask-project op te slaan door het volgende in te typen:
Dit zal een lokale kopie van Python en pip
installeren in een map genaamd myprojectenv
binnen je projectmap.
Voordat je toepassingen binnen de virtuele omgeving installeert, moet je deze activeren. Doe dit door het volgende in te typen:
Je prompt zal veranderen om aan te geven dat je nu binnen de virtuele omgeving werkt. Het zal er ongeveer zo uitzien: (myprojectenv)gebruiker@host:~/myproject$
.
Stap 3 — Het opzetten van een Flask-toepassing
Nu je in je virtuele omgeving bent, kun je Flask en Gunicorn installeren en beginnen met het ontwerpen van je toepassing.
Installeer eerst wheel
met de lokale instantie van pip
om ervoor te zorgen dat je pakketten worden geïnstalleerd, zelfs als de wheel-archieven ontbreken:
Let op
Ongeacht welke versie van Python je gebruikt, wanneer de virtuele omgeving is geactiveerd, moet je het pip
-commando gebruiken (niet pip3
).
Vervolgens installeer je Flask en Gunicorn:
Het maken van een voorbeeld-app
Nu je Flask beschikbaar hebt, kun je een eenvoudige applicatie maken. Flask is een microframework. Het bevat niet veel van de tools die meer uitgebreide frameworks zouden kunnen bevatten, en bestaat voornamelijk als een module die je kunt importeren in je projecten om je te helpen bij het initialiseren van een webapplicatie.
Hoewel je applicatie misschien complexer is, zullen we onze Flask-applicatie in één bestand maken, genaamd myproject.py
:
De applicatiecode zal in dit bestand leven. Het zal Flask importeren en een Flask-object instantiëren. Hiermee kun je de functies definiëren die moeten worden uitgevoerd wanneer een specifieke route wordt aangevraagd:
Dit definieert in feite welke inhoud moet worden weergegeven wanneer het hoofddomein wordt benaderd. Sla het bestand op en sluit het af wanneer je klaar bent.
Als je de initiële serverconfiguratiegids hebt gevolgd, zou je een UFW-firewall ingeschakeld moeten hebben. Om de applicatie te testen, moet je toegang toestaan tot poort 5000
:
Nu kun je je Flask-app testen door het volgende te typen:
Je zult output zien zoals het volgende, inclusief een nuttige waarschuwing die je eraan herinnert deze serverconfiguratie niet in productie te gebruiken:
Output* Serving Flask app "myproject" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Bezoek het IP-adres van je server gevolgd door :5000
in je webbrowser:
http://your_server_ip:5000
Je zou iets als dit moeten zien:
Wanneer je klaar bent, druk je op CTRL-C
in je terminalvenster om de Flask-ontwikkelingsserver te stoppen.
Het creëren van het WSGI-toegangspunt
Vervolgens maak je een bestand aan dat zal dienen als het toegangspunt voor je applicatie. Dit vertelt de Gunicorn-server hoe te communiceren met de applicatie.
Geef het bestand de naam wsgi.py
:
In dit bestand importeer je de Flask-instantie vanuit onze applicatie en voer je deze vervolgens uit:
Sla het bestand op en sluit het af wanneer je klaar bent.
Stap 4 — Configuratie van Gunicorn
Je applicatie is nu geschreven met een ingesteld toegangspunt. Je kunt nu doorgaan met het configureren van Gunicorn.
Voordat je verder gaat, controleer of Gunicorn de applicatie correct kan bedienen.
Dit kun je doen door het de naam van het toegangspunt van de applicatie mee te geven. Dit wordt geconstrueerd als de naam van de module (zonder de .py
-extensie), plus de naam van de aanroepbare functie binnen de applicatie. In dit geval is dat wsgi:app
.
Specificeer ook de interface en poort om aan te binden met behulp van het argument 0.0.0.0:5000
zodat de applicatie zal worden gestart op een publiek beschikbare interface:
Je zou uitvoer moeten zien zoals het volgende:
Output[2020-05-20 14:13:00 +0000] [46419] [INFO] Starting gunicorn 20.0.4
[2020-05-20 14:13:00 +0000] [46419] [INFO] Listening at: http://0.0.0.0:5000 (46419)
[2020-05-20 14:13:00 +0000] [46419] [INFO] Using worker: sync
[2020-05-20 14:13:00 +0000] [46421] [INFO] Booting worker with pid: 46421
Bezoek opnieuw het IP-adres van uw server met :5000
toegevoegd aan het einde in uw webbrowser:
http://your_server_ip:5000
Je zou de uitvoer van je applicatie moeten zien:
Wanneer je hebt bevestigd dat het goed functioneert, druk je op CTRL-C
in je terminalvenster.
Als je klaar bent met het gebruik van de virtuele omgeving, kun je deze deactiveren:
Alle Python-opdrachten zullen nu weer de Python-omgeving van het systeem gebruiken.
Vervolgens maak je het systemd-servicelicentiebestand aan. Het maken van een systemd-servicelicentiebestand zal het init-systeem van Ubuntu automatisch Gunicorn starten en de Flask-applicatie bedienen wanneer de server opstart.
Maak een eenheid-bestand aan met de extensie .service
binnen de map /etc/systemd/system
om te beginnen:
Daarin begin je met de sectie [Unit]
, die wordt gebruikt om metagegevens en afhankelijkheden te specificeren. Voeg hier een beschrijving van uw service toe en vertel het init-systeem om dit pas te starten nadat het netwerkdoel is bereikt:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
Vervolgens voeg je een [Service]
-sectie toe. Hiermee specificieer je de gebruiker en groep waaronder je wilt dat het proces wordt uitgevoerd. Geef je reguliere gebruikersaccount eigenaarschap van het proces aangezien het alle relevante bestanden bezit. Geef ook groepseigenaarschap aan de groep www-data
zodat Nginx gemakkelijk kan communiceren met de Gunicorn-processen. Vergeet niet om hier de gebruikersnaam te vervangen met jouw gebruikersnaam:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
[Service]
User=sammy
Group=www-data
Volgende, breng de werkmappen in kaart en stel de omgevingsvariabele PATH
in zodat het init-systeem weet dat de uitvoerbare bestanden voor het proces zich bevinden binnen onze virtuele omgeving. Specificeer ook het commando om de service te starten. Dit commando zal het volgende doen:
- Start 3 werkprocessen (hoewel je dit indien nodig moet aanpassen)
- Maak een Unix-socketsbestand aan,
myproject.sock
, binnen onze projectmap en bind het eraan. We stellen een umask-waarde van007
in zodat het socketsbestand wordt gemaakt met toegang voor de eigenaar en de groep, terwijl andere toegang wordt beperkt - Specificeer de naam van het WSGI-ingangspuntbestand, samen met de Python-functie binnen dat bestand (
wsgi:app
)
Systemd vereist dat je het volledige pad naar het Gunicorn-uitvoerbare bestand opgeeft, dat is geïnstalleerd binnen je virtuele omgeving.
Vergeet niet om de gebruikersnaam en projectpaden te vervangen door je eigen informatie:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
Tenslotte, voeg een [Install]
-sectie toe. Dit vertelt systemd waaraan deze service moet worden gekoppeld als je hem inschakelt om bij het opstarten te starten. Je wilt dat deze service start wanneer het reguliere multi-user systeem actief en operationeel is:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
[Install]
WantedBy=multi-user.target
Met dit is je systemd-servicebestand compleet. Sla het nu op en sluit het af.
Je kunt nu de Gunicorn-service die je hebt gemaakt starten en deze inschakelen zodat deze bij het opstarten start:
Laten we de status controleren:
Je zou output als deze moeten zien:
Output● myproject.service - Gunicorn instance to serve myproject
Loaded: loaded (/etc/systemd/system/myproject.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2022-05-10 19:40:41 UTC; 9s ago
Main PID: 17300 (gunicorn)
Tasks: 4 (limit: 2327)
Memory: 56.0M
CPU: 514ms
CGroup: /system.slice/myproject.service
├─17300 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
├─17301 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
├─17302 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
└─17303 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
May 10 19:40:41 r systemd[1]: Started Gunicorn instance to serve myproject.
. . .
Als je fouten ziet, zorg er dan voor dat je ze oplost voordat je verdergaat met de tutorial.
Stap 5 — Configuratie van Nginx voor het doorsturen van verzoeken
Je Gunicorn-toepassingsserver zou nu actief moeten zijn en wachten op verzoeken op het socketbestand in de projectdirectory. Nu kun je Nginx configureren om webverzoeken naar dat socket door te sturen door enkele kleine wijzigingen aan te brengen in het configuratiebestand.
Begin met het maken van een nieuw serverblok configuratiebestand in de sites-available
directory van Nginx. Noem dit myproject
om in lijn te blijven met de rest van de handleiding:
Open een serverblok en vertel Nginx om te luisteren op de standaard poort 80
. Vertel het ook om dit blok te gebruiken voor verzoeken voor de domeinnaam van onze server:
server {
listen 80;
server_name your_domain www.your_domain;
}
Voeg vervolgens een locatieblok toe dat overeenkomt met elk verzoek. Binnen dit blok voeg je het proxy_params
bestand toe dat enkele algemene proxyparameters specificeert die moeten worden ingesteld. Je zult dan de verzoeken doorsturen naar het socket dat je hebt gedefinieerd met behulp van de proxy_pass
richtlijn:
server {
listen 80;
server_name your_domain www.your_domain;
location / {
include proxy_params;
proxy_pass http://unix:/home/sammy/myproject/myproject.sock;
}
}
Sla het bestand op en sluit het af wanneer je klaar bent.
Om de Nginx-serverblokconfiguratie die je zojuist hebt gemaakt te activeren, link je het bestand naar de sites-enabled
directory:
Met het bestand in die directory kun je testen op syntaxisfouten:
Als dit terugkomt zonder enige problemen aan te geven, herstart dan het Nginx-proces om de nieuwe configuratie in te lezen:
Tenslotte, pas de firewall opnieuw aan. Je hebt geen toegang meer nodig via poort 5000
, dus je kunt die regel verwijderen. Je kunt dan volledige toegang toestaan tot de Nginx-server:
Je zou nu naar de domeinnaam van je server moeten kunnen navigeren in je webbrowser:
http://your_domain
Je zou de uitvoer van je applicatie moeten zien:
Opmerking: Je krijgt een HTTP 502 gatewayfout als Nginx geen toegang heeft tot het socketbestand van gunicorn. Meestal komt dit doordat de thuismap van de gebruiker andere gebruikers niet toestaat om bestanden erin te openen.
Als je socketbestand /home/sammy/myproject/myproject.sock
heet, zorg er dan voor dat /home/sammy
minimaal 0755
rechten heeft. Je kunt een tool zoals chmod
gebruiken om de rechten als volgt te wijzigen:
Vernieuw dan de pagina om te zien of de HTTP 502-fout verdwijnt.
Als je fouten tegenkomt, probeer dan het volgende te controleren:
sudo less /var/log/nginx/error.log
: controleert de Nginx-foutenlogboeken.sudo less /var/log/nginx/access.log
: controleert de Nginx-toegangslogboeken.sudo journalctl -u nginx
: controleert de Nginx-proceslogboeken.sudo journalctl -u myproject
: controleert de Gunicorn-logboeken van je Flask-applicatie.
Stap 6 — Het beveiligen van de applicatie
Om ervoor te zorgen dat het verkeer naar uw server veilig blijft, laten we een SSL-certificaat voor uw domein verkrijgen. Er zijn meerdere manieren om dit te doen, waaronder het verkrijgen van een gratis certificaat van Let’s Encrypt, het genereren van een zelfondertekend certificaat, of het kopen van een van een andere aanbieder en het configureren van Nginx om het te gebruiken door Stappen 2 tot en met 6 te volgen van Hoe maak je een zelfondertekend SSL-certificaat voor Nginx in Ubuntu 22.04. We zullen optie één (Let’s Encrypt) gebruiken omwille van de snelheid.
Installeer de Nginx-pakket van Certbot met apt
:
Certbot biedt verschillende manieren om SSL-certificaten te verkrijgen via plugins. De Nginx-plugin zal zorgen voor het herconfigureren van Nginx en het opnieuw laden van de configuratie wanneer nodig. Om deze plugin te gebruiken, typ het volgende:
Dit voert certbot
uit met de --nginx
plugin, waarbij -d
wordt gebruikt om de namen op te geven waarvoor het certificaat geldig moet zijn.
Als dit de eerste keer is dat je certbot
uitvoert, wordt je gevraagd om een e-mailadres in te voeren en akkoord te gaan met de servicevoorwaarden. Nadat je dat hebt gedaan, zal certbot
communiceren met de Let’s Encrypt-server, vervolgens een uitdaging uitvoeren om te verifiëren dat je het domein waarvoor je een certificaat aanvraagt, beheert.
Als dat succesvol is, zal certbot
vragen hoe je je HTTPS-instellingen wilt configureren:
OutputPlease choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
-------------------------------------------------------------------------------
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel):
Kies je optie en druk op ENTER
. De configuratie wordt bijgewerkt en Nginx zal worden herladen om de nieuwe instellingen op te pikken. certbot
zal afsluiten met een bericht waarin staat dat het proces succesvol was en waar je certificaten zijn opgeslagen:
OutputIMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/your_domain/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/your_domain/privkey.pem
Your cert will expire on 2020-08-18. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the "certonly" option. To non-interactively renew *all* of
your certificates, run "certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
Als je de Nginx-installatie-instructies in de prerequisites hebt gevolgd, heb je de overbodige HTTP-profieltoewijzing niet langer nodig:
Om de configuratie te controleren, navigeer opnieuw naar je domein, met behulp van https://
:
https://your_domain
Je zou opnieuw de uitvoer van je applicatie moeten zien, samen met de beveiligingsindicator van je browser, die moet aangeven dat de site beveiligd is.
Conclusie
In deze handleiding hebt u een eenvoudige Flask-toepassing gemaakt en beveiligd binnen een Python virtuele omgeving. U hebt een WSGI-ingangspunt gemaakt zodat elke WSGI-compatibele toepassingsserver ermee kan communiceren, en vervolgens de Gunicorn-app-server geconfigureerd om deze functie te bieden. Daarna hebt u een systemd-servicebestand gemaakt om de toepassingsserver automatisch op te starten bij het opstarten. U hebt ook een Nginx-serverblok gemaakt dat webclientverkeer doorstuurt naar de toepassingsserver, externe verzoeken doorgeeft en het verkeer naar uw server beveiligt met Let’s Encrypt.
Flask is een zeer eenvoudig maar uiterst flexibel framework dat bedoeld is om uw toepassingen functionaliteit te bieden zonder te strikt te zijn over structuur en ontwerp. U kunt de algemene stack gebruiken die in deze handleiding wordt beschreven om de door u ontworpen Flask-toepassingen te serveren.