Powrót do bloga

Konfiguracja Django z PostgreSQL, Nginx i Gunicorn na Ubuntu 20.04

Konfiguracja Django z PostgreSQL, Nginx i Gunicorn na Ubuntu 20.04

Django to darmowy i otwartoźródłowy framework aplikacji internetowych zbudowany w języku Python programowania. Django jest niezwykle szybki, bezpieczny i wysoce skalowalny. W rękach wykwalifikowanego programisty Django pozwala na szybkie stworzenie potężnej strony internetowej. Może bezproblemowo integrować się z popularnymi serwerami WWW (Apache, Nginx) oraz bazami danych (MySQL, MariaDB, PostgreSQL, Oracle, a także SQLite), itp. Django napędza niektóre z największych witryn internetowych na świecie, takich jak Instagram, Mozilla i NASA. Ten przewodnik pokazuje, jak skonfigurować podstawę aplikacji internetowej za pomocą Django z PostgreSQL, Nginx i Gunicorn na systemie Ubuntu 20.04.

Wymagania wstępne

Ten przewodnik wymaga posiadania serwera z systemem Ubuntu 20.04, skonfigurowanego z podstawową zaporą sieciową (firewallem) oraz użytkownika innego niż root z uprawnieniami sudo. Zapoznaj się z tym szczegółowym przewodnikiem na temat tego, jak skonfigurować serwer Ubuntu. Postępuj zgodnie z tym samouczkiem, aby skonfigurować użytkownika innego niż root z uprawnieniami sudo. Możesz również skonfigurować zaporę sieciową Iptables, postępując zgodnie z krokami w tym przewodniku.

Zainstalujemy Django w środowisku wirtualnym. Posiadanie środowiska dedykowanego dla konkretnego projektu pozwala na łatwiejsze zarządzanie wieloma projektami na tym samym serwerze. Po skonfigurowaniu baz danych i aplikacji wdrożymy serwer aplikacji Gunicorn. Gunicorn będzie interfejsem aplikacji, który tłumaczy żądania klientów z protokołu HTTP na wywołania Pythona, z których nasza aplikacja może korzystać. Następnie wdrożymy serwer Nginx przed Gunicornem ze względu na jego szybką obsługę połączeń i łatwe do wdrożenia funkcje bezpieczeństwa.

Instalacja niezbędnych pakietów

Na początek zainstaluj wszystkie niezbędne pakiety. Na szczęście wszystkie te pakiety są bezpośrednio dostępne w oficjalnych repozytoriach pakietów Ubuntu. Otwórz terminal i zaktualizuj APT pamięć podręczną pakietów:

Lista pakietów zależy od tego, czy aplikacja internetowa będzie korzystać z Pythona 2, czy Pythona 3. Uruchom następujące polecenie, aby zainstalować Django z Pythonem 3:

Django 1.11 LTS to ostatnie wydanie Django, które będzie wspierać Pythona 2. Jeśli zamierzasz używać Django z Pythonem 2, zainstaluj następujące pakiety:

Baza danych i użytkownik PostgreSQL

Jako rozwiązanie bazodanowe wykorzystamy PostgreSQL. To potężny, otwartoźródłowy obiektowo-relacyjny system baz danych. PostgreSQL oferuje niezawodność, solidność i wydajność. Szczegółowe kroki dotyczące konfiguracji PostgreSQL znajdziesz w tym przewodniku na temat konfiguracji PostgreSQL na serwerze Ubuntu. Na potrzeby tego przewodnika skonfigurujemy dedykowaną bazę danych i użytkownika dla naszej aplikacji Django.

Domyślnie PostgreSQL implementuje „uwierzytelnianie peer” (peer authentication) jako schemat uwierzytelniania dla połączeń lokalnych. W skrócie, „uwierzytelnianie peer” uwierzytelni logowanie, jeśli nazwa użytkownika systemu operacyjnego odpowiada prawidłowej nazwie użytkownika PostgreSQL. Podczas instalacji PostgreSQL skonfigurował użytkownika systemu operacyjnego postgres odpowiadającego użytkownikowi administracyjnemu PostgreSQL o nazwie postgres. Zaloguj się do interaktywnej sesji powłoki PostgreSQL jako użytkownik postgres za pomocą następującego polecenia:

