.NET Core, Node, Docker – Różne technologie w pipeline Gitlab CI

.NET Core, Node, Docker – Różne technologie w pipeline Gitlab CI6 min read

Dawno, dawno temu, za górami, za lasami, gdzie kakałko trzeba było na palenisku robić odganiając się patykiem od niedźwiedzi (a przynajmniej ja tak pamiętam te czasy) a aplikacje webowe tworzyło się w jednej technologii, życie było o wiele prostsze. Obecnie są to kombajny złożone z wielu technologii. Szczególnie to widać na przykładzie front-endu, który rozrósł się niesamowicie od czasu stworzenia pierwszych wersji Node.js. Jesteśmy wprost bombardowani nowymi frameworkami SPA, które coraz prześcigają się w benchmarkach. Co to oznacza z perspektywy DevOps-a?… Problemy. Dla przykładu – obecnie tworze aplikację SPA na stack-u .NET Core MVC, Vue.js, Docker. Teraz, w jaki sposób, mogę użyć pipline w Gitlab CI aby poprawnie zbudował aplikację i uaktualnił obraz docker-a w repozytorium? Dla samego .NET Core-a jest dość mało obraz-ów, co dopiero przy potrzebie uruchamiania komend docker-a i npm-a?

W dzisiejszym artykule przedstawię wam, jak ja podszedłem do rozwiązania problemu 🙂

Faza I: Internecie, na pomoc!

Taka mała zagadka na początek: co robi programista jak natrafi na problem? Kakałko. Później? Śmieje się z basistów. Czemu? Bo to proste. A co robi odpowiedzialny programista?  A no idzie do wujka Google pytać o pomoc (potem kakałko). Dokładnie tak zrobiłem. Niestety tym razem się zawiodłem. Oczywiście na forum gitlab-a natrafiłem na wątki, w których ludzie opisywali podobne problemy, jednak tam zazwyczaj kończyło się tym, że w sekcji “before_script” ktoś sobie doinstalował czy to docker-a, czy brakujące jdk-a. Osobiście nie chciałem skończyć z plikiem gitlab-ci.yml wielkości wieży Eiffel -a.

Skoro wujek Google nie był mi w stanie pomóc, to może Docker Hub znajdzie mi obraz docker-a, który będzie zawierał wszystkie potrzebne mi elementy. No niestety tutaj też natrafiłem na ścianę. O ile są obrazy, które obsługują stack-a np. node + docker, to już .NET Core + Node + Docker nie znalazłem 🙁

Faza II: Plik wielkości wieży Eiffle

Chcą mieć różne technologie w pipeline Gitlab CI musiałem przetestować rozwiązanie, które było opisane w jednym z wątków na forum Gitlab-a, czyli bazowanie na jakimś podstawowym obrazie docker-a (który załatwia mi jedną funkcjonalność systemu), oraz doinstalowanie w sekcji “before_script” pozostałych zależności. Jako podstawę wybrałem ogólnie dostępny obraz o wdzięcznej nazwie “gitlab:dind”, który wykonał za mnie dość ciężką robotę w postaci udostępnienia mi api docker-a w pipeline Gitlab CI, który to już jest uruchomiony w Dockerze.

TODO: Wstawić jakiś śmieszny gif z podpisem dockercepcja

Tak, tak, dobrze przeczytaliście: otrzymałem  docker-a w dockerze. Stąd też skrót tego obrazu “dind” => “docker in docker”.

Sam obraz bazuje na systemie operacyjnym ubuntu w wersji 14.04 LTS. Jest to bardzo stabilna i nadal często spotykana dystrybucja Ubuntu na serwerach.

Instalacja zależności

Jako, że bazowy obraz jest stworzony na podstawie ubuntu, to do instalacji zależności wykorzystamy apt-get (system do zarządzania pakietami). Może to was zaskoczy, ale pierwszym pakietem, który musimy doinstalować, jest “curl”. Wszystko przez to, że wersja ubuntu udostępniona jako bazy obraz docker-a jest wykastrowana z wielu funkcjonalności aby zmniejszyć jej rozmiar.

Zainstalowanie najnowszej wersji curl-a wymaga uaktualnienia listy pakietów w repozytoriach. Oba polecenia możemy połączyć w jedno za pomocą operatora &&, którego wykorzystanie pozwoli nam na znaczne zmniejszenie ilości warstw w obrazach docker-a.

$ apt-get update && apt-get install -y curl

