Jenkins jest narzędziem continuous integration i continuous delivery (CI/CD) pozwalającym na efektywne testowanie, budowanie i wdrażanie aplikacji. Umożliwia czynności takie jak integrację z kodem źródłowym repozytorium, automatyczne wykonywanie buildów w reakcji na zdarzenia webhooka, testy jednostkowe czy integracyjne i wdrożenie w zależności od powodzenia kompilacji. Nasza instancja Jenkinsa musi znajdować się za serwerem reverse proxy w celu integracji z GitHub poprzez webhook gdzie podajemy adres URL domeny naszego serwera Jenkins. Za pomocą Webhooka subskrybujemy zdarzenia na repozytorium po których są uruchamiane buildy Jenkinsa.
W poprzednim wpisie wytłumaczyłem jak uruchomić i skonfigurować reverse proxy, jednak powstaje pytanie ? Co kiedy nie dysponujemy własnym adresem domeny, a potrzebujemy aby nasze serwisy były dostępne w internecie. W takich przypadkach możemy skorzystać z Ngrok. Globalnej sieci serwerów reverse proxy pozwalającą na wystawienie lokalnie znajdujących się aplikacji do internetu. Za obsługę ruchu przychodzącego odpowiada agent, który jest pośrednikiem pomiędzy naszym hostem a serwerami Ngroka. Ządania klientów trafiają na losowo wygenerowany adres URL lub statyczną domenę, a następnie są przekierowywane do agenta protokołem HTTPS. Następnie agent przekazuje żądania do jednego z lokalnych serwisów. Istnieje możliwość określenia tzw. traffic policy poprzez moduły takie jak autentykacja, restrykcje dla określonych adresów IP, czy ograniczenie przepustowość ruchu. Ngrok może być wykorzystywany na przykład do integracji narzędzi CI/CD z systemami kontroli wersji, przedstawiania klientom różnych wersji aplikacji na domenach testowych czy w środowiskach developerskich.
W pracy DevOpsa Docker jest obowiązującym standardem więc warto znać to narzędzie. Każdy wpis na tym blogu gdzie hostujemy jakiekolwiek serwisy będzie oparty właśnie o Dockera
. Na początek pobierz repozytorium z konfiguracją dla Jenkinsa i Ngroka.
$ git clone https://github.com/it-stuff-pl/guides.gitWięcej na temat przeznaczenia poszczególnych sekcji w pliku yaml dla Docker Compose znajdziesz w tym wpisie. Tutaj chciałbym skupić się przede wszystkim na opcji healthcheck, która sprawdza poprawność działania serwera sieciowego Jenkinsa poprzez wysłanie żądania GET za pomocą CURL-a na otwarty endpoint /login. Ngrok uruchomi się tylko wtedy gdy healthcheck zakończy się pomyślnie i status kontenera Jenkinsa zmieni się na healthy. Następnie zwróć uwagę na komendy startowe dla kontenera Ngrok. Gdzie w pierwszej kolejności podajemy nazwę hosta i port kontenera Jenkins, a następnie za pomocą opcji --url adres statycznej domeny Ngrok. Dla darmowego konta jest jedna statyczna domena do wykorzystania i warto z niej skorzystać. Domyślnie domeny Ngroka są generowane dynamicznie więc z każdym uruchomieniem kontenera domena zmieni swój adres co utrudni integracje z GitHubem. Adres statycznej domeny znajduje się na koncie Ngrok w zakładce Universal Gateway > Domains.
services:
dind:
image: docker:dind
container_name: jenkins-docker
volumes:
- jenkins-docker-certs:/certs/client
- jenkins-data:/var/jenkins_home
environment:
- DOCKER_TLS_CERTDIR=/certs
ports:
- "2376:2376"
privileged: true
networks:
- cicd
jenkins:
image: myjenkins-blueocean:latest
build:
context: ./
dockerfile: jenkins.Dockerfile
container_name: jenkins-blueocean
volumes:
- jenkins-data:/var/jenkins_home
- jenkins-docker-certs:/certs/client:ro
environment:
- DOCKER_HOST=tcp://dind:2376
- DOCKER_CERT_PATH=/certs/client
- DOCKER_TLS_VERIFY=1
ports:
- "8080:8080"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/login"]
interval: 1m30s
timeout: 30s
retries: 5
start_period: 30s
networks:
- cicd
ngrok:
image: ngrok/ngrok:latest
container_name: ngrok
ports:
- "4040:4040"
environment:
- NGROK_AUTHTOKEN=${NGROK_AUTHTOKEN}
- DOMAIN_NAME=${DOMAIN_NAME}
command:
- "http"
- "http://jenkins:8080"
- "--url"
- "${DOMAIN_NAME}"
depends_on:
jenkins:
condition: service_healthy
networks:
- cicd
volumes:
jenkins-docker-certs:
jenkins-data:
networks:
cicd:
driver: bridgeDo autentykacji z chmurą Ngrok i utworzenia tunelu pomiędzy lokalnym serwisem a globalnym reverse proxy jest wymagany token, który znajduje się na utworzonym koncie Ngrok. Należy utworzyć plik .env w folderze projektu wraz ze zmienną NGROK_AUTHTOKEN, która jest wskazana w Docker Compose. Drugą zmienną jest DOMAIN_NAME, która jest adresem statycznej domeny Ngrok.
NGROK_AUTHTOKEN=<token_value>
DOMAIN_NAME=<ngrok_static_domain>Zwróć uwagę na serwis Jenkins w pliku docker-compose.yaml, gdzie wskazany jest plik Dockerfile z którego budowany będzie kontener po uruchomieniu z Docker Compose. Instrukcje obrazu są skopiowane z oficjalnej dokumentacji, natomiast do pliku została dodana instrukcja EXPOSE, która otwiera port kontenera 8080 na komunikację w wewnętrzej sieci Dockera dzięki czemu Ngrok będzie mógł hostować nasz serwis. Uruchom kontenery poleceniem.
$ docker compose up -dUruchomione kontenery, ich status, nazwę czy otwarte porty można sprawdzić komendą docker ps, natomiast adres domeny przypisany dla lokalnego serwisu można sprawdzić w interfejsie webowym agenta Ngrok na porcie 4040. Znajdując się na stronie internetowej naszego serwisu należy przeprowadzić początkową konfiguracje Jenkinsa wpisując losowo wygenerowane hasło administratora znajdujące się w lokalizacji /var/jenkins_home/secrets/initialAdminPassword. Aby dostać się do powłoki i systemu plików kontenera Jenkins w celu skopiowania hasła należy wpisać:
$ docker exec -it jenkins-blueocean /bin/bashNastępnie wydrukować hasło administratora poleceniem:
$ cat /var/jenkins_home/secrets/initialAdminPassword
Po zainstalowaniu pluginów i wypełnieniu formularza podstawowymi danymi takimi jak nazwa użytkownika, hasło i adres email możesz zalogować się do dashboarda Jenkinsa. Dalej utworzymy Personal access token, który posłuży do autentykacji Jenkinsa z serwerami GitHub, dzięki czemu możliwy będzie dostęp do repozytoriów.
- W celu utworzenia tokenu kliknij w ikonę profilu w prawym górnym rogu, a następnie wejdź w Settings > Developer settings > Personal access tokens > Tokens (classic).
- Nazwij token dowolną nazwą i nadaj zakres uprawnień dla tokenu:
- admin:repo_hook – Tworzenie webhooków dla zdarzeń w repozytoriach.
- repo – Dostęp do prywatnych repozytoriów. Jest to grupa uprawnień która obejmuję:
- repo:status – manipulowanie commit statuses
- repo:repo_deployment – manipulowanie statusami deploymentu
- repo:public_repo – dostęp do publicznych repozytoriów
- read:org and user:email – Zalecane uprawnienia dla wtyczki GitHub Authentication
- Po utworzeniu tokenu skopiuj i zapisz jego zawartość, będzie to potrzebne przy tworzeniu dostępów (credentials) w Jenkinsie.
- Następnie wejdź w dashboard Jenkinsa i dodaj dostępy które będą korzystać z wcześniej utworzonego tokenu w GitHub. Kliknij w ikonę ustawień, a następnie Credentials > Stores scoped to Jenkins > Global > Global credentials (unrestricted) > Add credentials
- Utwórz dostępy uzupełniając formularz:
- Kind – Secret text
- Secret – zawartość wcześniej utworzonego Personal access token.
- ID – dowolna nazwa dla tego dostępu
- Description – dowolny opis tego dostępu
- Po utworzeniu dostępów dodaj serwer GitHub zarządzany przez tą instancję Jenkinsa. Manage Jenkins > System > GitHub > GitHub servers > Add GitHub Server
- Uzupełnij formularz następująco:
- API URL – https://api.github.com
- Credentials – Wybierz wcześniej utworzone dostępy w punkcie 5.
- Na końcu przetestuj połączenie pomiędzy API GitHuba a Jenkinsem. Kliknij w Test connection, powinieneś otrzymać komunikat “Credentials verified for user …, rate limit: 4999”.
Istnieją różne typy projektów Jenkinsa służących do pracy z repozytoriami, w tym wpisie skupimy się na Multibranch Pipeline, który pozwala na definiowanie różnych pipeline’ów w zależności od danego brancha. Definicje dla pipeline’ów znajdują się w pliku Jenkinsfile. Kiedy ten plik znajduje się w danym branchu Jenkins wykryje go i umożliwi wykonanie danego zadania. Aby utworzyć projekt kliknij New Item na stronie głównej naszego Dashboarda. Wpisz nazwę projektu a następnie wybierz Multibranch Pipeline:
- Display name – Wpisz nazwę dla swojego projektu
- Branch Sources – Wybierz GitHub
- Credentials – Kliknij Add, a następnie Jenkins (Jenkins Credential Provider)
- Kind – Jako metodę uwierzytelniania wybierz Username and password
- Scope – Global
- Password – Wartość wcześniej utworzonego tokenu (Personal Access Token)
- ID – Wpisz rozpoznawalną nazwę, ten dostęp może się przydać również przy pracy z innymi projektami Jenkinsa.
- Repository HTTPS URL – Adres URL repozytorium dla którego ma zostać utworzony projekt.
- Po uzupełnieniu o wyżej podane opcje kliknij Validate aby sprawdzić czy masz dostęp do repozytorium oraz czy wprowadziłeś poprawny adres URL. Powinienieś zobaczyć komunikat “Credentials ok. Connected to https://github.com/rjasinski96/kickstat-app.”
W konfiguracji Multibranch Pipeline jest jeszcze pewna opcja o której warto wspomnieć przed zapisaniem konfiguracji, a mianowicie Suppress automatic SCM triggering. Domyślnie Jenkins zaczyna wykonywać pipeline od razu po wykryciu repozytoriów, i nie jest to wskazane zwłaszcza kiedy chcemy aby buildy były wykonywane tylko przy pomocy Webhooka po wykryciu zdarzeń na repozytorium. Robi się to też po to aby uniknąć tzw. Build storm. Wyobraź sobie dużą ilość branchy po których wykryciu uruchamiane są buildy wszystkie w jednym momencie
. Aby zmienić sposób triggerowania dla przyszłych zadań wejdź w:
- Branch Sources > GitHub > Property Strategy > Add Property > Supress automatic SCM triggering.
- Wybierz dla których branchy chcesz zmienić sposób triggerowania buildów.
- Branch names to build automatically – Wartość może być w postaci wyrażenia Regex. Gdy chcemy zmienić strategię dla każdego brancha w repozytorium wpisz .*
- Suppression strategy > For matching branches suppress builds triggered by indexing (continue to honor webhooks)
- Na końcu zapisz obecną konfigurację projektu klikając Save na dole strony.
Po zapisaniu konfiguracji sprawdź logi które powstały po zapisaniu konfiguracji i przeskanowaniu repozytoriów w zakładce Scan Repository Log.