Trafisz do wiersza poleceń PostgreSQL. Pierwszym krokiem jest utworzenie dedykowanej bazy danych dla projektu. Na potrzeby demonstracji baza danych będzie nosić nazwę viktor_project:

Kolejnym krokiem jest utworzenie dedykowanego użytkownika dla bazy danych projektu. Użytkownik powinien mieć silną nazwę użytkownika. Na potrzeby demonstracji nazwa użytkownika będzie brzmieć viktor_project_user:

Nowy, we will modify some parameters:

  • Określone parametry połączenia. W skrócie, nie będzie wymagane odpytywanie i ustawianie poprawnych wartości przy każdym nawiązywaniu połączenia. Znacznie poprawia to wydajność bazy danych.
  • Domyślne kodowanie na UTF-8. Jest to uniwersalne kodowanie i Django go oczekuje.
  • Domyślny schemat izolacji transakcji na „read committed”. Blokuje on odczyt z niezatwierdzonych transakcji.
  • Strefa czasowa na UTC.

Wszystkie te zmiany parametrów są zalecane przez sam projekt Django. Aby wdrożyć te zmiany, uruchom następujące polecenia. Nie zapomnij zmienić nazwy użytkownika bazy danych na właściwą:

Zmień administratora bazy danych na dedykowanego użytkownika bazy danych:

Nasza praca z PostgreSQL jest na razie zakończona. Wyjdź z interaktywnej powłoki PostgreSQL:

Exit the PostgreSQL interactive shell

Wirtualne środowisko Pythona

Po przygotowaniu bazy danych możemy teraz skupić się na spełnieniu pozostałych wymagań projektu. Dla łatwiejszego zarządzania utworzymy wirtualne środowisko i zainstalujemy tam wszystkie wymagania Pythona. Aby wygenerować wirtualne środowisko, potrzebujemy narzędzia virtualenv. Można je łatwo zainstalować za pomocą pip.

Poniższe polecenia zaktualizują pip i zainstalują virtualenv. Dla Pythona 3 uruchom następujące polecenia:

Dla Pythona 2 uruchom zamiast tego następujące polecenia:

Po tym, jak virtualenv zostanie zainstalowany, nadszedł czas na utworzenie wirtualnego środowiska. Następnie utwórz dedykowany katalog dla wirtualnego środowiska:

Następnie zmień bieżący katalog aktywny na dedykowany katalog dla wirtualnego środowiska:

Wewnątrz tego katalogu uruchom następujące polecenie. Narzędzie virtualenv utworzy wirtualne środowisko o nazwie projektu:

Utworzy to podkatalog o nazwie projektu. Podkatalog ten będzie zawierał lokalną wersję Pythona oraz pip. Zapewnia to elastyczność w instalowaniu i konfigurowaniu odizolowanego środowiska Python dla projektu.

Poniższe polecenie aktywuje wirtualne środowisko:

activate the virtual environment

Znak zachęty terminala zmieni się, wskazując, że pracujesz w wirtualnym środowisku Pythona. Teraz, gdy jesteśmy w wirtualnym środowisku, zainstalujemy niezbędne wymagania Pythona. Potrzebujemy Django, Gunicorn oraz psycopg2 (adapter PostgreSQL). Poniższe polecenie nakaże lokalnemu pip zainstalowanie tych komponentów:

Nawet jeśli używasz Pythona 3, pip jest właściwym poleceniem. Dzieje się tak, ponieważ wewnątrz wirtualnego środowiska pip3 zmienia nazwę na pip.

Nowy projekt Django

Gdy komponenty Pythona są już na miejscu, możemy rozpocząć pracę z rzeczywistymi plikami projektu Django.

  • Tworzenie projektu Django

Katalog projektu jest już utworzony. Każemy Django zainstalować tam swoje pliki. Ta procedura wygeneruje katalog drugiego poziomu zawierający właściwy kod. Katalog ten będzie również zawierał skrypt zarządzający. Kluczem jest to, że jawnie wskazujemy Django katalog docelowy, zamiast pozwalat mu decydować o katalogu względem bieżącego:

