Po małej przerwie, w dzisiejszym artykule postaram się opowiedzieć jak uruchomić aplikację ASP.NET Core w Dockerze na serwerze VPS. Docker jest narzędziem umożliwiającym uruchamianie procesów w odizolowanym środowisku nazywanym kontenerem. Kontener dostarcza procesowi wszystkich zależności czyniąc z niego autonomiczną jednostkę wykonującą określoną funkcję. Taki przenośny, wirtualny kontener można uruchomić na systemach Windows, Linux, macOS. W tym artykule opiszę jak zainstalować Dockera,  zbudować obraz i uruchomić go w działającym kontenerze a także uruchomić go na serwerze VPS.

Docker i jego składniki

Docker pozwala na podział naszego oprogramowania na niezależne komponenty nazywane kontenerami. Kontener to główne pojęcie w terminologii Dockera. Możemy powiedzieć, że kontener to komponent naszego oprogramowania, który pełni pojedynczą funkcję w naszej architekturze. Dzięki swoim małym wymiarom, kontenery są idealne do tworzenia mikrousług w architekturze SOA (Service Oriented Architecture), pozwala to na pewną elastyczność i łatwość skalowania ale też może wiązać się z większymi kosztami utrzymania. Kontener działa niezależnie od oprogramowania i urządzenia (platform i hardware agnostic). Do podstawowych komponentów Dockera zalicza się demon, komunikujący się z nim klient oraz repozytorium obrazów.

Docker Architecture Diagram
https://docs.docker.com/engine/docker-overview/#docker-engine

Docker Demon

Demon Dockera ( dockerd  ) nasłuchuje requesty Docker API i zarządza obiektami Dockera takimi jak obrazy, kontenery, sieci i wolumenami. Demon może także komunikować się z innymi demonami w celu zarządzania serwisami Dockera.

Docker Client

Klient Dockera ( docker ) to podstawowe narzędzie do komunikacji z Dockerem przez użytkowników. Gdy używamy poleceń takich jak docker run klient wysyła te polecenia do dockerd który je wykonuje. To polecenie używa Docker API. Klient Dockera może komunikować się z więcej niż jednym demonem.

Docker Registry

Rejestr Dockera przechowuje jego obrazy. Docker Hub i Docker Cloud są publicznymi rejestrami z których może korzystać kazdy i domyślnie Docker jest skonfigurowany aby używać tych rejestrów. Możesz także uruchomić swój prywatny rejestr. Jeżeli używasz Docker Datacaenter (DDC), to zawiera on Docker Truster Degistry (DTR).
Gdy uzywasz poleceń docker pull lub docker run to potrzebne obrazy zostają ściągnięte ze skonfigurowanego przez ciebie rejestru. Gdy użyjemy docker push obraz zostanie wysłany do rejestru.
Docker store ponadto pozwala na zakup lub sprzedaż obrazów Dockera a także udostępnianie ich za darmo.

Docker Engine Components Flow
https://docs.docker.com/engine/docker-overview/#docker-engine

 

Podczas używania dokera tworzymy wiele różnych obiektów, takich jak obrazy, kontenery, sieci, wolumeny, pluginy i innych. Poniżej postaram się je trochę opisać.

Images

Obraz jest szablonem tylko do odczytu który zawiera instrukcje do utworzenia kontenera Dockera. Często jest tak, że obraz bazuje na innym obrazie z drobnymi zmianami. Np. możesz zbudować obraz który bazuje na obrazie ubuntu, ale zainstalować dodatkowo serwer apache i Twoją aplikację, jak również ustawić konfigurację, aby mogła się poprawnie uruchomić. Możemy Tworzyć swoje obrazy jak również używać tylko tych stworzonych przez innych użytkowników, które są opublikowane w rejestrze. Aby zbudować swój własny obraz, musimy stworzyć Dockerfile z prostą składnią która definiuje wymagane kroki w celu utworzenia obrazu i uruchomienia go. Każda instrukcja w Dockerfile tworzy warstwę z obrazem. Kiedy zmienimy Dockerfile i przebudujemy obraz, tylko te warstwy które zostały zmienione są przebudowywane. To sprawia, że obrazy są tak lekkie, małe i szybkie w porównaniu do innych technologii wirtualizacji.

Containers

