Gitlab에 프로젝트를 생성하고 소스를 울려 gitlab-ci 구성을 하도록 하겠습니다.
Gitlab-CI 설명이 잘 되어있는 영상입니다. 참고하시면 좋겠습니다.
Spring initializr를 통해 test ptoject를 생성 합니다.
Maven 프로젝트로 선택해 주시고 나머지는 원하는 대로 구성해 주시면 됩니다.
압축을 풀면 아래와 비슷한 구조가 나타납니다.
├─ src
│ ├─ main/...
│ └─ test/...
├─ .gitignore
└─ pom.xml
./pom.xml 에 profile과 repository 설정을 추가합니다.
├─ src
│ ├─ main/...
│ └─ test/...
├─ .gitignore
└─ pom.xml # this!
Maven Deploy 단계에서 두 개의 maven repository에 병렬로 배포하기 위해 profile을 분리했습니다. 하나는 gitlab의 pacakge regisitry, 나머지 하나는 nexus3 maven repository에 배포됩니다.
<!-- ./pom.xml -->
<project>
<profiles>
<profile>
<id>private-gitlab-package-registry-deploy</id> <!--Gitlab package registry 에 배포-->
<distributionManagement>
<repository>
<id>ci-gitlab-maven</id>
<url>${CI_API_V4_URL}/projects/${env.CI_PROJECT_ID}/packages/maven/</url>
</repository>
<snapshotRepository>
<id>ci-gitlab-maven</id>
<url>${CI_API_V4_URL}/projects/${env.CI_PROJECT_ID}/packages/maven/</url>
</snapshotRepository>
</distributionManagement>
</profile>
<profile>
<id>private-nexus-repository-deploy</id> <!-- Nexus3 maven repository에 배포-->
<distributionManagement>
<repository>
<id>private-nexus3-maven-releases</id>
<url>http://nexus.domain.com/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>private-nexus3-maven-snapshots</id>
<url>http://nexus.domain.com/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
</profile>
</profiles>
<repositories>
<!-- private nexus maven repository -->
<repository>
<id>private-nexus3-maven</id>
<url>http://nexus.domain.com/repository/maven-public/</url>
</repository>
</repositories>
</project>
spring boot application을 docker container로 만들(containerize) dockerfile을 생성합니다.
├─ src
│ ├─ main/...
│ └─ test/...
├─ .gitignore
├─ .gitlab-ci-mvn-settings.xml
├─ dockerfile # this!
└─ pom.xml
# ./dockerifle
FROM openjdk:11-jre-slim
VOLUME /tmp
EXPOSE 8080
ARG JAR_FILE=target/*.jar
ADD ${JAR_FILE} ./app.jar
ENTRYPOINT [ "java", "-jar", "./app.jar" ]
Runner의 Maven 옵션을 정의한 파일(./.gitlab-ci-mvn-settings.xml)을 추가합니다.
├─ src
│ ├─ main/...
│ └─ test/...
├─ .gitignore
├─ .gitlab-ci-mvn-settings.xml # this!
├─ dockerfile
└─ pom.xml
<!-- ./.gitlab-ci-mvn-settings.xml -->
<settings>
<servers>
<!-- private nexus maven repository -->
<server>
<id>private-nexus3-maven</id>
<username>gitlab-ci</username>
<password>change_me</password>
</server>
<!-- private nexus maven releases repository -->
<server>
<id>private-nexus3-maven-releases</id>
<username>gitlab-ci</username>
<password>change_me</password>
</server>
<!-- private nexus maven snapshots repository -->
<server>
<id>private-nexus3-maven-snapshots</id>
<username>gitlab-ci</username>
<password>change_me</password>
</server>
<!-- private gitlab package registry -->
<server>
<id>private-gitlab-maven</id>
<configuration>
<httpHeaders>
<property>
<name>Job-Token</name>
<value>${env.CI_JOB_TOKEN}</value>
</property>
</httpHeaders>
</configuration>
</server>
<!-- gitlab package registry (CI) -->
<server>
<id>ci-gitlab-maven</id>
<configuration>
<httpHeaders>
<property>
<name>Job-Token</name>
<value>${env.CI_JOB_TOKEN}</value>
</property>
</httpHeaders>
</configuration>
</server>
</servers>
<mirrors>
<!-- private nexus repository -->
<mirror>
<id>private-nexus</id>
<mirrorOf>central</mirrorOf>
<name>private-nexus3-maven</name>
<url>http://nexus.domain.com/repository/maven-public/</url>
<blocked>false</blocked>
</mirror>
<!-- private nexus maven releases repository -->
<mirror>
<id>private-nexus3-maven-releases</id>
<mirrorOf>releases</mirrorOf>
<name>private-nexus</name>
<url>http://nexus.domain.com/repository/maven-releases/</url>
<blocked>false</blocked>
</mirror>
<!-- private nexus maven snapshots repository -->
<mirror>
<id>private-nexus3-maven-snapshots</id>
<mirrorOf>snapshots</mirrorOf>
<name>private-nexus</name>
<url>http://nexus.domain.com/repository/maven-snapshots/</url>
<blocked>false</blocked>
</mirror>
</mirrors>
</settings>
Gitlab-ci가 동작할 수 있도록 .gitlab-ci.yml을 추가합니다. 작성 문법은 아래 링크를 확인해 주시면 좋겠습니다.
├─ src
│ ├─ main/...
│ └─ test/...
├─ .gitignore
├─ .gitlab-ci-mvn-settings.xml
├─ .gitlab-ci.yml # this!
├─ dockerfile
└─ pom.xml
# ./.gitlab-ci.yml
variables:
MAVEN_OPTS: "-Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=INFO -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true"
MAVEN_CLI_OPTS: "-s .gitlab-ci-mvn-settings.xml --batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true"
cache:
paths:
- .m2/repository
- target/
stages:
- maven-build
- maven-test
- maven-deploy
- docker-deploy
maven-build: # maven build
image: maven:3.8.6-openjdk-11-slim
stage: maven-build
script:
- mvn $MAVEN_CLI_OPTS clean package -DskipTests
artifacts:
paths:
- target/*.jar
expire_in: 10 min
maven-test: # maven test
image: maven:3.8.6-openjdk-11-slim
stage: maven-test
script:
- mvn $MAVEN_CLI_OPTS test
maven-deploy-private-gitlab-package-registry: # deploy to gitlab package registry
image: maven:3.8.6-openjdk-11-slim
stage: maven-deploy
script:
- mvn $MAVEN_CLI_OPTS clean deploy -P private-gitlab-package-registry-deploy
maven-deploy-private-nexus-repository: # deploy to nexus3 maven repository
image: maven:3.8.6-openjdk-11-slim
stage: maven-deploy
script:
- mvn $MAVEN_CLI_OPTS clean deploy -P private-nexus-repository-deploy
docker-deploy-private-gitlab-container-registry: # deploy to gitlab container registry
image: docker:20.10.18
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
stage: docker-deploy
services:
- name: docker:20.10.18-dind
alias: docker
command: ["--tls=false", "--insecure-registry=registry.gitlab.domain.com"]
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- docker pull $CI_REGISTRY_IMAGE:latest || true;
- docker build --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --tag $CI_REGISTRY_IMAGE:latest .;
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA;
- docker push $CI_REGISTRY_IMAGE:latest;
docker-deploy-private-nexus-container-registry: # deploy to nexus3 container registry
image: docker:20.10.18
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
stage: docker-deploy
services:
- name: docker:20.10.18-dind
alias: docker
command: ["--tls=false", "--insecure-registry=registry.nexus.domain.com"]
before_script:
- docker login -u "$CI_NEXUS_REGISTRY_USER" -p "$CI_NEXUS_REGISTRY_PASSWORD" $CI_NEXUS_REGISTRY
script:
- docker pull $CI_NEXUS_REGISTRY/$CI_PROJECT_NAME:latest || true;
- docker build --tag $CI_NEXUS_REGISTRY/$CI_PROJECT_NAME:$CI_COMMIT_SHA --tag $CI_NEXUS_REGISTRY/$CI_PROJECT_NAME:latest .;
- docker push $CI_NEXUS_REGISTRY/$CI_PROJECT_NAME:$CI_COMMIT_SHA;
- docker push $CI_NEXUS_REGISTRY/$CI_PROJECT_NAME:latest;
Gitlab 그룹 & 프로젝트는 원하는 대로 구성해 주시면 됩니다.
Groups > new group > Create group
Groups > 생성한 Group > New project > Create blank project
Enable Static Application Security Testing (SAST) 를 체크하시면 gitlab-ci가 자동으로 생성되는데 그 안에 SAST를 위한 구성이 포함됩니다. 내용은 아래 링크를 확인해 주세요.
빈 프로젝트가 구성되면 아래와 같이 표시 됩니다.
.gitlab-ci.yml에서 사용한 CI 변수(Nexus3 접속 정보)를 정의합니다. Project > Settings > CI/CD Sttings > Variables 에서 프로젝트의 변수를 등록하는 방법과 Admin > Settings > CI/CD Sttings > Variables 에서 gitlab 전역으로 등록하는 방법 두 가지가 있습니다.
주의하실 점은 protected 변수로 정의하면 ci가 동작할 branch도 protected로 설정해야 해당 변수를 사용하실 수 있습니다.
앞서 구성한 테스트 프로젝트 파일을 repository에 추가하고 push 합니다.
프로젝트의 CI/CD메뉴를 확인 해 보면 앞에서 구성한 .gitlab-ci.yml을 가지고 gitlab-ci가 동작하게 됩니다.
CI/CD > Pipelines > pipeline_no
프로젝트의 pipeline 의 job의 console log를 확인 해 보면 minio에서 cache를 download하고 upload한 기록을 확인 할 수 있습니다.
CI/CD > Jobs > #job_no > console log
Checking cache for default-protected...
Downloading cache.zip from http://minio.domain.com/private-[MASKED]-cache/project/24/default-protected
Successfully extracted cache
(생략)
Creating cache default-protected...
.m2/repository: found 2707 matching files and directories
target/: found 32 matching files and directories
Uploading cache.zip to http://minio.domain.com/private-[MASKED]-cache/project/24/default-protected
Created cache
CI의 deploy단계가 성공하면 gitlab의 package, container registry와 nexus3의 maven repository, container registry에 deploy됩니다.
CI/CD > Jobs > #job_no > console log
7405 [INFO] Uploading to ci-gitlab-maven: http://gitlab.domain.com/api/v4/projects/24/packages/maven/com/domain/sendbox/[MASKED]/1.0.1-SNAPSHOT/maven-metadata.xml
7607 [INFO] Uploaded to ci-gitlab-maven: http://gitlab.domain.com/api/v4/projects/24/packages/maven/com/domain/sendbox/[MASKED]/1.0.1-SNAPSHOT/maven-metadata.xml (777 B at 3.9 kB/s)
7607 [INFO] Uploading to ci-gitlab-maven: http://gitlab.domain.com/api/v4/projects/24/packages/maven/com/domain/sendbox/[MASKED]/maven-metadata.xml
7842 [INFO] Uploaded to ci-gitlab-maven: http://gitlab.domain.com/api/v4/projects/24/packages/maven/com/domain/sendbox/[MASKED]/maven-metadata.xml (347 B at 1.5 kB/s)
7842 [INFO] ------------------------------------------------------------------------
7842 [INFO] BUILD SUCCESS
7842 [INFO] ------------------------------------------------------------------------
7843 [INFO] Total time: 7.380 s
7843 [INFO] Finished at: 2022-12-02T05:11:54Z
7843 [INFO] ------------------------------------------------------------------------
Saving cache for successful job
Gitlab > project > Packages and registries > Package registry
CI/CD > Jobs > #job_no > console log
$ docker build --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --tag $CI_REGISTRY_IMAGE:latest .;
Step 1/6 : FROM openjdk:11-jre-slim
(생략)
$ docker push $CI_REGISTRY_IMAGE:latest;
The push refers to repository [registry.gitlab.domain.com/sandbox/ci]
Gitlab > project > Packages and registries > Container registry
CI/CD > Jobs > #job_no > console log
7687 [INFO] Uploading to private-nexus3-maven-snapshots: http://nexus.domain.com/repository/maven-snapshots/com/domain/sendbox/[MASKED]/1.0.1-SNAPSHOT/maven-metadata.xml
7736 [INFO] Uploaded to private-nexus3-maven-snapshots: http://nexus.domain.com/repository/maven-snapshots/com/domain/sendbox/[MASKED]/1.0.1-SNAPSHOT/maven-metadata.xml (780 B at 16 kB/s)
7736 [INFO] Uploading to private-nexus3-maven-snapshots: http://nexus.doamin.com/repository/maven-snapshots/com/domain/sendbox/[MASKED]/maven-metadata.xml
7775 [INFO] Uploaded to private-nexus3-maven-snapshots: http://nexus.domain.com/repository/maven-snapshots/com/domain/sendbox/[MASKED]/maven-metadata.xml (367 B at 9.4 kB/s)
7775 [INFO] ------------------------------------------------------------------------
7775 [INFO] BUILD SUCCESS
7775 [INFO] ------------------------------------------------------------------------
7776 [INFO] Total time: 7.281 s
7776 [INFO] Finished at: 2022-12-02T05:12:04Z
7776 [INFO] ------------------------------------------------------------------------
Saving cache for successful job
Nexus3 > maven-snapshots
CI/CD > Jobs > #job_no > console log
$ docker build --tag $CI_NEXUS_REGISTRY/$CI_PROJECT_NAME:$CI_COMMIT_SHA --tag $CI_NEXUS_REGISTRY/$CI_PROJECT_NAME:latest .;
Step 1/6 : FROM openjdk:11-jre-slim
11-jre-slim: Pulling from library/openjdk
(생략)
$ docker push $CI_NEXUS_REGISTRY/$CI_PROJECT_NAME:latest;
The push refers to repository [[MASKED]/ci]
Nexus3 > docker-hosted
작성된 코드는 아래 Repository에 올려두었습니다.
궁금한 점이 있으시면 덧글로 남겨주세요. 확인 하는 대로 답변 드리도록 하겠습니다. :)
- Self managed repository and CI #1 - Overview
- Self managed repository and CI #2 - Docker network, Nginx reverse proxy
- Self managed repository and CI #3 - Nexus3
- Self managed repository and CI #4 - Minio
- Self managed repository and CI #5 - Gitlab
- Self managed repository and CI #6 - Gitlab-runner
- Self managed repository and CI #7 - Gitlab-CIㆍ현재 글