Artykuł pochodzi z wydania: Lipiec – Sierpień 2023
W stale ewoluującym środowisku ciężko zapanować nad wszystkimi zmiennymi, od których zależy prawidłowe działanie aplikacji. Dlatego bezpiecznym rozwiązaniem jest zamknięcie ich w niezależnym środowisku za pomocą konteneryzacji.
Podczas instalowania i użytkowania systemów serwerowych często trafia się na sytuacje, w których na jednej maszynie jest kilka aplikacji, wykorzystujących to samo środowisko. Względy bezpieczeństwa wymuszają aktualizowanie ich, ale niektóre wymagają do tego konkretnej wersji danego środowiska (np. Java, Python). W niniejszym artykule przeniesiemy aplikację do wyświetlania komunikatów działającą w środowisku NodeJS do kontenera, by odseparować ją od innych procesów i usprawnić zarządzanie nią.
W skład aplikacji wchodzą NodeJS, ExpressJS, MongoDB oraz witryna internetowa napisana w AngularzeJS. Stronę wyświetlaną użytkownikom utworzymy za pomocą AngularaJS i Boostrapa. Jej pliki (html) oraz powiązane zasoby (pliki JavaScript i AngularaJS, zasoby statyczne) umieścimy na serwerze http Express. Do jego uruchomienia wykorzystamy framework NodeJS. Serwer będzie się łączył z bazą danych MongoDB typu NoSQL. Jest to narzędzie, które pozwoli nam przechowywać proste zbiory danych w formie tzw. kolekcji zamiast znanych z relacyjnych baz tabel. Docelowo do kontenerów będziemy chcieli przenieść bazę danych oraz serwer WWW wraz z plikami strony. Zacznijmy jednak od najprostszego przykładu konteneryzacji.
Aplikacja Docker Desktop i terminal
Na początek stwórzmy aplikację za pomocą narzędzia Docker Desktop w wersji dla Windowsa. Program pozwala kreować zasoby Dockera, zarządzać nimi i przeglądać je w prosty sposób – obrazami, kontenerami, wolumenami. Aplikacja jest dostępna dla systemów Linux, Windows lub MacOS.
Po instalacji programu uruchamiamy go i czekamy na potwierdzenie gotowości działania. Przed przeniesieniem go do kontenerów utworzymy nową sieć, w której będziemy umieszczać kolejne kontenery aplikacji. Takie rozwiązanie pozwoli odseparować inne aplikacje od naszej oraz pomoże w organizacji. Wspólna sieć dla kontenerów umożliwia również komunikowanie się między nimi za pomocą nazwy hosta (hostname). W wierszu poleceń uruchamiamy komendę docker network create app. Po instalacji aplikacji Docker Desktop mamy dostęp do konsolowych poleceń Dockera.
Utworzy ona dla nas sieć o nazwie app. Przy pomocy komendy docker network ls sprawdzimy dostępne sieci. Do każdej z nich zostanie przypisany ID, którym będziemy się później posługiwać. Widoczny będzie również typ (driver) naszej sieci. W naszym przypadku domyślnym typem będzie „bridge”, który wykorzystuje urządzenie o takiej samej nazwie, będące mostkiem sieciowym do zapewnienia komunikacji między kontenerami, które są do niego podłączone.
Pierwszym elementem aplikacji, który uruchomimy przy pomocy Dockera, będzie silnik bazy danych MongoDB. Przechowuje on proste dokumenty zawierające nasze komunikaty (posty). Składają się one z pól: identyfikator (_id), nick, priorytet wiadomości (priority), czas utworzenia (time) i treść (content). Przykładowy dokument wygląda następująco:
{
_id: ObjectId(„647722f10dd199cc5eb7e
5ab”),
nick: 'Marcin Grzelka’,
priority: 'primary’,
content: '<p>2 maja odbędzie się
szkolenie.</p>\n’,
time: 1685529329271
}
Kontener z bazą będzie korzystał z obrazu MongoDB. Zapewnimy mu także miejsce na naszym dysku, na którym przechowa swoje dane. W tym wypadku pozwoli to na zachowanie danych utworzonych podczas pracy aplikacji po usunięciu kontenera i ponownym uruchomieniu go. Takie działania występują często przy migracji programu komputerowego. Gdy w przyszłości będziemy chcieli zaktualizować obraz do nowszej wersji, będziemy mieli dostęp również do starych danych.
Obraz MongoDB znajdziemy na stronie Docker Hub. W jego opisie umieszczono przykłady użycia komend Dockera, zmienne środowiskowe oraz lokalizację katalogów, na których pracuje. Dane bazy przechowywane są w lokalizacji /data/db oraz /data/configdb. W opisie obrazu są informacje o możliwych problemach użycia wolumenów Dockera dla Windowsa. W naszym projekcie wykorzystamy tylko jeden katalog z danymi.
Kolejną ciekawą opcją jest możliwość zaimportowania danych podczas tworzenia kontenera. Możemy dodać do bazy dowolne wpisy. W tym celu należy umieścić pliki skryptów Basha lub JavaScript w katalogu /docker-entrypoint-initdb.d kontenera. Oczywiście przydatne będą w tej sytuacji wolumeny. W katalogu init na hoście umieścimy dwa pliki – z danymi początkowymi msgs.json, który zawiera tablicę obiektów w formie JSON, oraz skrypt init.sh. Podczas inicjalizacji bazy będziemy chcieli, by dane z pliku zostały załadowane do bazy za pomocą mongosh – narzędzia linii poleceń dostępnego w kontenerze. Nasz skrypt zawiera tylko jedną komendę:
#!/bin/bash
mongoimport –db msgs –collection \
msgs –file /docker-entrypoint-initdb.d/\
msgs.json –type json –jsonArray
Mongoimport dodaje bazę msgs, w niej kolekcję msgs. Następnie z pliku msgs.json załaduje do niej znajdujące się tam dokumenty.
Aby uruchomić kontener mongo w terminalu, wykonujemy polecenie:
docker run –name mongo \
-v D:\aplikacja\baza\init:/\
docker-entrypoint-initdb.d/ \
-v D:\ aplikacja \baza\dane:/data/db \
-d \
–network=app \
–restart on-failure:3 \
mongo
Docker run służy do uruchomienia kontenera z obrazu mongo (ostatni argument komendy), któremu nadajemy taką samą nazwę. Za pomocą opcji -v montujemy w nim dwa wspomniane wcześniej katalogi. W przypadku wystąpienia błędu w kontenerze Docker spróbuje uruchomić go ponownie do trzech razy. Chcemy również, by kontener został podłączony do sieci o nazwie app.
Dostępne narzędzia
Po otrzymaniu identyfikatora kontenera jego stan sprawdzimy poleceniem docker ls. Lista kontenerów jest także w aplikacji Docker Desktop. Możemy z niej odczytać podstawowe informacje – nazwę i identyfikator, ale mamy również możliwość wykonania kilku działań. Po wybraniu kontenera zmienimy jego stan i zobaczymy logi działającego w nim procesu. Pomoże nam to uporać się z możliwymi problemami z podłączeniem do bazy. Pozostałe narzędzia to inspekcja kontenera oraz monitorowanie wykorzystywania przez niego zasobów. Statystyki pokażą nam zużycie procesora, pamięci, sieci oraz dysku twardego przez wybrany kontener.
Docker Desktop daje nam też możliwość zmieniania stanu kontenera w razie potrzeby. Możemy restartować go i pauzować. W przypadku, w którym nie będzie on nam już potrzebny, mamy możliwość całkowitego usunięcia go.
[…]
Paweł Ziółkowski
Autor jest absolwentem Uniwersytetu Ekonomicznego we Wrocławiu. Pracuje jako informatyk w Urzędzie Miejskim w Miękini.