Następnie musimy zainstalować .NET Core-a. Tutaj nic odkrywczego, po prostu trzeba wejść na stronę https://www.microsoft.com/net/core#linuxubuntu i podążać zgodnie z instrukcją. Jednocześnie trzeba skasować wystąpienia słowa sudo, inaczej podczas budowania obrazu otrzymamy błąd.

$ curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
$ mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg
$ sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-trusty-prod trusty main" > /etc/apt/sources.list.d/dotnetdev.list'
$ apt-get update && apt-get install -y dotnet-sdk-2.0.0

Potem przechodzimy do instalacji Node.js. Ponownie mogę tutaj dodać że nic odkrywczego się nie dzieje, wystarczy wejść w oficjalny tutorial instalacji znajdujący się w tym miejscu i wykonać wszystkie komendy.

$ curl -sL https://deb.nodesource.com/setup_8.x | bash -
$ apt-get update && apt-get install -y nodejs

Po przejściu tych wszystkich kroków plik gitlab-ci.yml powinien wyglądać podobnie do czegoś takiego:

stages:
  - build
build:
  image: 'gitlab:dind'
  stage: build
  before_script:
    - 'apt-get update && apt-get install -y curl'
    - 'curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg'
    - 'mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg'
    - sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-trusty-prod trusty main" > /etc/apt/sources.list.d/dotnetdev.list'
    - 'apt-get update && apt-get install -y dotnet-sdk-2.0.0'
    - 'curl -sL https://deb.nodesource.com/setup_8.x | bash -'
    - 'apt-get update && apt-get install -y nodejs'
    - 'dotnet restore'
  script: 
    - 'dotnet run'

Wstajemy na chwilę od biurka i w tym momencie tańczymy zasłużony taniec zwycięstwa. Nie martwcie się, też nie lubię się ruszać, stąd za taniec uważam przejście do lodówki po kawałek pizzy (ale w rytm muzyki).

Co z kodem? Jak widać zaczyna się tworzyć mały potworek, a mamy tutaj tylko jednego stage-a. Co jeśli byśmy musieli mieć np. 5 środowisk? Produkcja, preprodukcja, staging, QA, development? Zamknęlibyśmy to w jakąś funkcję? Albo po prostu powtarzali kod? No nie…

Faza III Własny obraz docker-a

Kiedy już mamy wszystkie potrzebne komendy do rozbudowania obrazu gitlab:dind toprosty sposób możemy stworzyć własny obraz, który będziemy mogli hostować za pomocą docker hub-a.

Wystarczy stworzyć plik Dockerfile i wypisać wszystkie potrzebne komendy poprzedzając je słowem “RUN”.

FROM gitlab/dind
RUN apt-get update && apt-get install -y curl

RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg

RUN mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg
RUN sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-trusty-prod trusty main" > /etc/apt/sources.list.d/dotnetdev.list'

RUN apt-get update && apt-get install -y dotnet-sdk-2.0.0

RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -

RUN apt-get install -y nodejs

Oczywiście, należy pamiętać, by nie pominąć komendy pobrania obrazu bazowego “FROM”.

Teraz, korzystając z docker CLI, umieszczamy stworzony obraz w repozytorium docker hub-a.

$ docker login -u $DOCKER_USER -p $DOCKER_PASSWORD
$ docker build -t bd90/dotnet-core-node-docker .
$ docker push bd90/dotnet-core-node-docker

Rzecz jasna trzeba założyć konto na docker hubie (pamiętajcie, DOCKER hub, inny hub nie pyknie) 🙂

Dzięki takiemu zabiegowi możemy skrócić nasz plik gitlab-ci.yml do postaci:

stages:
  - build
build:
  image: 'bd90/dotnet-core-node-docker'
  stage: build
  before_script:
    - 'dotnet restore'
  script: 
    - 'dotnet run'

Ba! Teraz nawet, w prosty sposób, możemy użyć tego obrazu do innych stage-y, czy nawet projektów!

Podsumowanie

Teraz już wiecie jak można stworzyć pipeline-a Gitlab CI z różnymi technologiami w środku. Pamiętajcie, aby nie bać się tworzyć własnych obrazów docker-a. Dodatkowo, jeśli chcielibyście wykorzystać mój obraz, to znajdziecie go tutaj. W obecnym stanie ten obraz nie jest jeszcze gotowy do użycia produkcyjnego. Natomiast, jeśli macie propozycję na jego to dajcie znać w komentarzach, mailem lub na twitterze.

Do następnego!

Cześć

By | 2017-10-15T23:30:57+00:00 Październik 15th, 2017|.NET, Docker, Gitlab, Node|1 Comment