Kontener jest uruchamianą instancją obrazu. Możemy go stworzyć, uruchomić, zatrzymać, przenieść lub usunąć używając Docker API lub CLI. Możemy podłączyć kontener do jednej lub wielu sieci, podpiąć do niego magazyn danych,a nawet stworzyć obraz bazujący na jego aktualnym stanie. Domyślnie, kontener jest stosunkowo dobrze izolowany od innych kontenerów na maszynie hostującej. Możemy kontrolować, jak bardzo kontener ma być odizolowoany od sieci, magazynu danych, podsystemów bazowych i innych kontenerów z maszyny hostującej. Kontener jest definiowany przez jego obraz, jak również wszelkie opcje konfiguracyjne które do niego dostarczamy kiedy go tworzymy lub uruchamiamy. Kiedy kontener jest zatrzymywany, żadne zmiany w jego stanie które nie zostały zapisane w magazynie danych – znikają.

Services

Usługi pozwalają nam na skalowanie kontenerów w wielu demonach Dockera, które razem pracują jak „mrowisko” z wieloma managerami i workerami. Każdy element takiego klastra jest demonem Dockera i każdy z nich używa do komunikacji Docker API. Usługa pozwala nam na definiowanie pożądanych stanów, takich jak liczbę replikacji usług która musi być dostępna w każdym czasie. Domyślnie usłgua jest równomiernie obciążona (load-balanced) dla wszystkich pracujących węzłów. Dla użytkownika usługa wydaje się być pojedynczą aplikacją. Docker Engine wspiera „tryb mrowiska” (swarm mode) w wersji od 1.12.

Jako ciekawostkę, mogę napisać że Docker został napisany w języku Go i kożysta z kilku funkcji jądra systemu Linux aby dostarczyć swoje funkcjonalności.

Instalacja Dockera

Instalacja Dockera i rozpoczęcie zabawy z nim jest bardzo proste. Pierwszym krokiem jest jego instalacja. Pod następującymi linkami są instrukcje dla Windowsa, macOS i Linuxa. W tym artykule będę używał systemu macOS.

Wchodzimy na stronę dockera i klikamy Download Docker from Docker Store:
screenshot-at-kwi-29-10-33-49Po przekierowaniu na nową stronę klikamy Get Docker i zapisujemy obraz na dysku. Instalacja jest bardzo prosta i polega na przeciągnięciu ikonki Dockera do folderu aplikacji:
screenshot-at-kwi-29-10-35-37

Po instalacji przechodzimy do folderu aplikacji i uruchamiamy dockera. Po uruchomienu musimy przejść przez kilka kroków kreatora, gdzie musimy podać hasło admina. Po wszystkim powinniśmy dostać ikonkę dockera w górnej belce:
screenshot-at-kwi-29-10-37-50Aby sprawdzić czy wszystko jest ok, odpalamy terminal i wpisujemy:

> docker --version

w odpowiedzi powinniśmy dostać:

Docker version 17.03.1-ce, build c6d412e

Jeżeli wszystko wygląda jak powyżej – mamy Dockera :).

Projekt ASP.NET Core

w celach testowych musimy otworzyć projekt testowy ASP.NET. W tym celu stworzymy nowy katalog i utworzymy nowy domyślny projekt webowy. Możemy tutaj wykorzystać dotnet cli lub yeomanW tym przykładzie użyję dotnet cli gdyż yeoman’a opiszę w osobnym artykule w przyszłości. W tym celu wykonujemy poniższe akcje:

mkdir DockerTest
cd DockerTest
dotnet new mvc

Następnie spróbujmy uruchomić projekt lokalnie:

dotnet restore
dotnet run

następnie otwieramy przeglądarkę i wpisujemy adres http://localhost:5000 i powinniśmy zobaczyć działającą stronę:
screenshot-at-kwi-29-10-52-11

Dockerfile dla ASP.NET Core

Docker potrzebuje Dockerfile który zawiera „przepis” tworzenia obrazu bazującego na projekcie. Tworzymi nowy plik o nazwie Dockerfile w folderze projektu:

touch Dockerfile

Jeżeli korzystamy z systemu windows, upewnijmy się, że ten plik nie ma rozszerzenia .txt – powinien nie mieć żadnego rozszerzenia. Otwieramy plik w edytorze tekstowym i wpisujemy:

FROM microsoft/dotnet:latest
COPY . /app
WORKDIR /app

RUN ["dotnet", "restore"]
RUN ["dotnet", "build"]

EXPOSE 5000/tcp
ENV ASPNETCORE_URLS http://*:5000

ENTRYPOINT ["dotnet", "run"]

Instrukcja FROM informuje Dockera, że zamierzamy używać istniejący obraz o nazwie microsoft/dotnet: latest. Ten obraz aktualnie zawiera wszystkie zależności konieczne do uruchomienia .NET Core na Linuxie, więc nie musimy się martwić o ich instalację.