Django odpowiednio utworzy projekt. Oto niektóre z ważnych plików i katalogów, na których się skupimy. Nazwy katalogów i plików są używane zgodnie z demonstracją.

  • ~/viktor_project/manage.py: Skrypt zarządzania projektem autorstwa Django.
  • ~/viktor_project/viktor_project/: Jest to pakiet zawierający projekt Django. Powinien zawierać pliki __init__.py, settings.py, urls.py, asgi.py oraz wsgi.py.
  • Dostosowywanie ustawień projektu

Po utworzeniu projektu pierwszą rzeczą do zrobienia jest dostosowanie jego konfiguracji. Otwórz settings.py w edytorze tekstu:

Pierwszą dyrektywą, której szukamy, jest ALLOWED_HOSTS. Definiuje ona serwery lub nazwy domen, które mogą łączyć się z instancją Django. Jeśli jakiekolwiek żądanie przychodzące z nagłówkiem Host nie pasuje do listy ALLOWED_HOSTS, wygeneruje to wyjątek. Jest to zalecane przez Django, aby uniknąć niektórych rodzajów luk bezpieczeństwa:

ALLOWED_HOSTS

Kolejną sekcją, na której się skupimy, jest DATABASE. Zarządza ona dostępem do bazy danych. Domyślnie zawiera konfigurację dla silnika bazy danych SQLite. Jednak w tym projekcie użyjemy bazy danych PostgreSQL. Django użyje adaptera psycopg2 do komunikacji z PostgreSQL:

django 1

Teraz przejdź na sam dół pliku. Dodaj następujące linie, aby wskazać lokalizację plików statycznych. Pomoże to Nginx obsługiwać żądania dotyczące tych elementów:

static

Nasza praca z settings.py jest na razie zakończona. Zapisz plik i zamknij edytor.

  • Finalizowanie wstępnej konfiguracji projektu

Możemy teraz zmigrować początkowy schemat bazy danych do dedykowanej bazy danych PostgreSQL. Uruchom następujące polecenie:

Następnie musimy utworzyć superużytkownika dla projektu. Aby wygenerować superużytkownika, uruchom następujące polecenie:

viktor_project

Zbierz wszystkie pliki statyczne w lokalizacji określonej w settings.py. Pliki statyczne zostaną zebrane w osobnym katalogu o nazwie „static” w katalogu projektu:

Teraz musimy popracować nad zaporą sieciową serwera. Jeśli postępowałeś zgodnie z przewodnikiem konfiguracji serwera, masz już skonfigurowany i aktywowany UFW. Utworzymy wyjątek dla portu 8000. Jest to domyślny port używany przez Django. Zapoznaj się z tym przewodnikiem, aby dowiedzieć się więcej o podstawach i użyciu zapory sieciowej UFW.

Następnie zweryfikuj działanie:

Na koniec możemy przetestować działanie serwera. Uruchom serwer deweloperski Django:

Jeśli konfiguracja przebiegła pomyślnie, serwer deweloperski Django powinien się uruchomić i akceptować przychodzące żądania. Otwórz przeglądarkę i przejdź pod adres IP/domenę swojego serwera na porcie 8000:

django 2

Powinieneś trafić na domyślną stronę główną Django. Aby uzyskać dostęp do panelu administracyjnego, dodaj /admin na końcu adresu URL. Panel administracyjny jest dostępny tylko dla superużytkownika, którego utworzyliśmy wcześniej:

Po zalogowaniu trafisz na domyślny interfejs administracyjny Django:

django 3

Na razie zakończyliśmy testowanie. Aby zatrzymać serwer, naciśnij „Ctrl + C” w oknie terminala.

  • Testowanie Gunicorn

Przed opuszczeniem środowiska wirtualnego chcemy upewnić się, że Gunicorn może obsługiwać aplikacje. Sposobem na przetestowanie tego jest użycie Gunicorn do załadowania modułu WSGI projektu.

Polecenie Gunicorn znajduje się w katalogu projektu:

To uruchomi Gunicorn na tym samym interfejsie, na którym działało Django. Możemy ponownie przetestować aplikację w zwykłej przeglądarce internetowej. Zwróć uwagę, że interfejs administracyjny nie będzie miał zastosowanych żadnych stylów, ponieważ Gunicorn nadal nie wie, jak znaleźć statyczną zawartość CSS:

Po zakończeniu naciśnij „Ctrl + C” w oknie terminala, aby zatrzymać serwer Gunicorn.

  • Opuszczanie środowiska wirtualnego

Konfiguracja aplikacji Django została zakończona. Uruchom następujące polecenie, aby wyjść ze środowiska wirtualnego:

Pliki gniazda i usługi Gunicorn

Zweryfikowaliśmy, że Gunicorn może wchodzić w interakcję z aplikacją Django. Potrzebujemy jednak bardziej niezawodnego sposobu zarządzania serwerem aplikacji. Tutaj do gry wkracza systemd. Systemd to jeden z najpopularniejszych systemów inicjalizacji dostępnych w systemie Linux. Oto szczegółowy przewodnik po tym, jak zarządzać usługami i jednostkami systemd.

Możemy utworzyć pliki gniazda i usługi dla Gunicorn, aby systemd mógł nim zarządzać tak, jakby był usługą. Przy rozruchu zostanie wygenerowane gniazdo Gunicorn. Gniazdo będzie nasłuchiwać połączeń przychodzących. Gdy nastąpi połączenie, systemd uruchomi procesy Gunicorn w celu obsługi tego połączenia.

  • Gniazdo Gunicorn

Zacznijmy od utworzenia gniazda Gunicorn. Plik musi zostać utworzony z uprawnieniami sudo:

Wprowadź następujący kod wewnątrz pliku:

Jak widać, kod składa się z trzech sekcji.

  • [Unit]: Ta sekcja opisuje gniazdo.
  • [Socket]: Definiuje lokalizację gniazda.
  • [Install]: Ta część zapewnia, że systemd utworzy gniazdo we właściwym czasie.

Zapisz plik i zamknij edytor.

  • Usługa Gunicorn

Następnie utworzymy plik usługi dla Gunicorn. Podobnie jak plik gniazda, on również musi zostać utworzony z uprawnieniami sudo:

Wprowadź następujący kod:

Kod zawiera wiele sekcji:

  • [Unit]: Ta sekcja określa metadane i zależności. Opisuje również uruchamianie dopiero po osiągnięciu celu sieciowego.
  • [Service]: Ta sekcja określa użytkownika i grupę, w ramach których będzie uruchamiany proces. Właścicielem grupy jest „www-data”, dzięki czemu Nginx może komunikować się z Gunicornem. Mapuje ona również katalogi robocze i określa polecenia startowe.
  • [Install]: Ta sekcja informuje systemd, z czym powiązać tę usługę, jeśli jest włączona przy rozruchu. Powinna ona uruchomić się po uruchomieniu zwykłego systemu wieloużytkownikowego.

Następnie zapisz plik i zamknij edytor.

  • Włączanie gniazda Gunicorn

Gniazdo Gunicorn jest gotowe do użycia. W związku z tym możesz uruchomić następujące polecenia. Spowoduje to uruchomienie i włączenie gniazda. Plik gniazda zostanie utworzony w /run/gunicorn.sock przy rozruchu. Po nawiązaniu połączenia z gniazdem systemd uruchomi usługę Gunicorn w celu jego obsługi:

Sprawdź status gniazda Gunicorn:

Teraz sprawdź istnienie pliku gniazda:

Jeśli status z systemctl wskazuje na błąd lub plik gunicorn.sock nie został znaleziony, oznacza to, że gniazdo nie zostało utworzone poprawnie. Sprawdź szczegółowy log w poszukiwaniu wskazówek:

gunicorn.socket

Nie zapomnij ponownie przyjrzeć się plikowi gunicorn.socket pod kątem potencjalnych błędów.

  • Aktywacja gniazda

Do tej pory uruchomiliśmy gunicorn.socket. Jednak bez żadnego żądania połączenia usługa gunicorn.service nie aktywuje się. Następnie zweryfikuj status Gunicorna:

Możemy przetestować mechanizm aktywacji gniazda, wysyłając żądanie połączenia za pomocą curl:

Powinieneś otrzymać kod HTML z aplikacji. Oznacza to, że Gunicorn uruchomił się pomyślnie i był w stanie obsłużyć aplikację Django. Zweryfikuj bieżący status usługi Gunicorn:

Jeśli wystąpi jakiekolwiek nieoczekiwane zachowanie lub dane wyjściowe (wskazujące na błąd), sprawdź szczegółowe logi w poszukiwaniu wskazówek:

Jeśli wprowadzono zmiany w pliku gunicorn.service, musisz przeładować demona, aby ponownie odczytać definicję usługi. Wymaga to również ponownego uruchomienia usługi Gunicorn:

Konfiguracja Nginx

Teraz skonfigurujemy Nginx, aby przekazywał ruch przychodzący do procesu. Najpierw utwórz nowy blok serwera w Nginx:

Następnie wprowadź następujący kod:

 

Oto kilka bloków w konfiguracji:

  • service: Ten blok definiuje, że serwer powinien normalnie nasłuchiwać na porcie 80 i odpowiadać na nazwę domeny lub adres IP serwera.
  • location: To jest pierwszy wpis lokalizacji. Definiuje on, gdzie znaleźć zasoby statyczne.
  • location: To jest drugi wpis lokalizacji. Ten blok definiuje standardowe parametry proxy oraz sposób przekazywania ruchu do gniazda Gunicorn.

Zapisz plik i zamknij edytor. Powiąż plik z katalogiem „sites-enabled”, aby go aktywować:

Następnie sprawdź, czy w konfiguracji Nginx nie ma błędów składniowych:

Jeśli nie znaleziono błędu, zrestartuj Nginx, aby wdrożyć zmianę:

Musimy ponownie zmodyfikować reguły UFW. Nie potrzebujemy już dostępu do serwera deweloperskiego, więc możemy usunąć wyjątek dla portu 8000. Dodatkowo chcemy otworzyć port 80 dla normalnego ruchu:

Zweryfikuj te zmiany reguł zapory sieciowej:

Serwer powinien być teraz dostępny z poziomu zwykłej przeglądarki internetowej.

Procedury rozwiązywania problemów

Jeśli wszystkie kroki zostały wykonane prawidłowo, aplikacja Django powinna być dostępna przez internet. Jeśli tak nie jest, oznacza to, że instalacja nie przebiegła zgodnie z planem. Musimy przeprowadzić diagnostykę, aby ustalić źródło problemu.

  • Nginx wyświetla stronę domyślną

Jeśli Nginx wyświetla stronę domyślną zamiast serwera proxy aplikacji, zazwyczaj oznacza to, że server_name został nieprawidłowo skonfigurowany w bloku serwera.

W tym przykładzie blok serwera jest przechowywany w następującej lokalizacji:

Wpis server_name określa, którego bloku serwera Nginx użyje do odpowiadania na żądania. Jeśli wyświetlana jest strona domyślna, Nginx prawdopodobnie nie był w stanie dopasować żądania do konkretnego bloku serwera, więc zamiast tego korzysta z bloku domyślnego:

Sprawdź, czy blok serwera Twojego projektu Django ma prawidłową wartość server_name.

  • 502 Bad Gateway

Błąd 502 wskazuje, że Nginx nie mógł pomyślnie przekierować żądania. Istnieje szeroki zakres potencjalnych problemów konfiguracyjnych, które mogą prowadzić do błędu 502, dlatego potrzebujemy wskazówek, aby przeprowadzić właściwą diagnostykę.

Głównym źródłem wskazówek są dzienniki błędów Nginx. Zazwyczaj wskazują one na warunki, które spowodowały problemy podczas proxy. Sprawdź dziennik błędów Nginx za pomocą następującego polecenia:

Po otwarciu dziennika spróbuj ponownie uzyskać dostęp do serwera. Powinno to wygenerować nowy komunikat o błędzie w dzienniku. Może to pomóc zawęzić problem. Oto kilka możliwych komunikatów:

  • connect() to unix:/run/gunicorn.sock failed (2: No such file or directory)