Po połączeniu z serwerem API GitHuba z użyciem utworzonych dostępów Jenkins powinen wykryć wszystkie branche w naszym repozytorium. Jak widzisz nie znaleziono plików Jenkinsfile ale tworzeniem pipeline’ów zajmiemy się w następnym wpisie. Uruchamianie buildów Jenkinsa po zdarzeniach z repozytorium jest możliwe dzięki webhooks. Możemy ustawić wykonanie builda np. po utworzeniu Pull requesta na danym branchu bądź wypchnięciu commitów na zdalne repozytorium i wiele więcej. Aby utworzyć Webhook przejdź do serwisu GitHub na stroną swojego repozytorium a następnie:
- Settings > Webhooks:
- Payload URL – Adres URL twojego serwera Jenkins. W naszym przypadku jest to: https://nazwa_domeny_ngrok/github-webhook/
- Wybierz jakie zdarzenia będą wysyłane na Webhook.
- Następnie zaznacz pole Active i kliknij Add webhook.
Brawo
w ten sposób uruchomiliśmy serwer Jenkinsa w Dockerze za Ngrok reverse proxy ze statycznym adresem domeny. Przeprowadziliśmy autentykacje Jenkinsa z GitHub API przy pomocy Personal access token i utworzyliśmy projekt typu Multibranch Pipeline z kodem źródłowym repozytorium. W następnym wpisie wdrożę prostą aplikację React gdzie napiszemy Pipeline i skorzystamy z Webhooka w reakcji na zdarzenia z konkretnych branchy tak żeby pokazać ci jak może to wyglądać w praktyce
.

