Zpět na blog

Vytvoření aplikace Django a Gunicorn s Dockerem na Ubuntu

Vytvoření aplikace Django a Gunicorn s Dockerem na Ubuntu

Django je pokročilý open-source Python webový framework, který vám pomůže rychle vytvořit vaši aplikaci v Pythonu. Podporuje rychlý vývoj a čistý, pragmatický design díky dodržování architektonického vzoru model–šablona–pohled (model–template–views). Již v základu framework obsahuje nezbytné moderní komponenty aplikací, jako je autentizace uživatelů, framework pro ukládání do mezipaměti, objektově-relační mapování, URL dispatcher, systém šablon, a přizpůsobitelné administrační rozhraní.

Gunicorn ‘Green Unicorn’ je Python WSGI HTTP server pro systémy UNIX. Server Gunicorn je kompatibilní s různými webovými frameworky, nabízí skvělý výkon a je šetrný k serverovým zdrojům. Docker je open-source kontejnerová platforma, která je tu s námi již nějakou dobu a činí vývoj aplikací rychlým, efektivním a předvídatelným.

V tomto návodu získáte dovednosti ve vývoji a nasazování škálovatelných kontejnerizovaných webových aplikací v Django. Budeme používat Django aplikaci Polls vytvořenou podle úvodních příruček pro začátek s Django. V době psaní tohoto návodu jsme jej založili na verzi Django 3.2 podporované verzí Python 3.6 nebo novější. Aplikaci nasadíme jako kontejner pomocí Dockeru a budeme ji spouštět pomocí serveru Gunicorn. Před nasazením aplikace Django v kontejneru samozřejmě budete muset provést několik úprav v kódu projektu, abyste vyřešili věci jako protokolování do standardních výstupních proudů a práci s proměnnými prostředí. Statické soubory, jako jsou CSS, JavaScript a obrázky, lze přesunout do služeb objektového úložiště, což umožní snadnou správu souborů z jednoho místa v multikontejnerovém prostředí.

Ukážeme vám, jak tyto úpravy implementovat na základě dobře popsané twelve-factor metodiky pro tvorbu škálovatelných webových aplikací. Jakmile úpravy dokončíte, sestavíte Docker obraz aplikace a nasadíte kontejnerizovanou aplikaci pomocí Dockeru. Doporučujeme vám postupovat podle kroků popsaných v tomto návodu, abyste mu plně porozuměli.

Předpoklady

Jelikož se jedná o praktický návod, doporučujeme vám mít připravené následující nastavení, které vám pomůže postupovat dál:

  • Server s Ubuntu 20.04. Můžete postupovat podle kroků 1 až 4 v tomto podrobném návodu, který vám pomůže nastavit váš server Ubuntu na CloudSigma.

  • Ujistěte se, že přidáte uživatele s oprávněními sudo na obou uzlech, které budeme používat ke spouštění příkazů, jak je popsáno v návodu výše.

  • Nainstalujte Docker na server. Můžete postupovat podle kroků 1, 2 a 3 v našem návodu na instalaci a provozování Dockeru. Nezapomeňte přidat výše vytvořeného sudo uživatele do skupiny Docker.

  • Kompatibilní objektové úložiště. Django podporuje několik služeb úložiště, jak je uvedeno v dokumentaci k django-storages. Můžete si vybrat tu, kterou preferujete, a postupovat podle dokumentace k jejímu nastavení. V tomto návodu budeme používat MinIO což je cloudová služba úložiště kompatibilní s S3.

  • Instanci SQL databáze. Django podporuje několik SQL databází které si můžete libovolně vybrat. V tomto návodu budeme používat PostgreSQL. Databáze PostgreSQL nebude nasazena uvnitř kontejneru. Nastavíme samostatný server Ubuntu pro hostování instance PostgreSQL, abychom zajistili naše multikontejnerové nastavení a také perzistenci dat. Můžete vytvořit další instanci Ubuntu 20.04 a postupovat podle tohoto návodu pro Nastavení instance databáze PostgreSQL na Ubuntu. Nezapomeňte v databázi PostgreSQL přidat roli pro vašeho sudo uživatele, jak je vysvětleno v krocích 2 a 3. Tato role vám umožní připojit se k databázi z ostatních serverů, které hostují vaše kontejnery.

Podle těchto požadavků byste měli mít dvě instance serveru Ubuntu. Na jedné instanci poběží váš Docker kontejner a na druhé instanci poběží instance PostgreSQL. Začněme!

Krok 1: Konfigurace instance databáze PostgreSQL

V této části upravíme konfiguraci Postgresu na serveru Ubuntu, na kterém běží instance Postgresu. To umožní připojení z externí IP adresy. Jakmile se připojí, můžeme vytvořit databázi a uživatelskou roli specifickou pro aplikaci Django Polls, kterou nasazujeme.

Nejprve, pokud jste nastavili své prostředí podle Požadavků, měli byste mít ve své databázi PostgreSQL roli pro svého uživatele sudo. Dále musíme pro tuto roli nastavit heslo. Na serveru, kde běží PostgreSQL, se přihlaste do terminálu Postgres pomocí následujícího příkazu:

Jakmile budete v terminálu Postgres, zadejte příkaz \password pro změnu hesla uživatele. Syntaxe pro příkaz \password je \password <username>. V našem případě příkaz:

Zadejte heslo a potvrďte jej. Uložte toto heslo na bezpečné místo, protože jej později použijete k ověření z druhého serveru Ubuntu. Poté napište exit a stisknutím klávesy Enter ukončete terminál Postgres.

Pokud jste na instanci serveru PostgreSQL povolili firewall (ufw), budete muset povolit provoz na výchozí port Postgresu 5432. Provoz můžete omezit tak, aby přicházel pouze ze specifické IP adresy vašeho druhého serveru Ubuntu, na kterém poběží kontejner Docker. Spuštěním následujícího příkazu přidejte pravidlo ufw a nahraďte zvýrazněnou IP adresu:

