Powrót do bloga

Jak wdrożyć aplikację Node.js (Express.js) za pomocą Dockera na Ubuntu 20.04

Jak wdrożyć aplikację Node.js (Express.js) za pomocą Dockera na Ubuntu 20.04

Wprowadzenie

Docker to platforma kontenerowa, która jest lekkim, zwirtualizowanym, przenośnym, zdefiniowanym programowo, standaryzowanym środowiskiem. Umożliwia uruchamianie oprogramowania w izolacji od innego oprogramowania działającego na fizycznej maszynie hosta. Docker jest kluczowym elementem aspektu ciągłego rozwoju i integracji (Continuous Development and Integration) w inżynierii oprogramowania. Oferuje on lekką alternatywę dla maszyn wirtualnych i pozwala programistom cieszyć się rozproszonymi architekturami aplikacji. Aby uzyskać szczegółowy przegląd ekosystemu Docker, zapoznaj się z tym artykułem.

Proces budowania aplikacji za pomocą Dockera rozpoczyna się od utworzenia przez programistę obrazu dla swojej aplikacji. Następnie obraz ten zostanie wdrożony wewnątrz kontenera. Obraz zawiera definiujące komponenty aplikacji, takie jak kod aplikacji, biblioteki, pliki konfiguracyjne, zmienne środowiskowe oraz środowisko uruchomieniowe. Obraz standaryzuje środowisko wewnątrz kontenera, nadając konteneryzacji cechy przenośności. Node.js to otwartoźródłowe, wieloplatformowe środowisko uruchomieniowe JavaScript dla backendu, które może wykonywać kod JavaScript poza przeglądarką internetową. Jest ono zbudowane w oparciu o należący do Chrome V8 JavaScript Engine. Express.js to minimalistyczny backendowy framework JavaScript, który działa na bazie Node.js.

W tym samouczku utworzymy obraz dla strony internetowej działającej na frameworku Express. Użyjemy Bootstrap, który jest biblioteką frontendową, aby poprawić wygląd frontendu. Po utworzeniu obrazu zbudujemy kontener i prześlemy go do Docker Hub. Docker Hub pozwala programistom na hostowanie skonteneryzowanych aplikacji w celu łatwego wdrożenia w dowolnym środowisku Docker. Gdy Twój kontener znajdzie się na Docker Hub, pobierzemy go i zbudujemy kolejny obraz, który będzie faktycznie obsługiwał naszą stronę internetową.

Wymagania wstępne

To będzie praktyczny samouczek. Powinieneś przygotować środowisko, które umożliwi Ci śledzenie kroków.

Krok 1: Konfiguracja zależności aplikacji

Przed utworzeniem obrazu musisz stworzyć kod źródłowy aplikacji. Kod źródłowy aplikacji obejmuje kod, zawartość statyczną oraz zależności, które zostaną skopiowane do kontenera. Zacznij od utworzenia katalogu dla swojego projektu w katalogu domowym użytkownika niebędącego rootem. Nazwiemy go node_express, ale możesz użyć dowolnej innej nazwy katalogu:

Następnie przejdź do tego katalogu:

To będzie katalog główny Twojej aplikacji. Aplikacja node.js oczekuje pliku package.json w folderze głównym. Npm używa tego pliku do określenia, jakich zależności potrzebuje Twoja aplikacja. Wprowadź następujące polecenie, aby utworzyć ten plik:

Następnie dodaj do pliku poniższy fragment kodu. Możesz dowolnie zaktualizować nazwę, autora, opis oraz plik punktu wejścia:

Jak widać, ten plik określa nazwę projektu, wersję, autora oraz licencję, na której kod aplikacji będzie udostępniany. Zaleca się używanie krótkiej i opisowej nazwy dla projektu, aby uniknąć duplikatów w rejestrze npm. Określiliśmy licencję ISC dla projektu, która pozwala na bezpłatne kopiowanie, modyfikowanie lub dystrybucję kodu aplikacji.

Co najważniejsze, należy zwrócić uwagę na następujące dyrektywy w pliku:

  • main”: ta dyrektywa określa punkt wejścia aplikacji, który ustawiliśmy jako index.js. Ten plik utworzymy za chwilę.
  • dependencies”: ta dyrektywa określa zależności aplikacji, które zostaną pobrane z rejestru npm po uruchomieniu polecenia npm, w naszym przypadku chcemy Express w wersji 4.17.1 i nowszej.

Możesz teraz zapisać plik, naciskając Ctrl + O. Następnie zamknij plik, naciskając Ctrl + X. Następnie zainstalujemy zależności, uruchamiając następujące polecenie:

Polecenie to instaluje zależności aplikacji określone w pliku package.json wewnątrz katalogów node_modules. Zostały one automatycznie utworzone przy pierwszym uruchomieniu polecenia. Po zainstalowaniu zależności aplikacji możesz teraz zacząć dodawać kod aplikacji.

Krok 2: Dodawanie plików kodu aplikacji

Stworzymy prostą stronę z przepisami, dzięki uprzejmości allrecipes. Głównym punktem wejścia dla aplikacji jest plik index.js. Dodamy katalog views, który będzie zawierał różne strony i statyczne zasoby projektu. Strona będzie miała stronę główną (landing page), która będzie zawierać informacje wprowadzające i linki do niektórych przepisów.

Kod naszej strony głównej zostanie umieszczony w pliku home.html. Najpierw utwórz plik index.js, wprowadzając następujące polecenie:

Dodaj następujący kod, który importuje i tworzy aplikację Express. Określa on również obiekt Router, katalog bazowy oraz port, na którym ta aplikacja będzie obsługiwana:

require to funkcja JavaScript, która ładuje moduł. W tym przypadku ładujemy moduł express. Następnie użyjemy zaimportowanego modułu do utworzenia obiektów express i router. Obiekt router wykonuje funkcje routingu aplikacji, odpowiadając na wywołania metod HTTP, które będziemy dodawać do tego obiektu w miarę postępów w samouczku.

Ustawiliśmy również path oraz port. Stała path definiuje katalog bazowy dla kodu. W naszym przypadku jest to podkatalog views wewnątrz głównego katalogu projektu. port określa port, na którym aplikacja express powinna nasłuchiwać, w naszym przykładzie ustawiliśmy go na 8090.

Gdy mamy już stałe, możemy określić niektóre trasy dla aplikacji za pomocą obiektu router. Dodaj następujący kod do pliku index.js, aby określić trasy:

Możesz dodać middleware do tras za pomocą funkcji router.use. W tym przypadku dodajemy funkcję, która rejestruje żądania routera przed przekazaniem ich do tras aplikacji. Żądanie GET do głównego adresu aplikacji zwróci plik home.html stronę. Następnie dodaliśmy strony dla trzech przepisów, które również będą pobierane za pomocą żądania GET do konkretnej strony przepisu.

Na koniec dodaj następujący kod, aby zamontować router oprogramowanie pośredniczące (middleware) oraz statyczne zasoby aplikacji. Dodatkowo wskaż aplikacji express, aby nasłukiwała na porcie 8090:

Twój kompletny plik index.js powinien wyglądać następująco:

Możesz teraz zapisać i zamknąć plik. Następnym krokiem jest dodanie statycznych stron internetowych do katalogu views. Zacznij od wprowadzenia następującego polecenia, aby utworzyć ten katalog:

Wprowadź następujące polecenie, aby otworzyć plik strony docelowej home.html:

Dodaj do pliku następujący kod. Kod ten importuje Bootstrap i oferuje odwiedzającym stronę informacje o tym, czym jest ta witryna:

Oprócz importowania Bootstrapa, strona dodaje również podstawowe menu nawigacyjne ułatwiające poruszanie się po stronach i powrót do strony głównej. Dodaliśmy również linię importującą nasz niestandardowy plik CSS:

Użyjemy tego pliku do dodania niestandardowego stylu do aplikacji w późniejszym czasie. Teraz utwórzmy trzy strony dla przepisów. Zaczynamy od utworzenia strony lasagna. Otwórz plik w edytorze nano za pomocą następującego polecenia:

W otwartym pliku dodaj następujący kod. Ten plik zaimportuje Bootstrapa, plik custom.css, określi menu nawigacyjne i przedstawi informacje o przepisie na lasagnę:

Postępujmy zgodnie z tym samym procesem, aby utworzyć plik dla strony z przepisem na guacamole. Otwórz plik za pomocą nano, uruchamiając następujące polecenie:

Następnie dodaj ten kod do pliku:

Na koniec utwórzmy plik banana_bread.html, wpisując polecenie:

Następnie dodaj do pliku następujący kod HTML:

Teraz utworzyliśmy już wszystkie strony. Jeśli pamiętasz, mamy dodać plik css/custom.css file. Enter the following command to create the directory:

Następnie utwórz i otwórz plik w edytorze nano za pomocą polecenia:

Możesz dodać więcej kodu CSS, aby ostylować swoją stronę według własnego uznania. Dla zwięzłości dodajmy do pliku następujący fragment kodu:

Po zakończeniu zapisz i zamknij plik.

Możesz teraz uruchomić aplikację, ponieważ mamy już zainstalowany kod źródłowy aplikacji i zależności projektu.