COPY WORKDIR kopiuje aktualną zawartość katalogu do nowego o nazwie app i ustawia ten katalog jako domyślny dla kolejnych instrukcji.

RUN uruchamia dotnet restore dotnet build aby przywrócić pakiety i zbudować projekt.

EXPOSE informuje Dockera aby ten wystawił na świat zewnętrzny port 5000 (domyślny dla ASP.NET Core).

ENV ustawia zmienną środowiskową ASPNETCORE_URLS w kontenerze, która zapewnia prawidłowe bindowanie adresu i portu do naszej aplikacji.

ENTRYPOINT określa polecenie, które będzie wykonane po uruchomieniu kontenera. W naszym przypadku jest to dotnet run.

Tworzenie Docker image

Po utworzeniu Dockerfile jesteśmy gotowi na zbudowanie obrazu:

docker build -t mariusz:mvcdemoapp .

Kropka w poleceniu powyżej jest istotna i mówi o tym, że chcemy skorzystać z pliku dockerfile w obecnym katalogu. Parametr  -t dodaje tag do naszego obrazu, w tym przypaku jest to mariusz:mvcdemoapp.

Po zbudowaniu naszego obrazi spróbujmy go uruchomić lokalnie:

docker run -d -p 8080:5000 -t mariusz:mvcdemoapp

Parametr -d pozwala uruchomić aplikację w detached mode to znaczy że będzie uruchomiona w tle i spokojnie będziemy mogli zamknąć terminal. Flaga -p ustawia mapowanie portu 8080 do 5000 ustawionego wewnątrz kontenera.

Czas najwyższy sprawdzić czy wszystko działa jak należy, przejdźmy więc pod adres: http://localhost:8080 i powinniśmy zobaczyć naszą stronkę 🙂

Polecenie docker ps  wyświetli nam listę aktualnie uruchomionych kontenerów:

CONTAINER ID        IMAGE                COMMAND             CREATED             STATUS              PORTS                    NAMES
8a73594c3de1        mariusz:mvcdemoapp   "dotnet run"        14 seconds ago      Up 12 seconds       0.0.0.0:8080->5000/tcp   upbeat_brown

A polecenie docker stop [containerId] zatrzyma uruchomiony kontener.

Na stronie Microsoftu znajdziemy instrukcję jak dodać automatycznie kontener do już istniejącego projektu za pomocą yeoman’a.

Wrzucamy na produkcję – repozytorium dockera

W ostatniej części artykułu spróbujemy wrzucić nasz obraz do prywatnego repozytorium dockera a następnie uruchomić go na naszym serwerze VPS.

W pierwszej kolejności tworzymy konto na hubie dockera:
screenshot-at-kwi-29-14-03-53

Rejestrujemy się i potwierdzamy nasz adres e-mail. Po zalogowaniu musimy utworzyć nasze repozytorium, w tym celu klikamy create repository. Wypełniamy formularz i wybieramy, czy nasze repozytorium ma być publiczne czy prywatne i klikamy Create. Ważne aby repozytorium lokalne miało taką samą nazwę jak zdalne. Np jeżeli zdalne repozytorium to username/myrepo to tworząc obraz dockera który chcemy do niego wrzucić musi mieć dokładnie taki tag: username/myrepo:nazwa

Wracamy do naszego terminala i logujemy się poleceniem

docker login -u username -p haslo

Po pomyślnym zalogowaniu wysyłamy nasz obraz do naszego rejestru:

docker push username/mariusz:mvcdemoapp

Wysyłanie obrazu może chwilę potrwać. Gdy obraz już się wyśle, łączymy się z naszym serwerem VPS, na którym już mamy, bądź też instalujemy Dockera, logujemy się w ten sam sposób jak wyżej i pobieramy obraz za pomocą komendy:

docker pull username/mariusz:mvcdemoapp

Uruchomienie obrazu wygląda identycznie jak byśmy to robili lokalnie.

 

Mam nadzieję, że teraz deploy aplikacji przy pomocy Dockera będzie dla wszystkich czytelników jasny i zrozumiały 🙂

1
Dodaj komentarz

avatar
1 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
1 Comment authors
kandascan Recent comment authors
  Subscribe  
najnowszy najstarszy oceniany
Powiadom o
kandascan
Gość

Świetny wpis! Nigdy wcześniej nie miałem okazji konfigurować i wdrażać prywatnych aplikacji na zewnątrz, po przeczytaniu Twojego artykułu wiem teraz jak to zrobić.