Tím zajistíte, že se k instanci PostgreSQL bude moci připojit pouze váš server. I když to umožňuje provoz přes firewall, musíte také upravit konfigurační soubory PostgreSQL, abyste povolili připojení ze vzdálené IP adresy. Ve výchozím nastavení konfigurace umožňuje připojení pouze z localhost. Konfigurační soubory pro PostgreSQL naleznete v adresáři /etc/postgresql/12/main. 12 je v tomto případě verze PostgreSQL, kterou jsme pro tento návod nainstalovali. Možná jste nainstalovali jinou verzi. Můžete tedy přejít do adresáře /etc/postgresql/ a vypsat obsah, abyste zjistili číslo verze nainstalovaného PostgreSQL.

K úpravě konfiguračního souboru použijte nano:

Najděte níže uvedený řádek, odkomentujte jej a nastavte jej tak, aby povoloval připojení ze všech IP adres:

Uložte a zavřete soubor. Poté musíte upravit také soubor pg_hba.conf, který je ve stejném adresáři jako postgresql.conf. Soubor pg_hba.conf vám umožňuje definovat, ze kterých počítačů se můžete k instanci PostgreSQL připojit, a také metodu ověřování. Otevřete soubor pomocí nano:

Přečtěte si prosím komentáře v tomto souboru, abyste porozuměli klíčovým slovům. Hledaná sekce je tato:

Building a Django and Gunicorn Application with Docker on Ubuntu 1

Zaměříme se na druhý řádek, po odkomentování by měl vypadat jako řádek níže:

Nahraďte prosím zvýrazněnou část IP adresou vašeho serveru Ubuntu, abyste mu umožnili připojení k instanci PostgreSQL. Jakmile budete připraveni, soubor uložte. Restartujte databázi PostgreSQL, aby se změny projevily:

Náš druhý server Ubuntu se specifikovanou IP adresou by měl být schopen se k instanci Postgres připojit.

Krok 2: Připojení k instanci serveru PostgreSQL a vytvoření databáze a uživatele

V tomto kroku se pokusíme zajistit, aby Ubuntu instance obsluhující náš kontejner Docker, se mohla připojit k druhému serveru, na kterém běží PostgreSQL instance. Přihlaste se do instance Ubuntu, která má Docker, a nainstalujte balíček postgresql-client uvnitř hostitelského stroje Ubuntu (zatím ne uvnitř kontejneru).

Standardně nejprve aktualizujte balíček apt a poté nainstalujte balíček pomocí následujících příkazů:

Balíček nainstalovaný výše vám pomůže vytvořit databázi a uživatele pro vaši aplikaci. Dále se musíme připojit k instanci PostgreSQL zadáním parametrů připojení klientovi Postgresql.

Parametry připojení se řídí touto syntaxí:

V tomto příkazu je username uživatel/role, kterou jste přidali do své databáze PostgreSQL. host IP adresa instance Ubuntu, na které běží vaše databáze PostgreSQL. port je výchozí port, na kterém Postgres naslouchá příchozím připojením, tj. 5432. Na místě database, použijeme výchozí databázi s názvem postgres která je součástí instalace PostgreSQL. Nahraďte odpovídajícím způsobem své hodnoty ve zvýrazněných částech a stiskněte Enter. Po výzvě zadejte heslo, které jste nastavili. Tím se přihlásíte do příkazového řádku Postgres, kde můžete spravovat databázi.

Úspěšně jste se připojili k instanci PostgreSQL. Nyní můžete vytvořit databázi pro aplikaci Django polls. Pojmenujme ji django_polls:

Ujistěte se, že váš příkaz končí středníkem, abyste předešli chybám. Poté se přepněte do databáze django_polls pomocí příkazu:

Dále vytvořte databázového uživatele specifického pro tento projekt. Pojmenujme uživatele django_user:

Zvolte pro svého uživatele bezpečné heslo. Jakmile to uděláte, musíme upravit parametry připojení pro uživatele, kterého jsme právě vytvořili. To pomáhá urychlit databázové operace tím, že zajišťuje, aby se správné hodnoty nedotazovaly a nenastavovaly při každém navázání připojení.

Nastavte výchozí kódování, které Django očekává, na UTF-8:

Dále nastavte výchozí schéma izolace transakcí na „ read committed“, což blokuje čtení z nepotvrzených transakcí:

Nastavte své časové pásmo. Aby byl návod univerzální, použijeme UTC:

Nakonec udělte novému uživateli administrátorská oprávnění k databázi:

Až budete připraveni, ukončete příkazový řádek PostgreSQL:

To je pro tento krok vše. Jakmile správně nakonfigurujete aplikaci Django, měla by být schopna spravovat vaši databázi.

Krok 3: Stažení aplikace z Git repozitáře a definování závislostí

V tomto kroku naklonujeme repozitář aplikace Django-polls. Tento repozitář obsahuje kód pro Djangův tutoriál „Napište svou první aplikaci v Django“.

Přihlaste se k serveru Ubuntu, na kterém běží Docker, vytvořte adresář s názvem django_project a přejděte do něj:

Poté naklonujte repozitář do adresáře pomocí následujícího příkazu:

Přejděte do adresáře a vypište jeho obsah:

Vypište obsah adresáře:

Building a Django and Gunicorn Application with Docker on Ubuntu 2

Všimněte si následujících položek:

  • manage.py: tento soubor je vstupem do nástroje příkazového řádku, který Django poskytuje pro správu vaší aplikace.

  • mysite: adresář s rozsahem projektu Django a nastavením kódu.

  • polls: adresář obsahující kód aplikace polls .

  • templates: obsahuje vlastní soubory šablon pro stránky administrace.

