Docker dla programistów jest idealnym narzędziem developerskim, ponieważ w izolowanym środowisku jesteśmy w stanie uruchomić naszą aplikację czy też tak jak w tytule tego artykułu skryptu. Przeczytać na ten temat możesz w każdym artykule opisującym dockera. W związku z tym w dniu dzisiejszym chciałbym pokazać jak w najprostszy sposób uruchomić napisany przez nas skrypt w języku Python. Pierwszym etapem będzie stworzenie obrazu przy pomocy pliku Dockerfile z naszym skryptem. Ma to ogromne znaczenie przy testowaniu aplikacji, ponieważ możemy wypróbować wiele możliwości bez ponownych instalacji i konfiguracji.
W drugiej części artykułu pokażę w jaki sposób taki obraz przesłać do DockerHub tak aby był dostępny w każdym miejscu na świecie.
Słowo wstępu uważam, że mamy za sobą dlatego teraz stwórzmy prosty skrypt w języku Python.
Promocja na kursy z Cyberbezpieczeństwa!
Zapisy przyjmujemy do 13 listopada do 23:59! . Skorzystaj z promocji: https://asdevops.pl/nis2-promocja/
Skrypt Pythona
Nie chcę wprowadzać nic skomplikowanego, ponieważ musiałbym odbiec od głównego tematu artykułu. Dlatego użyjemy bardzo prostego kodu hello world:
#!/usr/bin/env python3
print("Hello World")
Jeżeli uczyłeś się programowania, to na pewno spotkałeś się z identycznym lub podobnie napisanym.
Celem tego skryptu, jak i materiału jest pokazanie w jak najprostszy sposób możesz go uruchomić, dlatego musisz mi wybaczyć prostotę jaką się posłużyłem przy jego tworzeniu. Jeżeli masz jakiś własny to śmiało podmień go, a następnie spróbuj uruchomić korzystając z tego artykułu.
Oczywiście skrypt z przykładu należy zapisać na dysku. Dla osób którzy nigdy nie mieli styczności z językiem Python lub z programowaniem, wystarczy że zapiszecie kod z przykładu jako hello.py, gdzieś na dysku.
Docker dla programistów – tworzymy Dockerfile
Jeżeli chcemy stworzyć obraz pierwszym krokiem jest utworzenie tytułowego pliku. Otóż jeżeli skorzystamy z pliku Dockerfile stworzymy obraz, a nie kontener. W związku z tym będziemy w stanie stworzyć niezliczoną ilość kontenerów wywodzących się z obrazu.
W tym momencie pojawiają się dwie możliwości z których możesz skorzystać by osiągnąć ten sam wynik.
Pierwsza z nich polega na przesłaniu obrazu do DockerHub dzięki czemu będziesz miał możliwość pobrania go tak jak robiłeś to z innymi.
Drugim jest przesłanie pliku Dockerfile ze skryptem, co z kolei może okazać się dość niewygodne.
Najwygodniejszym z dwóch wymienionych sposobów będzie przesłanie obrazu do DockerHub dlatego też w dalszej części postaram się pokazać jak po stworzeniu obrazu możemy tego dokonać. Natomiast teraz zajmijmy się plikiem Dockerfile.
System bazowy
Używamy języka Python, w związku z tym nasz obraz musi mieć go zainstalowanego. Dlatego też początek naszego Dockerfile powinien wyglądać w następujący sposób:
FROM python:latest
Dzięki tej dyrektywie zostanie pobrana najnowsza wersja Pythona jaka istnieje w repozytorium dockera.
Katalog roboczy
Musimy ustalić gdzie nasz skrypt zostanie zapisany. Osobiście preferuje katalog /opt natomiast możesz wybrać inne miejsce jakie najbardziej Ci odpowiada:
WORKDIR /opt/hello
Dla naszego skryptu zostanie utworzony katalog w /opt noszący nazwę hello.
Wgrywanie skryptu do obrazu
Abyśmy mogli uruchomić skrypt musi znaleźć się on w obrazie dlatego też w pliku Dockerfile używamy polecenia które przekopiuje z naszego dysku taki. Robimy to w poniższy sposób:
COPY hello.py ./
Aby móc skopiować plik w prezentowany sposób musi się znajdować w tym samym miejscu co plik Dockerfile. W przypadku gdy tak nie jest musisz podać do niego ścieżkę najlepiej bezwzględną. Jeżeli zastosowałeś taki zapis jak w moim przykładzie skrypt znajduje się w katalogu /opt/name/hello.py.
Dyrektywa uruchomienia
Po wgraniu aplikacji musimy ją uruchomić przy starcie kontenera. Aby tego dokonać wystarczy posłużyć się prostym zapisem:
CMD [ "python3", "./hello.py"]
Cały kod
Aby ułatwić, w poniższym przykładzie znajduje się cały kod pliku Dockerfile:
FROM python:latest
WORKDIR /opt/hello
COPY hello.py ./
CMD [ "python", "./hello.py"]
Docker dla programistów – tworzenie obrazu
Jak sam zauważyłeś są to cztery linie kodu, dzięki którym tworzymy obraz z naszym skryptem. Oczywiście przy bardziej skomplikowanych skryptach lub aplikacjach, elementów konfiguracyjnych będzie znacznie więcej. W pliku Dockerfile pominąłem całkowicie etykiety tak aby nie wydłużać niepotrzebnie kodu.
Po stworzeniu pliku pozostało sprawdzić jak działa, dlatego używamy polecenia:
docker image build -t aplikacja-hello:0.1 .
Sending build context to Docker daemon 3.072kB
Step 1/4 : FROM python:latest
latest: Pulling from library/python
23858da423a6: Pull complete
326f452ade5c: Pull complete
a42821cd14fb: Pull complete
8471b75885ef: Pull complete
8ffa7aaef404: Pull complete
15132af73342: Pull complete
aaf3b07565c2: Pull complete
736f7bc16867: Pull complete
94da21e53a5b: Pull complete
Digest: sha256:e9c35537103a2801a30b15a77d4a56b35532c964489b125ec1ff24f3d5b53409
Status: Downloaded newer image for python:latest
---> e285995a3494
Step 2/4 : WORKDIR /opt/hello
---> Running in a90c2693202d
Removing intermediate container a90c2693202d
---> e9f9ad3e3cb3
Step 3/4 : COPY hello.py ./
---> c2105369b1f5
Step 4/4 : CMD [ "python", "./hello.py"]
---> Running in 7e5d20a18173
Removing intermediate container 7e5d20a18173
---> 84649c22e468
Successfully built 84649c22e468
Successfully tagged aplikacja-hello:0.1
W celu potwierdzenia czy nasz obraz został stworzony używamy podstawowego polecenia do wyświetlania listy z obrazami:
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
aplikacja-hello 0.1 84649c22e468 About a minute ago 921MB
Docker dla programistów – kontener z naszego obrazu
Stworzyliśmy obraz, który przy powstaniu kontenera powinien następnie uruchomić napisany przez nas skrypt. Sprawdźmy zatem czy wszystko zadziała zgodnie z tym co sobie zaplanowaliśmy:
docker run --name "hello-world" aplikacja-hello
Unable to find image 'aplikacja-hello:latest' locally
docker: Error response from daemon: pull access denied for aplikacja-hello, repository does not exist or may require 'docker login': denied: requested access to the resource is denied.
See 'docker run --help'.
Otrzymaliśmy błąd, w którym docker informuje nas o tym, że niestety nie udało mu się odnaleźć wskazanego obrazu aplikacja-hello:latest.
Bardzo ważna uwaga, gdy tworzymy obraz i określamy jego wersję nie możemy używać nazwy obrazu w taki sposób jak prezentowałem to w powyższym przykładzie. Nie istnieje obraz w wersji latest dlatego kontener nie mógł być stworzony i uruchomiony.
W takim wypadku aby kontener powstał możemy posłużyć się dwoma sposobami.
Pierwszy z nich polega na określeniu wersji w poleceniu :
docker run --name "hello-world" aplikacja-hello:0.1
Hello World
Drugi, na skorzystaniu z id obrazu:
docker run --name "hello-world-by-id" 84649c22e468
Hello World
Oczywiście musimy zmienić nazwę kontenera ponieważ dwa o takiej samej nazwie nie mogą istnieć.
Korzystając już jakiś czas z dockera przyznam, że miałem styczność z wieloma błędami popełnionymi właśnie w tym miejscu. Zgodzisz się ze mną, że wygodniej jest posługiwać się nazwami kontenerów niż ich ID. Natomiast po wielu problemach z tym powiązanych obecnie używam nazw kontenerów czy też obrazów by wiedzieć do czego służą, natomiast id w poleceniach takich jak na przykład uruchomienie.
Ma to bardzo duże znaczenie pod względem błędów z jakimi się spotkałem gdy na przykład pomyłkowo usunąłem nie ten obraz co chciałem. Spotkasz się albo już spotkałeś z różnego rodzaju wersjami obrazów czy też kontenerów. I jeżeli zechcesz usunąć jakąś wersję obrazu, to potem skorzystasz z polecenia w poniższy sposób:
docker rmi nazwa-obrazu
Zostanie usunięty obraz w wersji latest. Nie zawsze chcesz, aby tak było dlatego możesz usunąć coś nieświadomie, a potem przez dłuższy czas zastanawiać dlaczego nie działa to tak jak powinno. Z tego powodu warto korzystać z ID obrazów.
Docker Hub
Stworzyliśmy nasz obraz, teraz pozostało wgrać go na serwer dockera tak abyśmy mogli korzystać z niego z dowolnego miejsca na świecie.
Rejestracja
Pierwszym krokiem jaki musimy wykonać to zarejestrować się na stronie https://hub.docker.com/. Rejestracja jest banalnie prosta, nie różni się za wiele od innych jakie na pewno wykonywałeś niejednokrotnie. W związku z tym pominę ten etap. Jedyne co dopowiem to aby konto było aktywne musisz potwierdzić to klikając w link który otrzymasz w wiadomości e-mail.
Docker dla programistów – przygotowanie repozytorium
Po utworzeniu konta oraz zalogowaniu na stronie odnajdujemy odnośnik Create a Repository. Przed sobą powinieneś mieć podobny obraz jak poniżej:
W miejscu pola formularza opisanego Name wprowadzamy nazwę pod jaką ma być reprezentowane nasze repozytorium. W związku z tym, że nasz skrypt wypisuje hello world nazwałem je hello-world. Następnie w polu formularza description wpisuję Hello World Python Script Runed in Docker i wciskam button create.
Repozytorium zostało stworzone i z lewej strony otrzymujemy podpowiedź w jaki sposób możemy przesłać nasz obraz. Jednak nim to zrobimy, na początku musimy zalogować się do konta na naszym urządzeniu lokalnym.
Logowanie na lokalnej maszynie
Do tego celu korzystamy z bardzo prostego polecenia:
docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: kgodzisz
Password:
WARNING! Your password will be stored unencrypted in /home/darki/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Jeżeli otrzymałeś podobną informację jak ta w powyższym przykładzie to oznacza, że logowanie zakończyło się powodzeniem.
Docker dla programistów – zaznaczenie oraz przesłanie obrazu do DockerHub
Nim prześlemy obraz do naszego repozytorium, to najpierw musimy przygotować odpowiednio obraz do tego. Robimy to przy pomocy polecenia:
docker tag aplikacja-hello:0.1 kgodzisz/hello-world:aplikacja-hello
Używamy do tego opcji po której następuje nazwa oraz wersja obrazu jaki chcemy przesłać, następnie wyznaczamy miejsce gdzie będziemy go przesyłać. W tym przykładzie korzystamy ze stworzonego wcześniej repozytorium. Określenie wersji znajdujące się po hello-world jest opcjonalne. Natomiast jeżeli nie użyjesz dwukropka i nie wprowadzisz nazwy własnej zostanie ono określone jako latest.
Sprawdźmy zatem jak został przygotowany nasz obraz do przesłania:
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
kgodzisz/hello-world aplikacja-hello 84649c22e468 About an hour ago 921MB
Jeżeli pojawił się na liście tak jak w przykładzie powyżej oznacza to, że możemy go przekazać także do DockerHub. Aby to zrobić musimy wykorzystać taką komendę:
docker image push kgodzisz/hello-world:aplikacja-hello
The push refers to repository [docker.io/kgodzisz/hello-world]
f1d4a0f0adac: Pushed
99e381bf33c1: Pushed
e0faffa259a4: Mounted from library/python
31a8f6f25282: Mounted from library/python
b71cca0c7263: Mounted from library/python
6966fb7c59ef: Mounted from library/python
b78efdac8138: Mounted from library/python
bcc8223cbebf: Mounted from library/python
a24f9e96a54c: Mounted from library/python
54b354c15c5a: Mounted from library/python
b9fcb0f781e4: Mounted from library/python
aplikacja-hello: digest: sha256:9226a8eecf7c4f1283da06e5352ddb1f3008b17ea0e9858a2bd71af14dc3e63e size: 2632
Teraz w celu weryfikacji należy przejść do naszego konta i sprawdzić czy wszystko zostało przesłane.
Natomiast zawsze możesz spróbować pobrać wysłany przez siebie obraz:
docker pull kgodzisz/hello-world:aplikacja-hello
aplikacja-hello: Pulling from kgodzisz/hello-world
Digest: sha256:9226a8eecf7c4f1283da06e5352ddb1f3008b17ea0e9858a2bd71af14dc3e63e
Status: Image is up to date for kgodzisz/hello-world:aplikacja-hello
docker.io/kgodzisz/hello-world:aplikacja-hello
Ze względu, że mam już pobrany wskazany obraz, docker sprawdził tylko czy jest to aktualna wersja.
Podsumowanie
Jedną z najważniejszych funkcji dockera jest także możliwość uruchomienia aplikacji w odizolowanym środowisku. W tym materiale na prostym przykładzie pokazałem w jaki sposób od stworzenia po przesłanie naszego obrazu możemy wykorzystać tą wspaniałą funkcję oferowaną przez dockera. Mam nadzieję, że zaciekawił Cię ten temat, a następnie zaczniesz wykorzystywać dockera w swoich programistycznych doświadczeniach.