Jenkins 3. 컨테이너 배포(OCI, Dockerhub)
Jenkins 3. 컨테이너 배포(OCI, Dockerhub) — #개발자의도구들 #도커이미지 #도커OCI #Spring서버이미지 #OCI이미지제작 #OCI이미지실습 #젠킨...
#개발자의도구들 #도커이미지 #도커OCI #Spring서버이미지 #OCI이미지제작 #OCI이미지실습 #젠킨스컨테이너 #dockerhub #도커허브
AI스쿨 msa기반 java 백엔드 코스 중에 공부한 내용을 작성하였습니다
\* 현재 Spring x 프로젝트를 진행하고 있습니다. 전체 목차를 보시려면 여기를 눌러주세요.
\* Devops stack: 여기
\* 리눅스 기본기: 여기
Before
👉 OCI 이미지란 무엇인지
https://blog.naver.com/jword\_/223938458112
[컨테이너 아키텍처와 OCI
#개발자의도구들 #컨테이너아키텍처 AI스쿨 msa기반 java 백엔드 코스 중에 공부한 내용을 작성하였습니...
blog.naver.com](https://blog.naver.com/jword_/223938458112)
👉 Jenkins 파이프라인 수동배포
https://blog.naver.com/jword\_/223996728208
[Jenkins 2. VM 수동 배포 자동화하기
#개발자의도구들 #ElasticSearch #Logstash AI스쿨 msa기반 java 백엔드 코스 중에 공부한 내용을 작...
blog.naver.com](https://blog.naver.com/jword_/223996728208)
📌 이전까지 build의 불편한 점
- 현재 Jenkins를 연결 했으나 여전히 많은 문제들이 존재한다.
- MSA서버 특성상 배포할 노드를 각각 준비해줘야 한다.
- 노드마다 각 셋팅을 해줘야 한다.
- ⚙️1. jvm 다운로드 및 버전 맞추기
- 매우 단순한 일이긴하지만, 매번 셋팅하는 것이 매우 귀찮다.
- 특정 노드는 다른 버전의 jvm이 필요한 경우도 있을 것이다.
- 예를들어, ServerA는 jvm 18버전을
- 내 서버는 현재 jvm 17버전을 사용한다.
⚠️ 리눅스의 경우 라이브러리 버전이 전역에 고정 되므로 다른 버전을 사용한다면 배포에 문제가 발생한다.
컨테이너 런처 & Docker OCI를 통한 배포
기존 구조
- Jar를 실행시키기 위해 JVM이 필요하다.
- 버전을 맞춰줘야 한다.
- 👉⚠️ 다를 경우 문제 발생!
- 개발자가 직접 실행환경을 맞춰야하는 번거로움
- ⚙️ 원격접속
- ⚙️ 각 버전에 맞는 jvm 다운로드
- 😑 번거롭다!
새로운 구조
기존 배포 구조에 OCI 파일 생성 및 배포로 변경합니다.
-
- 빌드는 동일하게 하나의 워커 노드에서 진행
- 빌드된 파일은 OCI 이미지 파일로 제작하여 Dockerhub repository에 push
- MSA 서버별로 접속하여 dockerhub에서 각 이미지를 Pull하여 docker/podman으로 실행합니다.
OCI 이미지 파일 제작하기
Podman을 사용하여 진행할 것이기 때문에 Containerfile을 제작해야합니다. OCI 파일을 본격적으로 생성하기전 다음과 같은 질문을 생각해봅시다.
🤔 언제 OCI가 제작되나요?
- build 이후 jar 파일이 배포 완료되면
👉 그럼 여기서 jar파일이 해당 노드에 있다고 가정할 수 있습니다.
🤔 서버를 실행하기 위해 필요환 환경에 대해 생각해 봅시다.
- Spring을 돌리기 위해서는 다음과 같은 항목들이 필요합니다.
- JVM
- jar파일
- 실행 명령어
필요한 환경을 모두 OCI로 만들어 주면됩니다. 저는 JVM, 배포된 jar파일, 실행 명령어 등을 OCI로 만들었습니다.
\* devops 관련 파일들은 따로 repository를 작성하는 것이 좋습니다.
// 📦 Containerfile 제작
# 사용할 오픈JDK 버전을 명시적으로 지정 (예: 17.0.2)
FROM docker.io/openjdk@sha256:a996cdcc040704ec6badaf5fecf1e144c096e00231a29188596c784bcf858d05
# 작업 디렉터리 설정
WORKDIR /x-front-server
# Jenkins 빌드 결과로 생성된 JAR 파일을 컨테이너로 복사
# (아래 예시 이름을 빌드 산출물의 실제 JAR 이름에 맞게 바꿔주세요)
COPY build/libs/X-FrontServer-0.0.1-SNAPSHOT.jar /x-front-server/front.jar
# 컨테이너가 사용하는 포트 문서화 (예시 8080)
EXPOSE 8080
# 컨테이너 실행 시 JAR 실행
ENTRYPOINT ["java", "-jar", "front.jar"]
⚠️ Anti Pattern
- ❌ docker.io/openjdk:17-jdk-slim
- 이런 식으로 지정하면, 버전이 변경되어 이후 호환이 안될 수 있습니다.
- 👉 JVM은 정확한 태그를 지정해야합니다. (고유식별 가능하도록)
- ❌ ENTRYPOINT \["java", "-jar", "spring-server.jar", "--spring.profiles.active=beta", "--server.port=8090"\] >>> "--server.port=8090" \]
- 명령어는 최소한을 사용합니다. 해당 이미지 파일은 오직 beta프로필만 사용이 가능합니다.
- ❌ 하나의 빌드에 병렬적으로 build & deploy 진행
- MSA에서는 각각 다른 pipeline을 구축하여 분리하는 것이 일반적입니다.
- 내부에서 빌드 순서가 꼬여버릴 수 있고, 언제든 유동적으로 변경되기 때문
Deploy 파이프라인 변경 - 도커허브
파이프라인에서 두개의 repository를 참조합니다. 참조 순서는 아래와 같습니다.
1.
- x-front
- devops전용
1번에서 빌드가 완료된 후 생성된 .jar파일과 devops 전용 repository의 Containerfile을 참고하여 OCI 이미지를 생성해야합니다.
pipeline {
// 📌 reusable env vars
environment {
REGISTRY = 'docker.io'
IMAGE = 'toolod/x-frontserver'
VERSION_TAG = "1.0.0-${new Date().format('yyyyMMdd')}-${UUID.randomUUID().toString().take(7)}"
}
// -- 중략 --
stage('Deploy') {
steps {
// 1) Use devops repo (has oci/Containerfile)
dir('devops-management') {
git url: 'https://github.com/keyveloper/devops-management.git', branch: 'master'
// 2) Bring the JAR into this repo root
// 현재 dir = root
// 📌 $WORKSPACE - worker가 사용하는 루트 dir
sh '''
mv ${WORKSPACE}/build/libs/X-FrontServer-0.0.1-SNAPSHOT.jar ${WORKSPACE}/devops-management
'''
// 3) Build & Push OCI image using oci/Containerfile
withCredentials([string(credentialsId: 'DOCKERHUB_TOKEN', variable: 'DOCKERHUB_TOKEN')]) {
sh '''
# Docker Hub login (Podman)
podman login docker.io -u toolod -p "$DOCKERHUB_TOKEN"
# Build & push
podman build -f oci/Containerfile -t "${REGISTRY}/${IMAGE}:${VERSION_TAG}" .
podman tag "${REGISTRY}/${IMAGE}:${VERSION_TAG}" "${REGISTRY}/${IMAGE}:latest"
podman push "${REGISTRY}/${IMAGE}:${VERSION_TAG}"
podman push "${REGISTRY}/${IMAGE}:latest"
'''
}
}
}
}
}
}
- 환경변수를 사용하여 최대한 다시 쓸 수 있는 것을 저장해 둡시다.
- 이미지를 생성할 때는 반드시 고유태그를 붙여야 합니다. (Gitops를 위함)
- 저의 경우 버전-날짜-UUID 첫 7글자로 사용했습니다.
- latest 태그는 항상 최신으로 업데이트 되도록 설계하였습니다.
이미지가 성공적으로 pull 되었습니다.
Docker hub에서 가져오기
현재까지 진행된 순서는 아래와 같습니다.
- worker node가 build를 진행
- JAR파일과 Containerfile을 참조하여 Dockerhub에 빌드
stage('RUN') {
steps {
sh '''
ssh tod@192.168.0.13 << 'EOF'
# pull from docker hub
podman pull ${REGISTRY}/${IMAGE}:${VERSION_TAG}
podman run -d --name x-front-server-container -p 8080:8080 docker.io/toolod/x-frontserver:latest
EOF
'''
- SSH 접속해서 podman으로 이미지 pull해서 컨테이너 run하기
❌ 에러 발생
Error: invalid reference format
Error: creating container storage:
the container name "x-front-server-container"
is already in use by a78d293035b273de6d9c7d7bd8b09049c33109e0e20d80b640f11953a92ef99d.
You have to remove that container to be able to reuse that name:
that name is already in use, or use --replace to instruct Podman to do so.
- 이미 작동중인 컨테이너이기 때문에 BUILD에 실패합니다!
- 👉 보통 작동중인 서버를 새 서버로 한번에 교체하진 않습니다.
- 하지만 지금은 실습이 중요하니, 컨테이너를 제거하고 다시 띄우는 전략을 취할 수 있습니다.
podman rm -f x-front-server-container || true
- 아래 명령어를 파이프라인에 추가 해줄 수 있습니다.
빌드과정 단축 업데이트
도입 이전: 각 서버 명령어 입력 8회 x n개의 서버 + n개의 서버 셋팅
수동배포 자동화: 빌드 명령어 8회 고정(파이프라인 내에) + n개의 서버 셋팅
컨테이너 자동화 배포: 클릭 한번으로 전 과정 자동화