Chcete-li se dozvědět více o tom, jak jsme projekt skutečně vytvořili, podívejte se na Writing your first Django app z oficiální dokumentaci. Uvnitř django-polls adresáři chceme mít naše Python závislosti definované v textovém souboru. Nazveme ho requirements.txt. Otevřete soubor ve svém oblíbeném editoru:

Vložte do souboru následující řádky pro deklaraci závislostí:

V tomto souboru jsme definovali závislosti Pythonu s jejich přesnými verzemi, které by se měly nainstalovat při sestavení aplikace. Některé z nich zahrnují Django, django-storages pro interakci s buckety objektového úložiště, psycopg2 adaptér pro PostgreSQL, gunicorn WSGI server a další dodatečné závislosti. Po dokončení soubor uložte a zavřete.

Krok 4: Konfigurace proměnných prostředí pro aplikaci Django

Metodika twelve-factor app doporučuje, abyste z kódu aplikace vyjmuli pevně zakódované konfigurace. Tím získáte svobodu měnit chování aplikace za běhu úpravou proměnných prostředí bez nutnosti zasahovat do kódu. Docker s tímto nastavením pracuje, takže upravíme soubor nastavení tak, aby pracoval s proměnnými prostředí. Kubernetes také pracuje s tímto nastavením konfigurace. Další návod na nasazení s Kubernetes budeme sdílet na CloudSigma blog.

Soubor settings.py je hlavním souborem nastavení pro projekt Django. Jedná se o modul Pythonu, který k nastavení aplikace používá nativní datové struktury. Pro naši aplikaci se soubor nachází na umístění django-polls/mysite/settings.py. Většina jeho hodnot je pevně zakódovaná. To by od vás vyžadovalo úpravu konfiguračního souboru v kódu, pokud byste změnili chování aplikace. To chceme změnit. Naštěstí Python nabízí funkci getenv v modulu os . Můžeme ji použít ke konfiguraci Djanga tak, aby místo toho četlo konfigurační parametry z lokálních proměnných prostředí.

Pokračujme úpravou souboru django-polls/mysite/settings.py , abychom nahradili pevně zakódované hodnoty proměnných. Možná je budeme chtít aktualizovat za běhu voláním os.getenv. Tato funkce načte hodnotu nastavenou v zadaném názvu proměnné prostředí. Volitelně můžete zadat druhý parametr, což je výchozí hodnota, která se použije, pokud proměnná prostředí není nastavena.

Zde je příklad:

Na řádku výše říkáme Djangu, aby načetlo tajný klíč z proměnné prostředí. Neposkytujeme záložní hodnotu, protože klíč poskytneme externě. Pokud neexistuje, aplikace by se neměla spustit. Při externím poskytování tajného klíče chceme také zajistit, aby všechny naše kontejnerizované kopie aplikace používaly stejný klíč napříč různými servery. Tím se předejde potenciálním problémům, které vznikají, když různé kopie aplikace používají různé klíce.

Zde je další příklad s výchozí možností:

Na tomto řádku definujeme proměnnou prostředí DEBUG , která by se měla načíst. Pokud však není nastavena, poskytli jsme druhý parametr, který bude předán proměnné nastavení DEBUG . DEBUG je nastaveno na False , aby se zajistilo, že citlivé informace nebudou předány na frontend v případě, že nastane problém s aplikací. Pokud jsme však ve vývojovém režimu, chceme, aby bylo nastaveno na True , což nám umožní vidět informace o chybě, abychom ji mohli snáze opravit.

Nyní, když znáte důležitost proměnných prostředí, otevřete soubor django_project/django-polls/settings.py ve svém editoru. Nejprve importujte modul os přidáním tohoto řádku na začátek souboru settings.py :

Poté najděte tyto proměnné a aktualizujte je následovně:

V nastavení ALLOWED_HOSTS určujeme, že má získat hodnotu z DJANGO_ALLOWED_HOSTS proměnné prostředí a rozdělit ji na Python list pomocí čárky ( ,) jako oddělovače. Pokud proměnná chybí, ALLOWED_HOSTS se nastaví na 127.0.0.1.

Dále projděte soubor a najděte sekci DATABASES, nakonfigurujte ji tak, aby také četla z proměnných prostředí:

Všimněte si, že jsme přidali modul json.loads. Měli byste také přidat import tohoto modulu na začátek souboru settings.py:

Funkce json.loads deserializuje objekt JSON předaný do DATABASES['default']['OPTIONS'] z proměnné prostředí DB_OPTIONS. Zadání této volby nám umožňuje předat libovolnou datovou strukturu pro definování konfigurace databáze. Databázový stroj obsahuje sadu platných voleb, které se na něj vztahují. Volba JSON nám dává flexibilitu zakódovat objekt JSON s příslušnými parametry pro databázový stroj, který v danou chvíli používáme.

Položka DATABASES['default']['NAME'] určuje název databáze v námi nastaveném systému řízení relačních databází. V případě použití databáze SQLite byste měli uvést cestu k souboru databáze.

Upozorňujeme, že Python nabízí několik metod pro čtení externích proměnných prostředí. Použili jsme pouze jednu z nich. Můžete prozkoumat a použít jiné metody. V tomto kroku jste se naučili pracovat s externími proměnnými prostředí. To vám dává flexibilitu měnit proměnné a upravovat chování aplikace běžící v kontejnerech. V dalším kroku se naučíte pracovat se službami objektového úložiště.

Krok 5: Práce s externími službami objektového úložiště

Hlavní výhodou kontejnerizace aplikace je její přenositelnost pro snadné nasazení několika kopií aplikace při zvýšení provozu. Tím se vytváří prostor pro škálování. To však přináší problém s udržováním verzí statických souborů a prostředků v různých kontejnerech. Díky vylepšením v cloudových technologiích můžete tyto sdílené statické prvky přesunout do externího úložiště. Poté můžete soubory zpřístupnit přes síť všem běžícím kontejnerům. Místo pokusů o synchronizaci souborů napříč různými běžícími kontejnery máte jedno centrální místo pro jejich správu.