Skonfigurowaliśmy aplikację tak, aby nasłuchiwała na porcie 8090, uruchom następujące polecenie, aby nakazać zaporze sieciowej zezwolenie na ruch przez ten port. Jeśli określiłeś inny port, zastąp numer portu w poleceniu:

Teraz możesz uruchomić aplikację. Najpierw jednak upewnij się, że znajdujesz się w katalogu głównym projektu, uruchamiając następujące polecenie:

Uruchom aplikację za pomocą polecenia node index.js. Jeśli określiłeś inny punkt wejścia, zastąp go swoim punktem wejścia:

Jeśli przejdziesz w przeglądarce pod adres http://your_public_server_ip:8090, zobaczysz stronę główną Przepisów, tak jak została zdefiniowana:

Recipes

 

W nawigacji widoczne są linki do różnych przepisów. Kliknijmy na niektóre z nich. Poniżej znajduje się Lasagne - strona przepisu:

Node.js app install on Ubuntu 1

A tutaj mamy Guacamole - strona przepisu:

Guacamole

Do tego momentu utworzyłeś aplikację i przetestowałeś, że działa zgodnie z oczekiwaniami. Możesz wyjść z serwera, naciskając Ctrl + C, i przejść do tworzenia pliku Dockerfile. Pliki Dockerfile pomagają w skalowalności, umożliwiając odtworzenie instancji aplikacji w razie potrzeby.

Krok 3: Tworzenie pliku Dockerfile

Docker odczytuje instrukcje określone w pliku Dockerfile podczas budowania obrazów. Określa on środowisko uruchomieniowe aplikacji. Dzięki temu pomaga programistom uniknąć rozbieżności w zależnościach lub zmieniających się wersjach środowiska uruchomieniowego. Wprowadź następujące polecenie, aby utworzyć plik Dockerfile:

Obraz Dockera jest tworzony przy użyciu kilku warstw obrazów, które budują się jedna na drugiej. Zaczynasz od dodania obrazu bazowego, który stanowi punkt wyjścia dla aplikacji.

Ponieważ aplikacja ma działać w środowisku node.js, zaczniemy od dodania obrazu node:10-alpine dla node.js. Obecnie, gdy piszemy ten samouczek, jest to zalecana wersja LTS Node.js. Wybraliśmy ten konkretny obraz, ponieważ pochodzi on z projektu Alpine Linux. Dzięki temu pomoże to utrzymać rozmiar naszego obrazu na minimalnym poziomie. Istnieje kilka wariantów obrazów na stronie obrazów Node w Docker Hub, które możesz wybrać w zależności od swoich potrzeb.

Dodaj następujący kod, aby ustawić obraz bazowy aplikacji za pomocą dyrektywy FROM:

Ten obraz zawiera Node.js i npm. Każdy Dockerfile musi zaczynać się od dyrektywy FROM. Obraz Docker node domyślnie zawiera użytkownika node niebędącego rootem, którego można użyć do uruchomienia kontenera aplikacji zamiast roota. Zabezpieczenia Dockera zalecają nieuruchamianie kontenerów jako root i ograniczenie uprawnień tylko do tych, które są wymagane do działania jego zasobów.

W takim przypadku będziemy używać katalogu domowego użytkownika node jako katalogu roboczego dla aplikacji, a także samego użytkownika wewnątrz kontenera. Możesz zapoznać się z tym przewodnikiem po najlepszych praktykach dotyczącym obrazu Docker Node, aby uzyskać więcej informacji.

Utworzymy podkatalog node_modules wewnątrz /home/node wraz z katalogiem aplikacji, aby pomóc usprawnić uprawnienia do kodu aplikacji. Utworzenie tych katalogów zapewnia, że mają one odpowiednie uprawnienia, gdy uruchomimy polecenie npm install lokalnie wewnątrz kontenerów. Po utworzeniu katalogów należy ustawić ich własność na użytkownika node. Zrobimy to wewnątrz pliku Dockerfile, dodając następującą linię:

Następnie ustawisz katalog roboczy, dodając następującą linię:

Zawsze warto ustawić WORKDIR, aby Docker nie musiał tworzyć go domyślnie.

Dodaj następującą linię, aby skopiować pliki package.json i package-lock.json:

Zaleca się dodanie instrukcji COPY przed uruchomieniem npm install lub skopiowaniem kodu źródłowego aplikacji. Pozwala to na skorzystanie z mechanizmu buforowania Dockera. Podczas procesu budowania Docker sprawdza, czy ma zapisaną w pamięci podręcznej warstwę dla każdej instrukcji. Oznacza to, że jeśli nie zmieniłeś pliku package.json, Docker użyje istniejącej warstwy obrazu i uniknie ponownej instalacji modułów node, co przyspieszy proces budowania.

