W niniejszym artykule zaprezentujemy ostatnią część naszej serii o Dockerz’e, w której opowiemy Wam o różnicach między ARG oraz ENV, docker-compose, orkiestracji oraz docker API. Jeśli dopiero zaczynasz swoją przygodę z oprogramowaniem Docker, to zachęcamy do zapoznania się z poprzednimi częściami ( #1, #2 oraz #3), aby Twoja wiedza była budowana na solidnych fundamentach.

 

ARG vs ENV

W ostatnich artykułach wspominaliśmy o zmiennych środowiskowych, które dostarczone do kontenera poprzez komendę bądź plik .env mogą wpływać na działanie wdrażanej aplikacji. Nie są to jednak jedyne sposoby. Należy zwrócić uwagę na to, że na aplikację można wpływać zarówno poprzez zmienne środowiskowe ENV jak i dostarczane argumenty ARG. Różnica polega na momencie w którym takie zmienne są dostarczane - przy ENV jest to podczas uruchamiania kontenera, natomiast ARG przy budowaniu obrazu. Dobrze obrazuje to poniższa ilustracja:

Rysunek 1. Zakres działania ARG i ENV (vsupalov.com).

 

Z poziomu CMD polecenie z użyciem ARG może wyglądać w ten sposób:

docker build --build-arg MY_ARG=custom_value -t myimage .

 

Natomiast z użyciem ENV tak:

docker run --env MY_VAR=hello alpine

lub tak:

docker run --env-file env_file alpine

 

Obie te koncepcje można mieszać w przypadku stosowania budowania obrazu z poziomu pliku Dockerfile.

Rysunek 2. Przykładowy Dockerfile wykorzystujący ARG oraz ENV.

 

Na powyższej ilustracji widać, że ARG posiada domyślną wartość 80, którą można nadpisać używając przełącznika --build-args podczas budowania, bądź podczas uruchomienia kontenera z użyciem --env / --env-file.

 

Docker Compose

W Dockerze istnieje bardzo istotny mechanizm docker-compose, który odnosi się zarówno do polecenia docker-compose/docker compose jak i nazwy pliku docker-compose.yml. Ze względu na to jak konstruowane są aplikacje (np. mikrousługi) w dzisiejszych czasach oraz wymagania narzucane przez biznes odnośnie powtarzalności i niezawodności konfiguracji i oprogramowania powstało narzędzie docker-compose. Pozwala ono na przygotowanie całej konfiguracji środowiska skonteneryzowanego (aplikacji, bazy danych, reverse proxy), która następnie może być powtarzalnie wdrażana z użyciem jednego polecenia:

docker-compose up

Rysunek 3. Wizualizacja działania docker-compose. Źródło microsoft.com.

 

We wcześniejszych wersjach Dockera do zarządzania aplikacjami wielokontenerowymi służyło polecenie docker-compose.  Jednak począwszy od wersji Docker 1.27, polecenie docker compose zostało wprowadzone jako zamiennik polecenia docker-compose.  Ta zmiana została wprowadzona w celu dostosowania do konwencji nazewnictwa innych poleceń i zapewnienia bardziej spójnego środowiska użytkownika.

 

Rysunek 4. Przykładowa zawartość pliku docker-compose.yml.

 

Podstawowe dyrektywy występujące w pliku docker-compose.yml:

  • version — określa wersję używanej składni pliku Compose.
  • services - definiuje usługi do uruchomienia oraz ich konfiguracje.
  • image — określa obraz z repozytorium, który ma być używany dla usługi.
  • container_name — przypisuje kontenerowi konkretną nazwę.
  • ports - odwzorowuje porty z kontenera na maszynę hosta.
  • volumes — montuje woluminy z komputera hosta do kontenera.
  • networks - wskazuje sieć do połączenia kontenerów
  • environment - ustawia zmienne środowiskowe dla usługi.
  • depends_on - określa kolejność, w jakiej usługi mają być uruchamiane.
  • restart - ustawia zasady ponownego uruchamiania dla kontenera.
  • build - określa konfigurację kompilacji dla usługi.
  • context — ustawia miejsce z jakiego mają być wywoływane polecenia dotyczące budowania
  • dockerfile - nazwa pliku dockerfile

 

Sieć w kontenerach

W zależności od potrzeb stosuje się różne rodzaje komunikacji. Część nie wymaga konfiguracji, a część wręcz przeciwnie wymaga skonfigurowania dockerowej sieci. Możemy wyróżnić następujące komunikaty w Docker:

  • z kontenera do Internetu
  • z kontenera do hosta
  • między kontenerami

Zacznijmy od możliwości komunikacji kontenera na zewnątrz. Domyślnie każdy kontener ma dostęp do Internetu o ile system hosta ma takowy dostęp. Możemy więc odpytywać dowolne publicznie dostępne w Internecie API bez żadnej dodatkowej konfiguracji z wnętrza kontenera.

Drugą opcją jest komunikacja z wnętrza kontenera do hosta. Jeśli chcemy się np. odwołać do lokalnie działającej na systemie hosta bazy danych musimy w adresie użyć w adresie “host.docker.internal” zamiast localhost, którego użylibyśmy hostując aplikację lokalnie na hoście. Warto wspomnieć, że baza powinna być także skonteneryzowana. Taki układ z hostem i kontenerem nie jest dobrym rozwiązaniem produkcyjnym.

Rysunek 5. Przykład zastosowanie host.docker.internal.

 

Trzecią opcją najczęściej spotykaną jest komunikacja między dwoma kontenerami poprzez utworzoną w Dockerze sieć. Taki układ jest chyba najczęściej spotykany. Jest to także najlepsza praktyka, aby każda usługa stała w osobnym kontenerze np. baza danych i aplikacja, czy aplikacja oparta o mikroserwisy. Jeśli chcemy skomunikować dwa kontenery, to dodajemy je do tej samej sieci (docker run --network). W kodzie odnosimy się po nazwie drugiego kontenera (odnoszenie się po ip nie jest zalecane).

Rysunek 6. Wskazanie jako serwera MongoDB kontenera o nazwie my_mongo_container.

 

Za pomocą polecenia docker network create można stworzyć nową sieć, którą następnie używamy w poleceniu docker run lub pliku compose. Warto wiedzieć, że sieć można także utworzyć z poziomu samego pliku compose.

Rysunek 7. Możliwości polecenia docker network.

 

Narzędzia orkiestracji

Orkiestracja w środowisku Docker odnosi się do procesu automatyzacji, skalowaniem i zarządzaniem kontenerami Docker.  Umożliwia ona łatwe wdrażanie aplikacji w kontenerach, uruchamianie ich w środowisku rozproszonym. Najpopularniejsze narzędzia w zakresie orkiestracji to Docker Swarm oraz Kubernetes i chociaż oba służą do podobnego celu, mają różne architektury i zestawy funkcji.

Docker Swarm to natywne narzędzie do klastrowania i orkiestracji które zostało zaprojektowane tak, aby było łatwe w użyciu i jest dobrym wyborem dla mniejszych wdrożeń lub organizacji, które już korzystają z Dockera. Z drugiej strony Kubernetes to system orkiestracji kontenerów zapewniający potężny interfejs API do zarządzania aplikacjami w kontenerach i zawiera takie funkcje, jak automatyczne skalowanie, równoważenie obciążenia.  Kubernetes został zaprojektowany tak, aby był wysoce skalowalny i odporny na awarie. Jest to lepszy wybór dla większych wdrożeń lub organizacji, które wymagają wysokiego stopnia automatyzacji i kontroli nad aplikacjami kontenerowymi.

 

Docker API

Warto także podkreślić, że CLI nie jest jedynym sposobem na komunikację z Docker’em, ponieważ Docker posiada REST API, pozwalające na komunikację wywołaniami z poziomu języka programowania. Pozwala to na jeszcze większą optymalizację zarządzania usługami oraz automatyzację działań administratora.

Rysunek 8. Biblioteka dockerpy  - dokumentacja github.

 

Podsumowanie

To już ostatnia część naszych przygód z Docker’em. Poprzednie części znajdziecie tutaj: #1, #2 oraz #3. Mamy nadzieję, że dzięki naszej serii udało Wam się poszerzyć swoją wiedzę. 

 

Źródła:

https://vsupalov.com/docker-arg-vs-env/

https://azuremarketplace.microsoft.com/en-us/marketplace/apps/cloud-infrastructure-services.docker-compose-2016?tab=overview

https://github.com/docker/docker-py