Koncept, který se výše snažíme vysvětlit, je použití služeb cloudového objektového úložiště neboli Simple Storage Services (S3). Django má balíček s názvem django-storages, která vám umožňuje pracovat se vzdálenými úložišti. Django-storages spolupracují s většinou služeb objektového úložiště kompatibilních s S3, jako jsou mimo jiné FTP, SFTP, Amazon AWS S3, Google Cloud Storage, Dropbox a Azure Storage. V tomto návodu budeme používat MinIO. Klidně použijte jakékoli jiné služby objektového úložiště kompatibilní s S3. MinIO nabízí vysoce výkonné objektové úložiště kompatibilní s S3. S MinIO můžete vybudovat datovou infrastrukturu kompatibilní s S3 na jakémkoli cloudu.

Ukážeme vám, jak nastavit službu úložiště MinIO na platformě CloudSigma. Postupujte podle následujících kroků:

  • Začněte tím, že si vytvoříte účet na CloudSigma. Pokud narazíte na jakékoli problémy při vytváření úložiště MinIO, spojte se s bezplatnou 24/7 živou chatovou podporou CloudSigma’s, a oni vám pomohou.

  • Přidejte své fakturační údaje.

  • Dále si odtud vyžádejte svůj veřejně přístupný bucket: https://blog.cloudsigma.com/xxxx. Pro získání přístupových údajů k účtu budete muset kontaktovat podporu přes Live Chat.

  • Jakmile bude vaše prostředí objektového úložiště MinIO vytvořeno, obdržíte přístupové údaje a další pokyny pro přístup k němu. Přihlašovací údaje by měly obsahovat váš MINI_ACCESS_KEY, MINIO_SECRET_KEY, a MINIO_URL. Tyto klíče použijete v níže uvedených pokynech.

Proveďme několik dalších změn v souboru mysite/settings.py, který jsme upravovali v předchozím kroku. V tomto souboru přidejte aplikaci storages do seznamu INSTALLED_APPS:

INSTALLED_APPS

Aplikace storages se instaluje přes django-storages, jak je definováno v requirements.txt. Přejděte na konec souboru a nahraďte proměnnou STATIC_URL následujícím fragmentem kódu:

Všimněte si, že některé konfigurační proměnné jsou pevně zakódovány:

  • STATICFILES_STORAGE: definuje backend úložiště, který bude Django používat ke zpracování statických souborů. V našem návodu používáme úložiště MinIO, ale můžete použít jakýkoli backend kompatibilní s S3, jak je vysvětleno v dokumentaci k Django Storages.

  • AWS_S3_OBJECT_PARAMETERS: definuje hlavičky cache-control.

  • AWS_LOCATION: toto používáme k nastavení adresáře v rámci bucketu úložiště, kam se budou ukládat všechny statické soubory. Můžete si zvolit jiný název.

  • AWS_DEFAULT_ACL: nastavuje seznam řízení přístupu (ACL) pro statické soubory. Nastavení hodnoty na ‘ public-Read’ zpřístupní soubory všem veřejným uživatelům.

  • STATIC_URL: Django používá základní URL nastavenou v této proměnné ke generování URL pro statické soubory. Základní URL je v tomto případě odvozena spojením URL koncového bodu a podadresáře statických souborů.

  • STATIC_ROOT: definuje, kde se mají statické soubory lokálně shromažďovat před jejich zkopírováním do vzdáleného objektového úložiště.

Máme také některé externě definované proměnné prostředí pro zachování flexibility a přenositelnosti:

  • AWS_STORAGE_BUCKET_NAME: definuje název úložiště (bucketu), do kterého bude Django nahrávat statické soubory.

  • AWS_S3_ENDPOINT_URL: definuje URL koncového bodu (endpointu) používanou pro přístup ke službě objektového úložiště. Bude se jednat o URL namapovanou na server hostující vaši službu MinIO.

Po dokončení úprav soubor uložte a zavřete.

Jakmile máte tato nastavení připravena a nainstalovali jste deklarované závislosti Pythonu, můžete kdykoli spustit příkaz Django manage.py collectstatic pro shromáždění statických souborů vašeho projektu a jejich nahrání do vzdáleného objektového úložiště:

Zatím jsme však nenastavili soubor env s konfiguracemi, takže to pravděpodobně selže.

Při spuštění příkazu chvíli trvá, než se vaše statické soubory zkopírují do cloudového úložiště MinIO, v závislosti na jejich velikosti a rychlosti vašeho internetu.

To je pro tento krok vše. Podívejme se, jak můžeme vyřešit odesílání logů Django do Docker Engine, abyste si je mohli prohlédnout pomocí příkazu docker logs v dalším kroku.

Krok 6: Nastavení protokolování v aplikaci Django

V režimu ladění, když je volba DEBUG nastavena na True, Django zapisuje informace do standardního výstupu a standardního chybového výstupu. Informace z logů se obvykle zobrazují v terminálu, ze kterého jste spustili vývojový HTTP server.

V produkčním prostředí pravděpodobně používáte jiný HTTP server a volba DEBUG je nastavena na False. Django v tomto případě použije jinou metodu protokolování. Django odesílá logy s prioritou ERROR nebo CRITICAL na e-mailový účet správce, který definujete. To v mnoha situacích funguje skvěle.

V kontejnerizovaných prostředích a prostředích Kubernetes se důrazně doporučuje protokolování do standardního výstupu a standardního chybového výstupu. Zprávy logů se shromažďují v jediném adresáři v souborovém systému uzlu a jsou snadno dostupné pomocí příkazů kubectl and docker commands. S centralizovaným bodem protokolování v souborovém systému uzlu může provozní tým snadno spouštět procesy na každém uzlu pro sledování a přeposílání logů. Proto musíme naši aplikaci nakonfigurovat tak, aby zapisovala logy do tohoto standardního nastavení.