Przed uruchomieniem npm install, dodaj następującą linię, aby przełączyć użytkownika na node, aby upewnić się, że wszystkie pliki aplikacji i katalog node_modules należą do użytkownika node niebędącego rootem:

Nasz kontener jest teraz gotowy do uruchomienia polecenia npm install. Dodaj następującą linię do pliku Dockerfile:

Po zainstalowaniu node_modules, dodaj następującą linię, która nakaże Dockerowi skopiowanie kodu aplikacji do katalogu aplikacji w kontenerze z odpowiednimi uprawnieniami i własnością, tj. dla użytkownika node niebędącego rootem:

Ostatnim krokiem jest udostępnienie portu 8090 w kontenerze, tak jak zdefiniowaliśmy to w naszym pliku wejściowym index.js:

EXPOSE określa, które porty w kontenerze będą otwarte w czasie działania. CMD uruchamia polecenie startu aplikacji, w tym przypadku node index.js.

W pliku Dockerfile powinna znajdować się tylko jedna instrukcja CMD, ponieważ tylko ostatnia odnosi skutek. Zapoznaj się z dokumentacją referencyjną Dockerfile, aby zapoznać się z listą rzeczy, które można zrobić za pomocą Dockerfile.

Twój kompletny plik Dockerfile powinien wyglądać następująco:

Możesz teraz zapisać i zamknąć plik.

Następnym krokiem jest dodanie pliku .dockerignore. Podobnie jak plik .gitignore, plik .dockerignore określa, które pliki i katalogi w katalogu projektu nie powinny być kopiowane do kontenera.

Otwórz plik w edytorze nano:

Dodaj następujące linie wewnątrz pliku:

Jeśli pracujesz z repozytorium git, powinieneś również dodać katalog .git oraz plik .gitignore. Zapisz i zamknij plik.

Jeśli wszystko poszło dobrze, czas zbudować obraz aplikacji za pomocą polecenia docker build. Możesz dodać flagę –t do polecenia docker build, aby oznaczyć obraz łatwą do zapamiętania nazwą, w przeciwieństwie do losowego ciągu znaków, który Docker ustawia domyślnie. Będziemy również przesyłać obraz do Docker Hub, więc najlepiej jest dołączyć swoją nazwę użytkownika Docker Hub w tagu.

Użyjemy nodejs-express-image jako nazwy tagu. Możesz wybrać dowolną nazwę tagu. Oto polecenie do zbudowania obrazu:

Pamiętaj, aby zastąpić your_dockerhub_username swoją rzeczywistą nazwą użytkownika Docker Hub. Kropka (.) na końcu określa, że kontekstem budowania jest bieżący katalog.

Proces budowania trwa minutę lub dwie. Po jego zakończeniu wprowadź polecenie, aby sprawdzić swoje obrazy:

Powinieneś zobaczyć coś takiego:

sudo docker images

Pamiętaj, że zastąpiliśmy your_dockerhub_username rzeczywistą nazwą użytkownika.

Po potwierdzeniu, że obraz został zbudowany, możesz teraz utworzyć kontener z tym obrazem za pomocą docker run. Uwzględnione zostaną następujące flagi:

  • -p: publikuje port w kontenerze i mapuje go na port w systemie hosta. Do celów demonstracyjnych użyjemy portu 80 w systemie hosta. Jeśli jednak na tym porcie działa inny proces, możesz go zmodyfikować w razie potrzeby. Dowiedz się więcej o bindowaniu portów z dokumentacji Dockera.
  • -d: dla trybu odłączonego (detached). Pozwala kontenerowi na dalsze działanie w tle.
  • --name: możesz użyć tej flagi, aby ustawić łatwą do zapamiętania nazwę, zamiast pozwalać Dockerowi na przypisanie losowego ciągu znaków.

Polecenie utworzenia kontenera jest następujące. Zastąp odpowiednio swoją nazwę użytkownika Docker Hub:

Poczekaj, aż kontener zostanie zbudowany i uruchomiony. Możesz użyć tego polecenia, aby sprawdzić wszystkie uruchomione kontenery:

Powinieneś zobaczyć dane wyjściowe podobne do następujących:

Node.js app install on Ubuntu 3

Jak widać na wyjściu, kontener jest teraz uruchomiony. Możesz go wyświetlić w przeglądarce, odwiedzając publiczny adres IP swojego serwera bez podawania portu. Strona główna zostanie załadowana:

awesome recipe

 

