- Today
- Total
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- SPRING JWT
- SpringBoot
- 팀네이버
- Project
- LazyInitialization
- 캐싱전략
- 만들면서 배우는 클린 아키텍처
- 프로젝트
- Java
- JPA
- infra
- EntityTransaction
- Spring Security
- container
- 스프링
- chrome80
- 브랜치전략
- JWT
- 책
- 후기
- 팀네이버 공채
- spring
- docker
- redis
- Kotlin
- 리뷰
- websocket
- jenkins
- 젠킨스
- network
PPAK
[CI/CD] Docker 에서 Jenkins 구동하기 본문
이번 팀 프로젝트를 준비하면서 CI/CD 환경 구축을 해봐야겠다고 마음을 먹었다.
우선은 Jenkins 이미지를 생성하고 컨테이너를 생성하는 과정에서 중요한 부분을 정리하고자 본 글을 작성한다.
들어가기에 앞서서, 쓰게될 글을 간단하게 요약을 하면
Local Machine (실제 배포과정에선 EC2 인스턴스?) 의 Docker 를 통해 Jenkins Image 를 생성하고 실행하는 것이 전부인데
그 과정에서
1. Jenkins Image 생성을 위한 Dockerfile 작성
2. DooD (Docker out of Docker) 방식 적용
3. 가상 tty 로 Container 에 접근해 파일 수정
을 수행할 예정이다.
Jenkins Image 생성을 위한 Dockerfile, Shell Script 작성
#https://hub.docker.com/r/jenkins/jenkins
#pull jenkins image
FROM jenkins/jenkins:jdk11
USER root
#컨테이너 내에서 필요한 도커 설치
COPY docker_install.sh /docker_install.sh
RUN chmod +x /docker_install.sh
RUN /docker_install.sh
#설치 후 docker 그룹의 jenkins 계정 생성 후 해당 계정으로 변경
RUN groupadd -f docker
RUN usermod -aG docker jenkins
USER jenkins
https://github.com/docker/docker-install
docker 설치를 위한 공식 shell script
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
Jenkins 이미지를 불러온 후 컨테이너 내부에서 Jenkins 의 command 에 포함될 docker 명령을 위해서 docker 를 설치한다.
docker 를 설치할 때는 지속적으로 설치가 가능하도록 shell script 를 불러와서 실행한다.
여기서 한 가지 의문이 들 수 있다.
docker 위에서 동작하는 컨테이너에서 다시 docker 를 설치한다?
컨테이너 내에서 docker 관련 명령을 수행하기 위해서(Jenkins 의 빌드 자동화 과정에서 docker build 명령어를 수행하는 등의) docker daemon 의 도움이 필요하다.
여기서 우리는 두 가지 선택이 가능한데
1. Docker 위에 Docker Container 를 생성한다. (Docker In Docker, DInD)
2. Local Machine 위에서 실행 중인 docker daemon 을 이용한다. (Docker out of Docker, DooD)
여기서 DInD 를 적용하기 위해서는 Docker Container 의 권한을 --privileged 로 설정해야하는데, 해당 권한이 Local Machine 의 대부분의 장치에 접근 가능하기 때문에 보안 상에 큰 단점이 존재하여 추천하지 않는 방식이라고 한다.
DooD 는 Local Machine 의 docker daemon 을 통해 docker 명령어를 수행하는 방식으로, 이 역시 100% 안전한 방식이라고는 할 수 없지만 권장되어 사용하는 방식이다.
Docker Build
jenkins image 를 생성할 준비가 완료되었으므로 build 를 실시한다.
docker build -t jenkins/test_jenkins:1.0 .
Docker Desktop 혹은 docker images 를 통해 확인 가능하다.
Docker Run (중요!!)
https://hub.docker.com/_/jenkins 에 따르면
모든 jenkins data 가 /var/jenkins_home 에 저장된다고 한다 -> container 의 마운팅 포인트
-v 옵션을 통해 컨테이너에서 생성된 jenkins data 를 영구 저장할 수 있도록 한다.
위를 바탕으로 작성한 docker run code 이다
docker run -d -p 9090:8080 --name=jenkinscicd \
-v ~/jenkins_home_sub:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
jenkins/test_jenkins
여기서 -v /var/run/docker.sock:/var/run/docker.sock 를 추가한 이유는
위의 DooD 를 적용하기 위해서 인데, Local Machine 의 Docker socket 을 Container 의 것과 공유하여, Local Machine Docker daemon 으로 명령어를 보낼 수 있게 한다.
하지만 여기까지 설정하고, 실제로 Jenkins 를 사용하다보면 docker 명령어에 대한 permission denied 가 뜰 수 있다.
현재까지의 상태를 나열해 보면
container 에서 docker 를 설치한 유저 : root
docker.sock 의 접근 권한 : root group level
현재 container 의 유저 : docker(usermod 명령어 참고)
따라서 container 의 권한을 변경할 수는 없으니 container 내부의 docker.sock 파일의 권한을 변경해주도록 한다.
Docker Container 는 일종의 프로세스로 여겨지면서도 가장 큰 차이점은 Container 만의 독립된 파일 시스템이 존재한다는 것인데
이를 통해 터미널로 Container에 접속하여 파일 수정이 가능하다는 것을 의미한다.
Container 접속
docker exec -it -u root [container_id] /bin/bash
docker exec 명령어를 통해 container 에 특정 명령어를 실행하는 것을 의미한다.
따라서 /bin/bash 명령어를 수행하고, -it 옵션은 STDIN 표준 입출력을 열고 가상 tty (pseudo-TTY) 를 통해 접속하겠다는 의미이다.
https://docs.docker.com/engine/reference/commandline/exec/ 참고
이를 통해 /var/run 에서
chown root:docker /var/run/docker.sock
을 수행하고, jenkins container 를 재부팅하면 정상적으로 jenkins agent 가 동작하는 것을 확인할 수 있다.
잘못된 정보가 있다면 댓글로 알려주시면 감사하겠습니다!!
'infra' 카테고리의 다른 글
[Hazelcast] Distributed Computing (Predicate) (0) | 2023.09.28 |
---|---|
[Kafka] 메세지큐 서버 도입과 역할의 분리 (2) | 2023.01.10 |
[CI/CD] 프로젝트 무중단 배포 도입기 (2) | 2023.01.04 |
[CI/CD] Docker 에서 SpringBoot 구동하기 (0) | 2022.07.24 |
[CI/CD] Git Webhook 을 통한 Jenkins-Spring Boot 빌드, 배포 자동화 (0) | 2022.07.24 |