Jistě vás potěší, že Django využívá vysoce přizpůsobitelný modul logging ze standardní knihovny Pythonu. To vám umožňuje definovat slovník, který se předává do logging.config.dictConfig pro definování požadovaných výstupů a formátování. Zde je skvělý článek o Django Logging, The Right Way, který vám pomůže zvládnout techniky protokolování v Django.

Otevřete soubor django-polls/mysite/settings.py  ve vašem editoru. Na začátek souboru přidejte import pro knihovnu Pythonu logging.config:

Se všemi importy, které jsme dosud přidali, by vaše sekce importů v souboru settings.py měla vypadat takto:

Building a Django and Gunicorn Application with Docker on Ubuntu 3

Knihovna logging.config přijímá slovník s novou konfigurací protokolování prostřednictvím funkce dictConfig, čímž přepíše výchozí chování protokolování v Django.

Přejděte na konec souboru a přidejte následující fragment kódu pro konfiguraci protokolování:

LOGGING_CONFIG je nastaveno na None pro zakázání/vymazání výchozích konfigurací protokolování, které Django definuje. LOGLEVEL je nastaveno pomocí DJANGO_LOGLEVEL proměnné prostředí. Pokud však neexistuje, chceme, aby bylo nastaveno na ‘ info’.

Modul logging.config , který jsme importovali nahoře, poskytuje funkci dictConfig , která se používá k nastavení nového konfiguračního slovníku. Slovník definuje formátování textu pomocí klíče formatters . Výstup se nastavuje pomocí klíče handlers a nakonec klíč loggers definuje, která zpráva má jít do kterého handleru.

Jakmile máte tato nastavení definována, Docker zpřístupní protokoly prostřednictvím příkazu docker logs. Podobně v dalším návodu, který budeme dělat pro Kubernetes, můžete protokoly zobrazit pomocí příkazu kubectl logs. Pojďme nyní v dalším kroku zahájit proces kontejnerizace.

Krok 7: Definování Dockerfile aplikace

V tomto kroku definujeme konfiguraci pro spuštění obrazu kontejneru, který poběží s aplikací Django obsluhovanou WSGI serverem Gunicorn. Definujeme běhové prostředí pro sestavení obrazu kontejneru, nainstalujeme aplikaci a její závislosti a provedeme několik závěrečných konfigurací.

  • Rodičovský obraz pro aplikaci Django

Rozhodnutí o základním obrazu, na kterém bude váš kontejner založen, je úplně prvním rozhodnutím, které při řešení kontejnerizovaných nasazení učiníte. Samozřejmě máte možnost sestavit své obrazy kontejnerů od nuly (SCRATCH), tj. z prázdného souborového systému, nebo je založit na existujícím obrazu kontejneru. Protože nechceme znovu objevovat kolo, budeme náš obraz stavět na základním obrazu. K dispozici je mnoho open-source obrazů kontejnerů z oficiálního repozitáře obrazů kontejnerů Dockeru. Pokud nestavíte svůj obraz od nuly, důrazně doporučujeme použít obraz z oficiálního hubu Dockeru. Je to proto, že Docker ověřuje, zda obrazy splňují osvědčené postupy, a zajišťuje pravidelné aktualizace a bezpečnostní záplaty.

Vzhledem k tomu, že Django je framework pro Python, využijeme obraz se standardním prostředím Pythonu, který již má nainstalované nástroje a knihovny, které potřebujeme. Na oficiální stránce pro obrazy Pythonu na Docker hubu, najdete obraz založený na Pythonu pro různé verze Pythonu.

Z našich různých návodů založených na Dockeru, si všimnete, že používáme obrazy založené na Alpine Linux. Alpine Linux nabízí robustní, ale štíhlé prostředí operačního systému pro spouštění kontejnerizovaných aplikací. Přestože je jeho souborový systém malý, je rozšiřitelný a přichází s kompletním systémem správy balíčků s možností přidávání funkcí.

Při výběru základního obrazu na Docker hubu si můžete všimnout, že pro každý obraz je k dispozici více tagů. Pro účely Python, máme 3-alpine, což odkazuje na nejnovější verzi obrazu Pythonu 3 nejnovější verze Alpine. To znamená, že v případě, že váš projekt pracuje se starší verzí obrazu, může se při aktualizaci ze strany správců obrazu Dockeru rozbít. Abyste se takovým scénářům v budoucnu vyhnuli, doporučujeme vždy volit co nejspecifičtější tagy pro obraz, který chcete použít.

V tomto návodu použijeme 3.8.12-alpine3.15 obraz jako základní obraz pro naši aplikaci Django. Tento konkrétní tag bude specifikován v Dockerfile pomocí instrukce FROM. Dockerfile bude v hlavním adresáři projektu: django_project.

Začněte tím, že přejdete z adresáře Django-polls zpět do adresáře django_project adresáře:

Jakmile budete v adresáři, otevřete ve svém oblíbeném editoru soubor s názvem Dockerfile :

Dále vložte následující řádek pro nastavení základu vašeho obrazu:

Klíčové slovo FROM  definuje výchozí bod vlastního Docker obrazu. Jakmile je definován, můžeme pokračovat v přidávání instrukcí pro nastavení aplikací. Tyto instrukce nainstalují potřebné závislosti, zkopírují soubory aplikace a nastaví běhové prostředí.

Přidejte následující fragment kódu do souboru Dockerfile:

V tomto fragmentu kódu říkáme Dockeru, aby zkopíroval soubor requirements.txt  do /app/requirements.txt, aby se zajistilo, že závislosti aplikace budou k dispozici v souborovém systému obrazu. Požadavky zahrnují všechny balíčky Pythonu potřebné ke spuštění aplikace. Závislosti se kopírují jako první, aby Docker mohl uložit vrstvu obrazu do mezipaměti. Je to proto, že Docker ukládá do mezipaměti každý krok v souboru Dockerfile. První sestavení obrazu obvykle trvá déle. Docker stáhne závislosti a poté je uloží do mezipaměti. Pokud se soubor requirements.txt nezmění, Docker provede sestavení z mezipaměti, což následná sestavení urychlí.

Další krok obsahuje instrukci RUN, která spouští seznam příkazů Linuxu, zřetězených pomocí linuxového operátoru &&. Tyto příkazy provádějí následující:

  • Použijí nástroj pro správu balíčků Alpine apk k instalaci vývojových souborů PostgreSQL a základních závislostí pro sestavení.

  • Vytvoří virtuální prostředí Pythonu.

  • Nainstalují závislosti Pythonu definované v souboru requirements.txt pomocí pip.

  • Zkompilují potřebné běhové balíčky analýzou požadavků nainstalovaných balíčků Pythonu.

  • Odeberou všechny závislosti pro sestavení, které již nejsou potřeba.

Důvodem pro zřetězení příkazů v kroku RUN je snížení počtu vrstev obrazu. Docker vytvoří novou vrstvu obrazu nad stávajícím souborovým systémem pokaždé, když narazí na ADD, COPY nebo RUN instrukce v souboru Dockerfile. Komprimace příkazů tam, kde je to možné, minimalizuje počet vytvořených vrstev obrazu.

Položky přidané do vrstev obrazu nelze v následující vrstvě odebrat. Před přechodem k další instrukci musíte deklarovat instrukce pro smazání nežádoucích položek. To je nezbytné pro zmenšení velikosti obrazu. Měli byste si všimnout, že jsme přidali apk del příkaz na konec RUN příkazu. To bylo provedeno za účelem odstranění závislostí pro sestavení poté, co jsme je použili k sestavení balíčků aplikace.

Dále tu máme další ADD instrukci, kterou používáme ke zkopírování kódu aplikace do adresáře /app. Poté použijeme instrukci WORKDIR k nastavení pracovního adresáře obrazu na adresář /app , který nyní obsahuje kód aplikace.

Dále tu máme instrukce ENV, které používáme k nastavení dvou proměnných prostředí, jež obraz zpřístupní běžícím kontejnerům. Nejprve nastavíme proměnnou VIRTUAL_ENV na /env. Za druhé nastavíme proměnnou PATH tak, aby zahrnovala adresář /env/bin . Na těchto dvou řádcích načítáme skript /env/bin/activate, což je způsob, jakým aktivujeme virtuální prostředí v prostředí Linuxu. Více o práci s virtuálními prostředími v Pythonu na jiných operačních systémech si můžete přečíst. Poslední instrukcí je příkaz EXPOSE, který nastavuje port 8000, na kterém bude kontejner za běhu naslouchat.

V tuto chvíli je váš Dockerfile téměř kompletní, kromě výchozího příkazu, který se spustí při spuštění kontejnerů. Pojďme si ho definovat v další části.

  • Porozumění výchozímu příkazu obrazu Dockeru

Při spouštění kontejneru Docker můžete zadat příkaz, který se má provést. Pokud však příkaz nezadáte, výchozí příkaz obrazu Dockeru určí, co se stane při spuštění kontejneru. K definování výchozího příkazu v souboru Dockerfile používáme instrukce ENTRYPOINT nebo CMD samostatně nebo společně.

Pokud se rozhodnete definovat jak ENTRYPOINT, tak CMD, v instrukci ENTRYPOINT definujete spustitelný soubor, který bude kontejnerem spuštěn. V instrukci CMD definujete výchozí seznam argumentů pro tento spustitelný příkaz. Výchozí seznam argumentů můžete přepsat připojením alternativních argumentů na příkazovém řádku při spouštění kontejneru ve formátu:

Tento formát bráních vývojářům ve snadném přepsání příkazu ENTRYPOINT. Příkaz ENTRYPOINT je definován tak, aby volal skript, který nastaví prostředí a provede různé akce na základě poskytnutého seznamu argumentů.

Instrukci ENTRYPOINT můžete použít i samostatně ke konfiguraci spustitelného souboru kontejneru. Tento formát však neumožňuje definovat výchozí seznam argumentů. Argumenty můžete zadat při spuštění kontejneru pomocí příkazu docker run .

Pokud se rozhodnete použít pouze CMD , Docker to interpretuje jako výchozí příkaz a seznam argumentů, které můžete za běhu přepsat. Více informací naleznete v oficiální referenční dokumentaci k Dockerfile.

. Podívejme se, jak můžeme informace, které jste se dozvěděli o výchozích příkazech, aplikovat na náš příklad kontejneru. Ve výchozím nastavení chceme aplikaci obsluhovat pomocí serveru gunicorn. I když seznam argumentů předávaných serveru gunicorn nemusí být konfigurovatelný za běhu, chceme mít flexibilitu spouštět jiné příkazy pro účely, jako je ladění nebo správa konfigurací (inicializace databáze, shromažďování statických souborů atd.). Jak vidíte, je v našem nejlepším zájmu použít CMD k definování výchozího příkazu, což nám umožní jej v případě potřeby přepsat.

Zde jsou některé syntaxe, které můžete použít k definování příkazu CMD :

  • CMD ["command", "argument 1", "argument 2", . . . ,"argument n"]: Formát exec (doporučený formát) přijímá příkaz a seznam argumentů. Spouští příkaz přímo bez zpracování shellem.
  • CMD command "argument 1" "argument 2" . . . "argument n": Formát shell definuje příkaz a seznam argumentů. Předává seznam příkazů shellu ke zpracování. To se může hodit, pokud chcete v příkazu nahradit proměnné prostředí, nicméně to není zcela předvídatelné.
  • CMD ["argument 1", "argument 2", . . . ,"argument n"]: Formát seznamu argumentů, definuje pouze výchozí seznam argumentů a používá se společně s ENTRYPOINT instrukcí.

