CI/CD dla Java Developerów w GitLabie – Kompletny Scenariusz w 6 Krokach

bykowski.pl 4 dni temu

Continuous Integration i Continuous Delivery to nieodłączne elementy nowoczesnego developmentu. Dzięki nim automatyzujesz testowanie, budowanie i wdrażanie swoich aplikacji – zyskując czas, jakość i pewność, iż Twoja aplikacja działa, jak należy.

jeżeli chcesz lepiej zrozumieć samą koncepcję CI/CD, sprawdź mój wcześniejszy artykuł:
Continuous Integration i Continuous Delivery – wprowadzenie

Tutaj natomiast przejdziemy do konkretów – zbudujemy kompletny pipeline CI/CD w GitLabie dla aplikacji Java opartej na Spring Boot. Dowiesz się, jak:

  • zbudować projekt (Maven/Gradle),
  • uruchomić testy jednostkowe i integracyjne,
  • przeprowadzić statyczną analizę kodu,
  • zbudować obraz Dockera,
  • wypchnąć go do GitLab Container Registry,
  • automatycznie wdrożyć aplikację na serwer.

Krok 1: Stwórz prostą aplikację Spring Boot

Nie musimy komplikować – wystarczy prosty endpoint:

@RestController public class HelloController { @GetMapping("/hello") public String getHello() { return "hello"; } }

Dodaj też przykładowy test jednostkowy, na potrzeby scenariusza CI/CD:

@SpringBootTest class HelloControllerTest { @Autowired private MockMvc mockMvc; @Test void helloShouldReturnDefaultMessage() throws Exception { mockMvc.perform(get("/hello")) .andExpect(status().isOk()) .andExpect(content().string("hello")); } }

Krok 2: Konfiguracja Pipelin’u .gitlab-ci.yml

W katalogu głównym projektu utwórz plik .gitlab-ci.yml. Na samym początku tego pliku określ, z jakiego obrazu Dockerowego chcesz korzystać w jobach CI/CD – dla projektów Maven najczęściej wybieramy oficjalny obraz:

image: maven:3.9.4-eclipse-temurin-17

To bardzo ważne – ten obraz zapewnia środowisko z zainstalowanym Mavenem i Javą 17. Dzięki temu wszystkie komendy mvn będą działać poprawnie.

Następnie definiujemy etapy (stages):

stages: - build - test - analyze - package - deploy

Krok 3: Budowanie i testowanie

before_script: - chmod +x mvnw # jeżeli używasz mvnw, który znajduje się w repo (zamiast tego z obrazu) musisz dodać te uprawnienia build: stage: build script: - ./mvnw clean compile test: stage: test script: - ./mvnw test

Krok 4: Analiza kodu

Aby statyczna analiza kodu działała, musisz dodać do pom.xml plugin SpotBugs (lub inny).

<plugin> <groupId>com.github.spotbugs</groupId> <artifactId>spotbugs-maven-plugin</artifactId> <version>4.7.3.0</version> <configuration> <failOnError>false</failOnError> </configuration> </plugin>

Następnie w .gitlab-ci.yml dodajesz:

analyze: stage: analyze script: - ./mvnw com.github.spotbugs:spotbugs-maven-plugin:4.7.3.0:check

Krok 5: Budowanie Dockera i publikacja

W tym etapie chcemy zbudować obraz Dockera z naszą aplikacją Java i wysłać go do GitLab Container Registry, czyli prywatnego rejestru obrazów dostępnego w Twoim projekcie GitLab.

Ale uwaga! Do budowania i pushowania obrazów Dockerowych potrzebujemy specjalnego środowiska – nie wystarczy już zwykły image z Mavenem. Tutaj konieczne jest uruchomienie Docker-in-Docker (DinD) – czyli środowiska, które pozwoli GitLabowi uruchamiać polecenia docker build, docker push itp.

Dlatego w tym etapie:

  • używamy obrazu docker:latest, który zawiera klienta Dockera,
  • uruchamiamy usługę pomocniczą docker:dind, która daje dostęp do samego demona Dockera wewnątrz kontenera.

Oto gotowy przykład konfiguracji joba:

package: stage: package image: docker:latest # Obraz z klientem Docker services: - docker:dind # Demon Docker w kontenerze script: - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA . - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA

Krok 6: Automatyczny deploy

Etap wdrożenia zależy od tego, na jakie środowisko publikujesz aplikację. Inaczej będzie wyglądać deploy do AWS, inaczej na serwer z Kubernetesem, a jeszcze inaczej – na klasyczny VPS z Linuksem i Dockerem.

Na koniec naszego pipeline’u automatycznie wdrażamy aplikację na zdalny serwer VPS. W tym przykładzie używamy klasycznego połączenia SSH z wykorzystaniem sshpass, a sam deploy realizujemy dzięki docker-compose.

deploy: stage: deploy image: alpine:latest before_script: - apk add --no-cache openssh sshpass script: - sshpass -p "$DEPLOY_SERVER_PASSWORD" ssh -o StrictHostKeyChecking=no root@123.123.123.123 " docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.gitlab.com && docker pull registry.gitlab.com/my-group/my-project:$CI_COMMIT_SHORT_SHA && IMAGE_TAG=$CI_COMMIT_SHORT_SHA docker-compose -f /root/myapp/docker-compose.yml up -d"

Uwaga: W powyższym przykładzie dane wrażliwe (klucz prywatny SSH i adres IP serwera) zostały wpisane jawnie tylko w celach demonstracyjnych. W prawdziwym projekcie zawsze przechowuj takie informacje jako zmienne środowiskowe w ustawieniach GitLaba (CI/CD → Variables), aby uniknąć przypadkowego wycieku danych i zadbać o bezpieczeństwo.

Podsumowanie

I gotowe! Masz w pełni funkcjonalny pipeline CI/CD dla aplikacji Java w GitLabie. Budujesz, testujesz, analizujesz, pakujesz w kontener i… automatycznie wdrażasz!
Finalny plik .gitlab-ci.yml

image: maven:3.9.4-eclipse-temurin-17 stages: - build - test - analyze - package - deploy before_script: - chmod +x mvnw build: stage: build script: - ./mvnw clean compile test: stage: test script: - ./mvnw test analyze: stage: analyze script: - ./mvnw com.github.spotbugs:spotbugs-maven-plugin:4.7.3.0:check package: stage: package image: docker:latest services: - docker:dind script: - docker login -u "gitlab-ci-token" -p "$CI_JOB_TOKEN" $CI_REGISTRY - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA . - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA deploy: stage: deploy image: alpine:latest only: - main before_script: - apk add --no-cache openssh sshpass script: - sshpass -p "$DEPLOY_SERVER_PASSWORD" ssh -o StrictHostKeyChecking=no root@123.123.123.123 " docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.gitlab.com && docker pull registry.gitlab.com/my-group/my-project:$CI_COMMIT_SHORT_SHA && IMAGE_TAG=$CI_COMMIT_SHORT_SHA docker-compose -f /root/myapp/docker-compose.yml up -d "

Moje szkolenie

Chcesz zobaczyć live coding, praktyczne przykłady i jeszcze więcej detali CI/CD?
Dołącz do mojego szkolenia CI/CD dla Java Developerów, które poprowadzę już w maju – zarezerwuj miejsce i wynieś swój dev workflow na wyższy poziom!

Idź do oryginalnego materiału