Pomyślnie wdrożyłeś statyczną stronę internetową Node Express za pomocą Dockera. Zobaczmy, jak możemy przesłać ten obraz do Docker Hub w celu przyszłego użycia i skalowania.

Krok 4: Praca z repozytoriami obrazów Docker

Możesz przesyłać swoje obrazy do rejestrów obrazów, takich jak Docker Hub, i zapisywać je do przyszłego użytku, udostępniać innym programistom lub umożliwiać skalowanie kontenerów. Możemy przesłać utworzony obraz do Docker Hub i użyć go do ponownego utworzenia kontenera.

Użyj następującego polecenia, aby zalogować się na swoje konto Docker Hub. Zastąp je swoją rzeczywistą nazwą użytkownika Docker Hub:

Wprowadź hasło po wyświetleniu monitu. Po zalogowaniu plik ~/.docker/config.json zostanie utworzony w katalogu domowym użytkownika, zawierający Twoje dane uwierzytelniające Docker Hub.

Po skonfigurowaniu wprowadź następujące polecenie, aby przesłać obraz do Docker Hub, określając tag ustawiony wcześniej podczas budowania obrazu:

To polecenie przesyła obraz platformy Docker na Twoje konto Docker Hub. Jeśli odwiedzisz swoje konto, zobaczysz niedawno przesłany obraz:

Docker Hub

Możemy przetestować użyteczność repozytorium obrazów, niszcząc bieżący kontener aplikacji i odbudowując go przy użyciu obrazu z repozytorium.

Wyświetl listę swoich bieżących kontenerów, wprowadzając polecenie:

Powinieneś zobaczyć dane wyjściowe podobne do tych:

Docker Hub

Zanotuj CONTAINER ID wyświetlony w danych wyjściowych, skopiuj go i użyj do zatrzymania kontenera za pomocą polecenia, zastępując identyfikator swoim:

Wprowadź następujące polecenie, aby wyświetlić listę wszystkich obrazów platformy Docker dostępnych w Twoim systemie:

W danych wyjściowych pojawi się nazwa Twojego obrazu, obraz node.js oraz inne obrazy z procesu budowania.

Wprowadź następujące polecenie, aby usunąć obrazy, w tym nieużywane lub wiszące obrazy:

Wpisz y, aby potwierdzić. Spowoduje to usunięcie zatrzymanych kontenerów i obrazów. Jeśli wyświetlisz ich listę, zobaczysz pustą listę w danych wyjściowych:

output

Teraz usunąłeś zarówno kontener, w którym działa aplikacja, jak i sam obraz. Dowiedz się więcej o usuwaniu kontenerów, obrazów i wolumenów platformy Docker, postępując zgodnie z naszym samouczkiem.

Możemy teraz odtworzyć cały proces, najpierw pobierając obraz z Docker Hub za pomocą następującego polecenia. Zastąp odpowiednio swoją nazwę użytkownika Docker Hub:

Ponownie wyświetl listę swoich obrazów platformy Docker za pomocą polecenia:

Powinieneś zobaczyć obraz w danych wyjściowych:

sudo docker

Możesz teraz odbudować swój kontener, używając polecenia z Kroku 3. Oczywiście zastąp swoją nazwę użytkownika Docker Hub tam, gdzie to konieczne:

Wyświetl listę swoich kontenerów, aby potwierdzić, że został odbudowany:

Powinieneś zobaczyć podobne dane wyjściowe:

W przeglądarce przejdź do publicznego adresu IP swojego serwera, a powinieneś zobaczyć działającą aplikację.

Podsumowanie

Jeśli przeszedłeś przez ten samouczek do tego miejsca, masz teraz statyczną stronę internetową stworzoną za pomocą Express i Bootstrap oraz wdrożoną za pomocą platformy Docker. Użyłeś plików statycznej strony internetowej do zbudowania obrazu platformy Docker i użyłeś tego obrazu do utworzenia kontenera. Następnie przesłałeś obraz do rejestru obrazów platformy Docker, Docker Hub, udostępniając go do przyszłego użytku lub skalowania. Aby przetestować użycie rejestru obrazów, usunąłeś obrazy i kontenery, pobrałeś obrazy z rejestru i odbudowałeś kontenery.

Ten samouczek wyjaśnił, jak wdrożyć aplikację Node.js. Jeśli chcesz dowiedzieć się, jak korzystać z innego stosu programistycznego, mamy samouczek dotyczący Wdrażania aplikacji Laravel za pomocą Docker Compose na serwerze Nginx.

Więcej zasobów dotyczących korzystania z platformy Docker można znaleźć w następujących samouczkach:

Miłego korzystania z komputera!

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.