Budeme používat formát exec pro definování naší finální instrukce v Dockerfile. Přidejte následující řádek na konec vašeho Dockerfile:

Nyní můžete uložit a zavřít Dockerfile.

Když spustíte kontejnery pomocí tohoto obrázku, spustí gunicorn navázaný na port localhostu 8000 se 3 workery a zavolají funkci application v souboru wsgi.py nalezeném v adresáři mysite . Můžete se rozhodnout poskytnout jiný příkaz, který přepíše výchozí příkaz při spuštění a spustí jiný proces namísto gunicornu. Možná se budete chtít dozvědět více o Gunicorn workerech.

Váš Dockerfile je nyní připraven a můžete použít docker build k sestavení obrazu aplikace. Můžete použít docker run ke spuštění kontejneru na vašem lokálním vývojovém stroji.

  • Sestavení Docker obrazu

Příkaz docker build bude ve výchozím nastavení hledat Dockerfile v aktuálním adresáři, aby našel své instrukce pro sestavení. Odesílá také „kontext“ sestavení démonu Docker. Kontext sestavení je sada souborů, které by měly být během procesu sestavení k dispozici. Ve výchozím nastavení je aktuální adresář, ve kterém spouštíte příkaz docker build , nastaven jako kontext sestavení.

Zatímco jste ve stejném adresáři, který obsahuje váš Dockerfile, spusťte příkaz docker build. Zadejte obraz a tag pomocí příznaku -t a nastavte aktuální adresář jako kontext sestavení pomocí tečky ( .) na konci příkazu:

V tomto příkazu jsme obraz pojmenovali django-polls a tag v1. Všimněte si tečky na konci příkazu, používáme ji k označení aktuálního adresáře jako kontextu sestavení.

Po dokončení docker build by se měl zobrazit výstup podobný následujícímu:

Building a Django and Gunicorn Application with Docker on Ubuntu 4

Váš Docker obraz je nyní připraven. Pokud bychom některé konfigurace nepřenesli do externích proměnných prostředí, mohli byste kontejner snadno spustit pomocí příkazu docker run. Nicméně, protože jsme nenakonfigurovali externí proměnné prostředí, které jsme nastavili v souboru settings.py, spuštění selže. Pojďme to dokončit v dalším kroku.

Krok 8: Nastavení běhového prostředí a testování aplikace

Blížíme se ke konci tohoto návodu. V tomto kroku budeme konfigurovat proměnné prostředí v souboru env . S nastavenými proměnnými v souboru env můžeme vytvořit schéma databáze, vygenerovat a nahrát statické soubory do externí služby úložiště objektů a nakonec aplikaci otestovat.

Docker přichází s několika metodami, které můžete použít k poskytnutí proměnných prostředí kontejneru. V našem případě chceme poskytnout seznam proměnných prostředí prostřednictvím souboru. Proto použijeme metodu --env-file.

Pomocí vašeho preferovaného editoru vytvořte soubor s názvem env v adresáři django_project:

Vložte následující seznam proměnných:

Proměnné v seznamu jsou ty, které jste definovali v předchozích krocích:

  • DJANGO_SECRET_KEY: Vygenerujte jedinečnou, nepředvídatelnou hodnotu, jak je vysvětleno v dokumentaci k Django. K vygenerování náhodného řetězce a jeho nastavení do proměnné můžete použít tento příkaz:

  • DEBUG: Tuto hodnotu jsme nastavili na True, ale pro produkční nasazení ji nezapomeňte nastavit na False tím, že ji ponecháte prázdnou.

  • DJANGO_LOGLEVEL: toto jsme nastavili na info, klidně ji upravte na požadovanou úroveň.

  • DJANGO_ALLOWED_HOSTS: nastavte tuto hodnotu na IP adresu serveru Ubuntu, na kterém běží vaše kontejnery Docker. Volitelně ji nastavte na *, což je zástupný znak odpovídající všem hostitelům, pokud jste ve vývojovém režimu.

  • DB_DATABASE: pokud jste použili jiný název databáze, nastavte jej zde odpovídajícím způsobem.

  • DB_USERNAME: nastavte tuto hodnotu na uživatelské jméno, které jste zvolili pro svou databázi.

  • DB_PASSWORD: nastavte tuto hodnotu na heslo, které jste zvolili pro svou databázi.

  • DB_HOST: nastavte tuto hodnotu na hostitele, na kterém běží vaše databázová instance, jak jste ji nastavili v Kroku jedna.

  • DB_PORT: nastavte tuto hodnotu na port vaší databáze.

  • STATIC_MINIO_BUCKET_NAME: nastavte tuto hodnotu na název bucketu, který jste vytvořili ve svém účtu cloudového úložiště MinIO.

Po dokončení úprav soubor uložte a zavřete.

Konfigurace prostředí jsou nyní připraveny. Musíme spustit kontejner a předat mu argumenty pro přepsání výchozího příkazu CMD a vytvořit schéma databáze pomocí příkazů manage.py makemigrations a manage.py příkazů migrate.

Zde je příkaz:

V tomto příkazu spouštíme obraz kontejneru django-polls:v1, přičemž k předání souboru s proměnnými prostředí používáme příznak env-file. Výchozí příkaz CMD také přepíšeme pomocí sh -c "python manage.py makemigrations && python manage.py migrate" Po spuštění tohoto příkazu ke spuštění kontejneru se vytvoří databázové schéma, jak je definováno v kódu aplikace.

V případě úspěchu byste měli vidět výstup podobný tomu níže:

Building a Django and Gunicorn Application with Docker on Ubuntu 4

Výstup indikuje, že databázové schéma bylo úspěšně vytvořeno.

