이 글을 쓰게된 이유는 CI/CD를 구축하는 과정 중 만나게된 개념인 DinD & DooD에 대해 궁굼증이 생겨서, 내용을 학습하고 정리한 글입니다.
참고한 [블로그](Spring & Jenkins & Docker & DockerHub & GitHub 활용한 CI/CD) 는 링크를 걸어 두었습니다. (굉장히 잘 정리해 주셨으니 저처럼 CI/CD를 처음 구축해보는 분들에게는 강력 추천하는 글입니다!!)
맞닥드린 문제는 다음과 같고 3번째 문장 jenkins안에서 Dockerfile을 빌드하기 위해서는 "Docker로 띄운 jenkins container안에서 docker 명령어 사용이 가능해야한다."
📌 결론부터 말하자면, 이글은 "Docker로 띄운 jenkins container안에서 docker 명령어 사용이 가능해야한다." 문장을 이해하고 적용하기 위한 과정을 정리하는 글이다.
docker run
docker ps
위의 docker 명령얻들은 cli를 활용해 docker 이미지를 실행하고 실행중인 이미지 등을 보는 명령어이다.
우리는 이 명령어들을 사용해 docker 를 자유롭게 활용할 수 있다.
❓ 이게 어떻게 가능한 것일까?
위의 물음에 답하기 위해서는 docker의 구성요소에 대해 알고 넘어갈 필요가 있다.
Docker는 데몬과 클라이언트 간의 통신을 할 때 로컬에서는 유닉스 소켓(docker.sock)을 사용하고, 원격에서는 TCP 소켓을 사용한다.
정리하자면 결국 원격 레지스트리에 통신하는 것도, 이미지들을 관리하는 것도, 접근하는 것도 Host(데몬)이다.
그럼 이제 질문에 답을 해보자. 도커 명령어를 사용한다는 말의 의미는 무엇일까?
💡 도커 명령어를 사용한다는 건 client를 통해 docker 명령어를 받고 client가 중간의 rest api를 거쳐서 데몬에 docker 명령어를 전달해 그 결과값을 받아 사용자에게 보여주는 일련의 과정이 가능해야 함을 의미한다.
이제 위에서 정리한 내용을 기반으로 "Docker로 띄운 jenkins container안에서 docker 명령어 사용이 가능해야한다." 이 문장은 "Docker로 띄운 jenkins container안에서 호스트 시스템의 Docker 데몬의 사용이 가능해야 한다." 로 수정할 수 있다.
그럼 위에서 정의한 문제를 어떻게 설계할 수 있는지에 대한 의문이든다.
이 물음에 답은 다음 문장을 성공적으로 수행했을 때 가능하다.
📌 DooD(Docker out of Docker)를 사용하기 위해 Docker 컨테이너를 실행할 때 호스트 시스템의 Docker 소켓을 컨테이너 내부로 바인딩 할 수 있다.
이번에도 문장의 의미를 한번에 이해할 수 없다. 늘 그랬듯 이 문장의 의미를 해석하기 위해 차근차근 단계를 거쳐가보자!
드디어 오늘의 포스트 주제에 대해 이야기 할 수 있는 모든 빌드업이 마무리 됬다.
이 방식은 간단히 말해서 도커 컨테이너 내부에서 도커 컨테이너를 생성하는 방법을 의미한다.
예를 들어 ubuntu 컨테이너를 실해아고 해당 컨테이너 내에서 다른 컨테이너를 생성하는 과정을 떠올릴 수 있습니다.
하지만 이 방법은 일반적으로 성능과 보안적인 측면 때문에 권장되지는 않습니다.
자세한 내용은 해당 링크를 참고해 주세요!
이 방식은 위에서 다룬 문제에 대한 답이기에 단계를 나눠 그 방식을 소개하려고 합니다.
1) Docker 데몬을 컨테이너 내에서 직접 사용한다.
2) 컨테이너 내부에서 호스트의 Docker 데몬에 접근한다.
3) Docker 명령을 실행하고 이미지를 다운로드하여 컨테이너를 생성하고 실행한다.
DooD 방식을 요약하면 이와 같습니다. 핵심은 컨테이너 내부에서 호스트의 Docker 데몬에 접근하는 것 입니다.
그럼 다시 돌아와 이해가 되지 않았던 문장을 다시 회귀해 봅시다.
📌 DooD(Docker out of Docker)를 사용하기 위해 Docker 컨테이너를 실행할 때 호스트 시스템의 Docker 소켓을 컨테이너 내부로 바인딩 할 수 있다.
"DooD를 사용하기 위해 Docker 컨테이너를 실행" 이라는 말의 의미는 jenkins 컨테이너에서 DooD 방식을 통해 Dockerfile을 생성하고 DockerHub에 푸시한다는 것으로 이제 이해할 수있습니다.
그럼 "호스트 시스템의 Docker 소켓을 컨테이너 내부로 바인딩 할 수 있다." 이말의 의미는 무엇일까요?
결론부터 말하자면 DooD를 구현하겠다는 말을 풀어쓴 문장입니다.
호스트의 Docker 데몬은 Unix 소켓을 통해 통신하는데 DooD사용하기 위해 Docker 컨테이너를 실행할 때 호스트 시스템의 Docker 소켓을 컨테이너 내부로 바인딩 하는 것을 의미합니다.
Docer 소켓의 위치는 /var/run/docker.sock에 위치하고 있으며 이 파일을 jenkins 컨테이너 내부로 바인딩 하는 것을 의미한다고 볼 수 있습니다.
다음은 두 단계를 거쳐 jenkins 컨테이너 내부로 docker 소켓을 바인딩 하는 작업을 소개하겠습니다.
Dockerfile 생성
sudo vim Dockerfile
Dockerfile 작성 시작
FROM jenkins/jenkins:jdk11
#도커를 실행하기 위한 root 계정으로 전환
USER root
#도커 설치
COPY docker_install.sh /docker_install.sh
RUN chmod +x /docker_install.sh
RUN /docker_install.sh
# 도커 그룹에 사용자 추가
RUN usermod -aG docker jenkins
USER jenkins
간단히 말해 jenkis 용 docker 컨테이너를 생성할 Dockerfile을 작성하고 해당 컨테이너 내부에서 docker를 설치합니다.
docker_install.sh 파일 생성
sudo vim docker_install.sh
docker_install.sh 파일 작성 시작
#!/bin/sh
apt-get update && \
apt-get -y install apt-transport-https \
ca-certificates \
curl \
gnupg2 \
zip \
unzip \
software-properties-common && \
curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg > /tmp/dkey; apt-key add /tmp/dkey && \
add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
$(lsb_release -cs) \
stable" && \
apt-get update && \
apt-get -y install docker-ce
도커를 설치하는 .sh 파일입니다.
sudo chmod 666 /var/run/docker.sock
도커는 host의 docker.sock을 빌려서 사용한다고 했습니다. 따라서 docker.sock 파일의 권한을 변경하여 그룹 내 다른 사용자도 접근 가능하도록 변경해줘야 합니다. 다음 명령어로 접근 가능하도록 세팅해줍니다.
이번글은 도커로 띄운 jenkins 컨테이너 안에서 도커 명령어 사용이 가능하게 하기 위해 어떤 내용을 알아야하는 지 정리해보았습니다.
긴글 읽어 주셔서 감사합니다.
출처: https://backtony.github.io/spring/aws/2021-08-08-spring-cicd-1/#도커-세팅
https://aidanbae.github.io/code/docker/dinddood/