Tworzenie aplikacji nie jest proste i wie to każdy programista. Najtrudniejsze jest jednak rozpoczęcie swojej przygody, więc tym razem Przemek chciałby pomóc w tej kwestii, czyli rozpoczęcia pracy z Pythonem i Dockerem podczas pracy na systemie Windows.
Wielu deweloperów ze względu na wygodę decyduję się na pracę w środowisku najbliższym aplikacji, na którym będzie wystawiona na produkcję. Pozwala to między innymi na uniknąć niepożądanych problemów integracji międzyplatformowej oraz redukuje to koszt złożonych i drogich narzędzi deweloperskich, które oferują do jakiegoś stopnia integrację wieloplatformową. Ci, którzy nie dysponowali dużym budżetem i specjalistycznym wsparciem technicznym jeszcze do niedawna z góry byli skazani na różne formy obejścia, np. stawiając paralelnie dwa systemy operacyjne spięte pod jedną boot’owalną partycją efi, bądź instalacją maszyn wirtualnych z użyciem Virtualbox’a czy VMWare’a. Z inicjatywą na rozwiązanie potrzeb mniejszych deweloperów wyszedł Microsoft, który po raz pierwszy wprowadził wbudowany w system Win10 wsparcie dla obsługi systemów Linux’owych. WSL (Windows Subsystem for Linux) w pierwszej generacji nie był pełnym systemem i opierał się częściowo o zasoby systemowe Windows’a. Nie posiadał własnego jądra, stąd też nie mógł korzystać w pełni z własnych wywołań systemowych i bezpośrednio korzystać z zasobów sprzętowych. Z tego względu takie narzędzia deweloperskie jak konteneryzacja z użyciem Dockera nie było jeszcze możliwe do zrealizowania. Ale wraz z wejściem w życie najnowszej stabilnej wersji Win10 2004 w maju bieżącego roku deweloperzy otrzymali stabilne niezawodne narzędzie jakim jest WSL2. Microsoft w swojej dokumentacji WSL and WSL2 Comparision przedstawia podstawowe różnice jakie wprowadzono w aktualizacji. Te zmiany umożliwiły pełne wsparcie dla konteneryzacji Dockera i nie tylko. WSL2 nie jest uzależniony już od systemu plików Windows’a oraz umożliwia udostępnienie serwera X, co dla mniej wtajemniczonych oznacza: Tak jest możliwe uruchomienie aplikacji z interfejsem graficznym pod WSL. Więcej o tym i jak to zrobić można przeczytać tutaj: Running WSL GUI Apps on Windows 10
WSL na start – Instalacja najnowszej aktualizacji Windows’a maj 2020
W pierwszej kolejności wypadałoby sprawdzić jaką aktualnie mamy wersję systemu. Najprościej jest to zrobić wpisując w pasek zadań winver
![WSL Python Django Docker 1](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/1.png?resize=640%2C485&ssl=1)
![WSL Python Django Docker 2](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/2.png?resize=460%2C423&ssl=1)
Jeżeli wersja jest wyższa niż 1903 i build wyższy niż 18362 nie ma pilnej potrzeby aktualizacji do nowszej wersji w celu instalacji WSL2, ale zalecana jest mimo wszystko aktualizacja do najnowszej stabilnej wersji.
Klasycznie można zaktualizować Windowsa korzystająć z opcji Windows Update w ustawieniach systemu Win10. Jak należy to zrobić wytłumaczone jest w dokumentacji od Microsoftu pod linkiem Pobieranie aktualizacji systemu Windows 10 z maja 2020 r.. Jeżeli z jakichś przyczyn najnowsza aktualizacja się nie wyświetli, można spróbować zaktualizować system ręcznie korzystając z Asystenta aktualizacji. Możliwe jest też aktualizacja Windows’a do wersji preview, która nie jest oficjalnie wydana i żeby z niej skorzystać należy zasubskrybować opcję Windows Insider Program:
![WSL Python Django Docker 3](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/3.png?resize=640%2C500&ssl=1)
Więcej o tym jak to zrobić można przeczytać pod linkiem Getting started with the Windows Insider Program, ale nie jest to zalecane, ze względu na bardzo zawodne funkcjonowanie WSL2.
WSL – Instalacja i aktualizacja do WSL2
Po tym jak upewniliśmy się, że system spełnia wymogi do instalacji WSL2 możemy przejść do głównego etapu stawiana środowiska. Bardzo pomocna będzie w tym szczegółowa dokumentacja Microsoftu: Install Windows Subsystem for Linux . W pierwszej kolejności trzeba uruchomić Windows’owy shell systemowy PowerShell z uprawnieniami administratora.
![WSL Python Django Docker 4](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/4.png?resize=640%2C485&ssl=1)
Następnie wprowadzamy polecenie w shellu w celu umożliwienia instalacji WSL:
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
![WSL Python Django Docker 5](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/5.png?resize=640%2C364&ssl=1)
Następnie wprowadzamy polecenie w shellu w celu umożliwienia aktualizacji do WSL2:
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
![WSL Python Django Docker 6](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/6.png?resize=640%2C364&ssl=1)
Pobieramy i instalujemy aktualizację do WSL2 link
Na koniec w shellu poniższym poleceniem ustawiamy dla WSL domyślną wersję 2:
wsl --set-default-version 2
Powyższe operacje mogą zajać trochę czasu, a system będzie wymagał ponownego uruchomienia w celu wprowadzenia zmian. Po pomyślnym przejściu tego etapu możemy w końcu zainstalować wybraną przez nas dystrybucję Linux’a. Należy uruchomić aplikację Microsoft Store i wpisać dystrybucję, którą chcemy zainstalować. Do wyboru mamy:
- Ubuntu 16.04 LTS
- Ubuntu 18.04 LTS
- Ubuntu 20.04 LTS
- openSUSE Leap 15.1
- SUSE Linux Enterprise Server 12 SP5
- SUSE Linux Enterprise Server 15 SP1
- Kali Linux
- Debian GNU/Linux
- Fedora Remix for WSL
- Pengwin
- Pengwin Enterprise
- Alpine WSL
![WSL Python Django Docker 7](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/7.png?resize=640%2C361&ssl=1)
Dobrym wyborem na start będzie Ubuntu 20.04 LTS, ze względu na najbardziej powszechne użycie i najlepsze wsparcie. Tu w celach prezentacyjnych pokażę OpenSUSE, ale nie ma większej różnicy w instalacji różnych dystrybucji pod WSL2.
Po pobraniu wpisujemy w pasku zadań naszą dystrubucję i uruchamiamy, należy odczekać chwilę i voilà mamy zainstalowaną dystrybucję linuksa pełną gębą.
![WSL Python Django Docker 8](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/9.png?resize=640%2C484&ssl=1)
![WSL Python Django Docker 9](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/8.png?resize=640%2C335&ssl=1)
Takimi rzeczami jak konfiguracja sieci i inne podstawowe rzeczy są z góry załatwione. Utworzony jest most sieciowy, z naszą dystrybucją, dzięki czemu mamy pełną łączność ze światem z poziomu dystrybucji. Możemy to sprawdzić wpisując w PowerShella ipconfig
, a w WSL ip a show dev eth0
:
![WSL Python Django Docker 10](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/10.png?resize=640%2C545&ssl=1)
![WSL Python Django Docker 11](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/11-1.png?resize=640%2C669&ssl=1)
Instalacja Docker Desktop
Kolejnym krokiem będzie instalacja zaplecza Dockera, dzięki któremu będzie możliwe korzystanie z wirtualizacji WSL2 do zarządzania kontenerami pod Windows’em. link
Po zainstalowaniu Docker-Desktop i wejściu w ustawienia, możemy zobaczyć, że demon Docker’a będzie korzystał z wirtualizacji WSL2.
![WSL Python Django Docker 12](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/13.png?resize=640%2C424&ssl=1)
O developmencie z użyciem Docker’a i WSL2 można przeczytać tutaj: Docker Desktop WSL 2 backend
Teraz należałoby doinstalować również podstawowe narzędzia potrzebne do zarządzania kontenerami Docker’a. Należy uruchomić dystrybucję i uruchomić polecenie w shellu:
$ sudo apt -y install docker docker-compose
![WSL Python Django Docker 13](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/12.png?resize=640%2C335&ssl=1)
![WSL Python Django Docker 14](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/14.png?resize=640%2C335&ssl=1)
Instalacja Visual Studio Code i konfiguracja do pracy z WSL
Obecnie najlepszym środowiskiem deweloperskim, które spina wszystkie powyższe technologie jest Visual Studio Code od Microsoft’u.
![WSL Python Django Docker 15](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/15.png?resize=640%2C360&ssl=1)
By otrzymać wsparcie VS Code’a dla WSL2 należy zainstalować odpowiedni plugin. Najprościej jest to zrobić wciskając kombinację klawiszy Ctrl+Shift+x i wpisać „WSL”. Pierwsza pozycja Remote – WSL, instalujemy wtyczkę i możemy się cieszyć pełnym wsparciem dla WSL2.
![WSL Python Django Docker 16](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/16.png?resize=640%2C360&ssl=1)
Utworzenie bazowego projektu Django i jego deployment z użyciem Docker’a
W pierwszej kolejności należałoby utworzyć folder na naszą pierwszą aplikację.
![WSL Python Django Docker 17](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/18.png?resize=640%2C360&ssl=1)
![WSL Python Django Docker 18](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/17.png?resize=640%2C360&ssl=1)
Na ten moment folder z naszą aplikacją jest otwarty spod systemu Windows’a, aby otworzyć folder pod WSL2 należy wcisnąć zielony przełącznik w lewym dolnym rogu okna. Następnie wybieramy opcję Remote-WSL: Reopen Folder in WSL, a następnie naszą zainstalowaną dystrybucję.
![WSL Python Django Docker 19](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/19.png?resize=640%2C360&ssl=1)
![WSL Python Django Docker 20](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/20.png?resize=640%2C360&ssl=1)
Kolejno uruchamiamy terminal klikając prawym na pasku po lewej i wybieramy opcję Open in Integrated Terminal. Instalujemy podstawowe narzędzie, by móc przejść do dalszej pracy. W pierwszej kolejności pylint i pipenv. Pylint pomaga w pisaniu kodu w Pythonie i podpowiada składnię, a pipenv pozwoli nam na wprowadzenie wirtualnego środowiska w celu odizolowania narzędzi deweloperskich tylko na potrzebę tego projektu. Należy wykonać poniższe polecenie:
$ sudo apt -y install pylint pipenv
![WSL Python Django Docker 21](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/21.png?resize=640%2C360&ssl=1)
![WSL Python Django Docker 22](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/22.png?resize=640%2C360&ssl=1)
Na potrzebę naszej aplikacji django potrzebny będzie oddzielny katalog, który uprości nam później deployment.
$ mkdir src; cd src
Następnie uruchamiamy wirtualne środowisko wpisując polecenie:
$ pipenv shell .
![WSL Python Django Docker 23](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/23.png?resize=640%2C360&ssl=1)
Instalujemy przy aktywowanym środowisku podstawowe narzędzia: django i silnik bazodanowy do obsługi PostgreSQL psycopg2
$ pipenv install django psycopg2-binary
![WSL Python Django Docker 24](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/24.png?resize=640%2C360&ssl=1)
Tworzymy teraz nasz przykładowy projekt z aplikacją.
$ django-admin startproject example
Później wchodzimy do katalogu z projektem i tworzymy przykładową aplikację
$ django-admin startapp example_app
Kolejno potrzebujemy teraz skonfigurować nasz projekt korzystał z bazy danych Postgres’a i by dane do naszej bazy danych były pobierane jako zmienne środowiskowe. Otwieramy plik example/example/settings.py
i na samym początku zaciągamy moduł os, który będzie potrzebny do pobrania zmiennych ze środowiska.
""" Django settings for example project. Generated by 'django-admin startproject' using Django 3.1.1. For more information on this file, see https://docs.djangoproject.com/en/3.1/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/3.1/ref/settings/ """ from pathlib import Path import os # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent ...
Dodajemy naszą aplikację do zainstalowanych:
# Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'example_app' ] ...
I modyfikujemy sekcję DATABASES:
# Database # https://docs.djangoproject.com/en/3.1/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': os.getenv('POSTGRES_DB'), 'USER': os.getenv('POSTGRES_USER'), 'PASSWORD': os.getenv('POSTGRES_PASSWORD'), 'HOST': os.getenv('POSTGRES_HOST'), 'PORT': '', } } ...
Następnie w katalogu głównym całego projektu tworzymy plik .env i uzupełniamy go adekwatnymi zmiennymi:
![WSL Python Django Docker 25](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/25.png?resize=640%2C360&ssl=1)
Kolejno potrzebujemy, aby nasza aplikacja była uruchamiana w kontenerze, stąd należy utworzyć plik Dockerfile, aplikacja opiera się cała na pythonie, więc zaciągniemy gotowy obraz python:3.8-slim.
FROM python:3.8-slim
Kolejno na potrzebę kontenera tworzymy domyślnego użytkownika z odpowiednimi ograniczonymi uprawnieniami, spod którego aplikacja będzie uruchamiana.
ENV ENVIRONMENT docker ENV NAME example ENV HOME /home/$NAME ENV APP /home/$NAME/app RUN useradd --create-home --home-dir $HOME -u 1000 $NAME \ && mkdir -p $HOME \ && chown -R $NAME:$NAME $HOME
Aby aplikacja w kontenerze działała prawidłowo potrzebuje dostępu do podstawowych narzędzi, bo mogła uruchomić aplikację:
RUN ["pip", "install", "pipenv"]
Wskazujemy, gdzie skopiować pliki naszej aplikacji do katalogu roboczego w kontenerze. Aby to zrobić prawidłowo należy wpierw zmienić użytkownika example, a następnie skopiować pliki z przekazaniem uprawnień dla naszego użytkownika.
USER $NAME COPY --chown=$NAME ./src $APP WORKDIR $APP
Na koniec instalujemy zależności dla naszego projektu i uruchamiamy skrypt inicjalizujący i uruchamiający naszą aplikację.
RUN ["pipenv", "sync"] CMD ["/bin/bash", "entrypoint.sh"]
Całość pliku kontenera powinna wyglądać mniej więcej tak:
FROM python:3.8-slim ENV ENVIRONMENT docker ENV NAME example ENV HOME /home/$NAME ENV APP /home/$NAME/app RUN useradd --create-home --home-dir $HOME -u 1000 $NAME \ && mkdir -p $HOME \ && chown -R $NAME:$NAME $HOME RUN ["pip", "install", "pipenv"] USER $NAME COPY --chown=$NAME ./src $APP WORKDIR $APP RUN ["pipenv", "sync"] CMD ["/bin/bash", "entrypoint.sh"]
Teraz potrzebujemy napisać skrypt, który jak wyżej zostało wspomniane zainicjalizuje i uruchomi aplikację django. Potrzebujemy zmigrować modele bazodanowe i odpalić aplikację:
#!/bin/bash cd example pipenv run python manage.py migrate pipenv run python manage.py runserver 0.0.0.0:8000
Ostatnie co zostało do zrealizowanie to dostarczenie bazy danych dla naszej aplikacji, tu z pomocą przyjdzie nam docker-compose, który pozwala na wyrażenie jakie zależności zachodzą pomiędzy poszczególnym kontenerami. Upraszczając opis tych zależności, nasza aplikacja w swoim kontenerze nie posiada bazy danych, stąd potrzebujemy utworzyć kolejny kontener, w którym będzie uruchomiana instancja bazy PostgreSQL. Całość opisujemy w pliku docker-compose.yml i umieszczamy go w głównym katalogu projektu.
# version: '3.4' version: '3' services: example_app: env_file: - .env # wskazanie ścieżki do pliku ze zmiennymi środowiskowymi restart: unless-stopped # warunek restartu kontenera, gdyby coś poszło nie tak build: . # ścieżka do obrazu image: example # nazwa obrazu volumes: # wskazanie katalogów, które mają być zachowane nawet po tym jeśli kontener zakończy pracę - ./src:/home/jgportal/app ports: # porty które mają być wystawione (tutaj port dla naszej aplikacji django) - "8000:8000" depends_on: - example_db_host # wskazanie kontenera, który ma wpierw być uruchomiony jako kontener zależny (nasza baza danych) networks: - example # wskazanie do jakiej sieci należy kontener example_db_host: env_file: - .env restart: unless-stopped image: postgres:12-alpine volumes: - 'postgres_data:/var/lib/postgresql/data/' # baza danych musi zachowywać dane nawet jeśli ją zatrzymamy i uruchomimy ponownie ports: - "5432:5432" networks: - example # baza danych jest w tej samej sieci co nasza aplikacja networks: example: volumes: postgres_data: src:
Nareszcie na tym etapie pracy możemy sprawdzić owoce naszej pracy, by uruchomić całą usługę w głównym katalogu wpisujemy dwa polecenia:
$ docker-compose build $ docker-compose up
Jeżeli wszystko poszło zgodnie z planem, powinniśmy otrzymać podobny rezultat:
![WSL Python Django Docker 26](https://i0.wp.com/www.czarnaowca.it/wp-content/uploads/2020/10/26.png?resize=640%2C360&ssl=1)
Dowiedz się jeszcze o inny przydatnych rzeczach o Dockerze tutaj!