Dalším krokem je vytvoření administrátorského uživatele pro aplikaci Django. Spustíme kontejner a otevřeme v něm interaktivní shell pomocí následujícího příkazu:

Příkaz spustí kontejner s příkazovým řádkem shellu, který můžete použít k interakci s shellem Pythonu. Pojďme vytvořit uživatele:

Postupujte podle výzev a zadejte uživatelské jméno, e-mailovou adresu, heslo, znovu zadejte heslo a stisknutím klávesy Enter uživatele vytvořte. Ukončete shell a ukončete kontejner stisknutím CTRL+D.

Dále musíme kontejner spustit znovu a přepsat výchozí příkaz příkazem Django collectstatic k vygenerování statických souborů pro aplikaci a jejich nahrání do vaší cloudové služby úložiště MinIO:

Po dokončení byste měli vidět podobný výstup jako níže, který indikuje, že se váš kontejner úspěšně připojil k úložné službě MinIO a nahrál statické soubory:

static files

Náš úložný bucket nyní vypadá takto, s adresáři, které Django vytvořil:

Building a Django and Gunicorn Application with Docker on Ubuntu 5

Nakonec nyní můžeme aplikaci spustit pomocí příkazu:

Zde je výstup:

output

Když spustíte výše uvedený příkaz, spustí se výchozí příkaz CMD ve vašem obrazu a zpřístupní se port 8000 jak je definováno. Nyní se Ubuntu na portu 80 se namapuje na 8000 port kontejneru django-polls:v1.

Nyní můžeme aplikaci otestovat v prohlížeči. Přejděte v prohlížeči na veřejnou IP adresu vašeho serveru: http://your_server_public_ip.

Očekávejte chybu 404 Stránka nenalezena, protože podle Django tutoriálu, jsme nedefinovali trasu pro / cestu:

page not found

Máme proměnnou DEBUG nastavenou na True, proto vidíme tuto chybovou stránku se spoustou klíčových informací. Zrušme nastavení proměnné DEBUG . Nejprve budete muset zastavit běžící kontejner pomocí CTRL+C. Poté otevřete env soubor:

Dále najděte proměnnou DEBUG a zrušte její nastavení, nebo ji nechte prázdnou. Necháme ji prázdnou, protože funkce getenv interpretuje False jako řetězec, a proto vrací true:

Uložte soubor a znovu spusťte kontejner pomocí příkazu:

Pokud navštívíte http://your_server_public_ip ve svém prohlížeči, měli byste vidět výchozí stránku 404:

not found

Viděli jste, jak můžete manipulovat s chováním vaší aplikace Django za běhu pomocí proměnných prostředí, aniž byste upravovali zdrojový kód.

Přejděte na http://your_server_public_ip/polls, abyste viděli domovskou stránku Polls:

Building a Django and Gunicorn Application with Docker on Ubuntu 6

Nemáme žádné ankety, protože jsme aplikaci právě nasadili.

Přejděte do administračního rozhraní: http://your_server_public_ip/admin, abyste viděli okno pro ověření administrátora:

polls administration

Pro přihlášení zadejte přihlašovací údaje, které jste nastavili pomocí příkazu createsuperuser . Nyní byste měli být na rozhraní administrační stránky:

site administration

Všimněte si, že všechny statické soubory jsou poskytovány z externí úložné služby, kterou jsme nastavili. Můžete kliknout pravým tlačítkem myši v okně prohlížeče a vybrat Zobrazit zdrojový kód stránky:

external storage

Můžete přidat nějaké otázky a možnosti a otestovat celkový výkon aplikace:

questions and choices

Vraťte se na index Polls http://your_server_public_ip/polls a zkuste hlasovat v otázce:

django framework

Poté, co vše otestujete a potvrdíte, že funguje podle očekávání, můžete kontejner ukončit.

Závěr

Úspěšně jste nakonfigurovali webovou aplikaci Django tak, aby dobře fungovala v prostředí založeném na kontejnerech. To zahrnovalo přizpůsobení aplikace pro práci s externími proměnnými prostředí, nastavení aplikace pro použití cloudové úložné služby pro statické soubory a vytvoření Dockerfile pro obraz kontejneru. Změny, které jsme provedli za účelem dockerizace aplikace, si můžete prohlédnout ve django-polls-docker větvi django-polls GitHub repozitáře.

Od této chvíle jsou možnosti omezeny pouze vaší představivostí. Můžete nastavit reverzní proxy Nginx, která bude stát mezi klienty a serverem Gunicorn. Můžete také přidat Certbot pro získání certifikátů TLS k zabezpečení vašeho serveru Nginx. Doporučujeme přidat HTTP proxy pro ukládání pomalých klientů do vyrovnávací paměti a ochranu vašeho serveru Gunicorn před útoky typu Denial of Service.

Zatímco ve spouštěcím příkazu Dockerfile jsme definovali 3 workery, můžete si nastavit preferovaný počet v závislosti na prostředcích dostupných na vašem serveru. Více informací naleznete v oficiální dokumentaci návrhu Gunicorn. Pokud si přejete, můžete sestavený obraz Dockeru odeslat na Dockerhub a zkusit jej nasadit v několika prostředích, která mají nainstalovaný Docker. Pokud se chcete dozvědět více, sledujte náš blog s návody, protože budeme připravovat navazující návod, jak zabezpečit aplikaci Django pomocí Nginx a Let’s Encrypt.

Na závěr uvádíme další zdroje, které vám pomohou s využitím Dockeru:

Přejeme příjemnou práci s počítačem!

author

Shreyas Patil

Autor · CloudSigma

Preslav Dobrev je kreativní designér ve společnosti CloudSigma, který se zaměřuje na konzistentní firemní identitu prostřednictvím tradičních i inovativních marketingových kanálů. Je zdatný v propojování umělecké vize se strategickým marketingem za účelem vytváření působivých příběhů značky.

Komentáře

Zatím žádné komentáře. Buďte první.