Wskazuje to, że Nginx nie mógł znaleźć gunicorn.sock w lokalizacji zdefiniowanej w konfiguracji. Lokalizacja ta jest określona przez dyrektywę proxy_pass w bloku witryny. Sprawdź, czy proxy_pass wskazuje właściwą lokalizację gunicorn.sock wygenerowanego przez jednostkę systemd gunicorn.socket:

Jeśli gunicorn.sock nie został znaleziony w katalogu /run, oznacza to, że systemd nie mógł go wygenerować. Należy ponownie sprawdzić kroki konfiguracji pliku gniazda Gunicorn.

  • connect() to unix:/run/gunicorn.sock failed (13: Permission denied)

Wskazuje to, że Nginx nie mógł połączyć się z gniazdem Gunicorn z powodu problemów z uprawnieniami. Może się tak zdarzyć, jeśli proces został wykonany jako użytkownik root zamiast użytkownika sudo. Chociaż systemd pomyślnie wygenerował gunicorn.sock, Nginx nie jest w stanie go użyć.

Jednym z możliwych powodów mogą być ograniczone uprawnienia między katalogiem głównym (/) a plikiem gunicorn.sock. Sprawdź uprawnienia i własność pliku gniazda oraz każdego z jego katalogów nadrzędnych:

Pierwsza kolumna opisuje uprawnienia do pliku. Druga kolumna opisuje właściciela (użytkownika), a trzecia właściciela grupy. Jeśli którykolwiek z katalogów prowadzących do gunicorn.sock nie ma odpowiednich uprawnień do odczytu i wykonywania, Nginx nie uzyska dostępu do gniazda.

  • Django wyświetla „could not connect to the server: Connection refused”

Wskazuje to, że Django nie mogło połączyć się z serwerem PostgreSQL. Upewnij się, że serwer PostgreSQL jest uruchomiony i działa:

Jeśli nie działa, uruchom następujące polecenia, aby go uruchomić i włączyć:

sudo systemctl enable postgresql

Jeśli nadal występuje ten błąd, upewnij się, że dane uwierzytelniające bazy danych są poprawnie zdefiniowane w settings.py:

Więcej informacji o rozwiązywaniu problemów

W celu dodatkowego rozwiązywania problemów przygotowano różne logi. Logi te mogą pomóc zawęzić źródła problemów.

Oto lista logów, które mogą pomóc:

  • Logi Nginx
  • Logi dostępu - Nginx
  • Logi błędów - Nginx
  •  Logi aplikacji - Gunicorn
  •  Logi socketów - Gunicorn
Po dokonaniu jakiejkolwiek aktualizacji konfiguracji lub aplikacji może być konieczne ponowne uruchomienie procesów w celu zastosowania zmian. Jeśli aplikacja Django została zaktualizowana, zrestartuj proces Gunicorn, aby zastosować zmiany:
W przypadku wprowadzenia zmian w plikach socketu lub usługi Gunicorn, przeładuj demona i zrestartuj procesy:
Jeśli wprowadzono zmiany w konfiguracji bloku serwera Nginx, należy ją przetestować przed wdrożeniem. Wymaga to również zrestartowania Nginx:

Podsumowanie

Ten poradnik pomyślnie pokazuje, jak położyć fundamenty pod Django. Django dostarcza wiele typowych komponentów aplikacji internetowej, pozwalając skupić się na unikalnych elementach. Projekt Django będzie działał w środowisku wirtualnym. Gunicorn zarządza komunikacją między żądaniami klientów a Django. Na koniec, Nginx działa jako reverse proxy do obsługi połączeń klientów.

Miłego korzystania!

author

Hark Labs

Autor · CloudSigma

Preslav Dobrev jest projektantem kreatywnym w CloudSigma, skupiającym się na spójnej tożsamości biznesowej przy wykorzystaniu tradycyjnych i innowacyjnych kanałów marketingowych. Biegle łączy wizję artystyczną ze strategicznym marketingiem, tworząc wywierające wpływ narracje marki.

Komentarze

Brak komentarzy. Bądź pierwszy.