☘ ANONI Chat - CICD 구성
graph TD
A[GitHub Push]
B[Jenkins Git Pull]
C[Gradle Build Jar]
D[Docker Build & Tag]
E[DockerHub Push]
F[서버 Pull + Deploy]
DinD란? - “도커 안에 도커를 실행한다”는 개념.
방식 | 설명 | 핵심 개념 |
---|---|---|
1️⃣ 진짜 DinD (Nested Docker) | 컨테이너 안에 Docker 엔진 자체를 설치하고 dockerd 를 직접 실행 |
내부에 완전한 Docker daemon |
2️⃣ Docker-outside-of-Docker (DooD) | 컨테이너에서 호스트의 Docker 데몬에 접근 (/var/run/docker.sock 바인드) |
외부 Docker 제어 |
3️⃣ Remote Docker | 컨테이너에서 다른 머신의 Docker 데몬을 TCP로 접근 (tcp://... ) |
원격 제어 |
일반적인 경우에, Docker에서 Jenkins이미지를 pull받아 컨테이너를 실행시키는 것이 가장 간단하다. 하지만, 이번엔 같은(Ubuntu)서버 내에서 Jenkins와 Spring서버를 Docker로 함께 띄울예정 이다.
그렇게 때문에 위에서 기술한 DooD방식으로 Docker로 띄운 Jenkins안에서 Docker를 제어해야한다.
이를위해 /var/run/docker.sock
을 마운트 해야한다.
현재 스펙은 ubuntu:22.04 / Spring 3.3.12 / Java17 이다.
# 베이스 이미지 설정
FROM ubuntu:22.04
LABEL maintainer="xotjd794613@naver.com"
#- **비대화식 모드 설정**
# apt 설치 시 발생하는 `timezone 설정`, `Y/N 질문` 등을 자동으로 건너뛰기 위한 설정
ENV DEBIAN_FRONTEND=noninteractive
# 1. UBUNTU 시스템 패키지`s 설치
RUN apt-get update && apt-get install -y \
curl gnupg2 ca-certificates apt-transport-https software-properties-common \
git sudo unzip wget lsb-release openjdk-17-jdk \
&& apt-get clean
# 2. 사용자 hello 생성 및 sudo 권한 부여(비밀번호 묻지 않도록)
# Docker CLI 사용이나 기타 시스템 명령 실행 시 필요
RUN useradd -m -d /home/hello -s /bin/bash hello \
&& echo "hello ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
ENV JENKINS_HOME=/home/hello
# 3. Docker CLI 설치 (DooD 방식) - Jenkins 내부에서 `docker build`, `docker run`, `docker push` 명령 사용 가능
# Jenkins가 호스트의 Docker 데몬을 **/var/run/docker.sock**로 제어하게 되는 구조를 전제로 셋팅
RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker.gpg && \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
> /etc/apt/sources.list.d/docker.list && \
apt-get update && apt-get install -y docker-ce-cli
# 4. Jenkins WAR 다운로드 (LTS 버전)
# /usr/share/jenkins.war 경로에 배치
ENV JENKINS_VERSION=2.440.1
RUN wget https://get.jenkins.io/war-stable/${JENKINS_VERSION}/jenkins.war -O /usr/share/jenkins.war
# 5. 포트 노출
# → 도커 실행 시 `-p 8080:8080 -p 50000:50000` 으로 외부 연결 가능
EXPOSE 8080
EXPOSE 50000
# 6. Jenkins 실행
# Dockerfile 실행 이후 명령은 `jenkins` 사용자 권한으로 실행됨 (보안을 위해 루트 권한 피함)
USER hello
WORKDIR /var/hello
# `8080` 포트에서 Jenkins 서비스가 시작됨
CMD ["java", "-jar", "/usr/share/jenkins.war"]
Docker이미지 빌드
jenkins-dood
이름으로 이미지 생성docker build -t jenkins-dood .
docker tag jenkins-dood xotjd794613/jenkins-dood:v0.01
push/pull 후 docker.sock 사용하여 실행
docker run -d \
--name jenkins-dood \
-p 8080:8080 \
-v /var/run/docker.sock:/var/run/docker.sock \
jenkins-dood:v0.01
permission denied
오류
즉, /var/run/docker.sock
파일에 접근할 수 있는 권한이 없기 때문에 발생한 오류이다.
다음과 같이 docker.sock에 접근권한은 root만이 갖고 있기 때문에,
현재 계정을 docker
그룹에 포함시켜야 한다.
# + Docker 그룹id확인 후(GID: 999)에 추가 (호스트와 GID 일치)
RUN groupadd -g 999 docker && \
useradd -m -d /home/hello -s /bin/bash -G docker hello && \
echo "hello ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
또는
root계정으로 변경 후 권한주기
sudo usermod -aG docker hello(계정명)
문제 해결 후,
ip주소:8080
으로 접속하면 jenkins admin 페이지를 확인할 수 있다.
위 페이지에서 admin passwd를 찾기 위해서는 ssh에서 다음 명령어를 통해 알 수 있다.
docker exec -it jenkins-dood cat /home/hello/secrets/initialAdminPassword
Install suggested plugins
!만약 특정한 커스텀 설정이나 최소 설치 환경이 필요한 경우엔 오른쪽을 선택해서 수동으로 선택할 수 있음
자동 설치중 대부분에서 fail
이 발생했다.
핑 확인시 정상적으로 붙어있는 모습
그렇다면 무엇이 문제일까?
이를 위한 확인. (컨테이너에 붙기)
docker exec -it jenkins-dood bash
# 컨테이너에 붙은 후 `apt update로 확인`
E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)
E: Unable to lock directory /var/lib/apt/lists/
다음과 같은 로그를 보고 큰 단서를 얻을 수 있었다.
이 에러는 컨테이너 내부에서 apt update
를 실행하려 했지만, 현재 사용자가 루트 권한이 아니기 때문에 실패한 것이다.
jenkins dockerfile 중,,, 다음 부분을 보면 알 수 있다.
# 6. Jenkins 실행
# Dockerfile 실행 이후 명령은 `jenkins` 사용자 권한으로 실행됨 (보안을 위해 루트 권한 피함)
USER hello
WORKDIR /var/hello
하지만...
이미 hello 계정에는 /etc/sudoers
sudo권한을 준것을 볼 수있다.
RUN groupadd -g 999 docker && \
useradd -m -d /home/hello -s /bin/bash -G docker hello && \
echo "hello ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# /usr/share/jenkins.war 경로에 배치
#ENV JENKINS_VERSION=2.440.1 !!플러그인 설치 실패로 인해 버전업
ENV JENKINS_VERSION=2.462.3
RUN wget https://get.jenkins.io/war-stable/${JENKINS_VERSION}/jenkins.war -O /usr/share/jenkins.war
결론
젠킨스 파이프라인(Jenkins Pipeline)이란, 소프트웨어 빌드, 테스트, 배포의 전체 과정을 코드로 정의하고 자동화할 수 있게 해주는 Jenkins의 핵심 기능이다.
CI/CD(지속적 통합/지속적 배포)를 효율적으로 수행하기 위한 필수 도구이다.
다음 설정을 통해 파이프라인을 구성할 수 있다.
Git repo에 push시 자동적으로 통합 / 배포 할 수 있지만, 일단은 Jenkins Admin에서 수동 트리거 되도록 설정해 두었다.
Git repo(prod branch) push 후 → Jenkins 수동 빌드
시