DinD(Docker in Docker) & DooD(Docker out of Docker)

min.c00·2023년 6월 10일
3
post-thumbnail

이 글을 쓰게된 이유는 CI/CD를 구축하는 과정 중 만나게된 개념인 DinD & DooD에 대해 궁굼증이 생겨서, 내용을 학습하고 정리한 글입니다.

참고한 [블로그](Spring & Jenkins & Docker & DockerHub & GitHub 활용한 CI/CD) 는 링크를 걸어 두었습니다. (굉장히 잘 정리해 주셨으니 저처럼 CI/CD를 처음 구축해보는 분들에게는 강력 추천하는 글입니다!!)


  • 목표
  1. local에서 Github으로 푸시한다.
  2. Githubdml webhook을 이용해 jenkins에 전달한다.
  3. jenkins 동작과정
    1. Github의 코드를 받아 빌드, 테스트를 진행한다.
    2. Dockerfile을 이용해 이미지를 빌드하고 DockerHub에 푸시한다.
    3. deploy.sh파일을 운영 EC2로 전송하고 운영EC2에 deploy.sh 실행 명령어를 보낸다.
    4. deploy.sh안에는 DockerHub에서 이미지를 받아오고 실행시키는 코드가 담겨있다.
  4. 운영용 EC2에서는 deploy.sh 파일을 실행하여 docker로 spring boot 프로젝트를 띄운다.

  • 문제 정의
  1. jenkins용 EC2내에서 Docker 데몬은 돌아가고 있다. (호스트 시스템내의 Docker Engine)
  2. EC2 내에서 Docker를 이용해 Jenkins이미지를 가져와 Container로 띄운다.
  3. 이 jenkins 안에서 Dockerfile을 빌드하여 DockerHub로 push한다.

맞닥드린 문제는 다음과 같고 3번째 문장 jenkins안에서 Dockerfile을 빌드하기 위해서는 "Docker로 띄운 jenkins container안에서 docker 명령어 사용이 가능해야한다."

📌 결론부터 말하자면, 이글은 "Docker로 띄운 jenkins container안에서 docker 명령어 사용이 가능해야한다." 문장을 이해하고 적용하기 위한 과정을 정리하는 글이다.


1. Docker 명령어를 사용한다는 말의 의미

docker run 
docker ps

위의 docker 명령얻들은 cli를 활용해 docker 이미지를 실행하고 실행중인 이미지 등을 보는 명령어이다.

우리는 이 명령어들을 사용해 docker 를 자유롭게 활용할 수 있다.

이게 어떻게 가능한 것일까?


2. Docker 시스템 유닛 (Docker의 구성 요소)

위의 물음에 답하기 위해서는 docker의 구성요소에 대해 알고 넘어갈 필요가 있다.

  1. Client
  • 사용자가 docker를 제어하기 위해 사용하는 도구
  • docker cli를 통해 사용자와 상호작용함
  • client는 사용자의 명령을 docker 데몬에 전달하고 데몬의 응답을 받아 사용자에게 표시한다.
  1. Host(데몬)
  • docker 컨테이너를 생성, 관리, 실행하는 역할을 수행
  • 데몬은 백그라운드에서 실행되는 서비스로 호스트 시스템 위에서 동작함.
  • 데몬은 컨테이너간의 격리를 위해 리눅스 컨테이너 기술인 namespaces, cgroups 등을 사용한다.
  1. Registry
  • docker 이미지를 저장하고 배포하는 중앙 저장소

Docker는 데몬과 클라이언트 간의 통신을 할 때 로컬에서는 유닉스 소켓(docker.sock)을 사용하고, 원격에서는 TCP 소켓을 사용한다.

정리하자면 결국 원격 레지스트리에 통신하는 것도, 이미지들을 관리하는 것도, 접근하는 것도 Host(데몬)이다.

그럼 이제 질문에 답을 해보자. 도커 명령어를 사용한다는 말의 의미는 무엇일까?

💡 도커 명령어를 사용한다는 건 client를 통해 docker 명령어를 받고 client가 중간의 rest api를 거쳐서 데몬에 docker 명령어를 전달해 그 결과값을 받아 사용자에게 보여주는 일련의 과정이 가능해야 함을 의미한다.

이제 위에서 정리한 내용을 기반으로 "Docker로 띄운 jenkins container안에서 docker 명령어 사용이 가능해야한다." 이 문장은 "Docker로 띄운 jenkins container안에서 호스트 시스템의 Docker 데몬의 사용이 가능해야 한다." 로 수정할 수 있다.


3. 어떻게 가능하게 할것인가?

그럼 위에서 정의한 문제를 어떻게 설계할 수 있는지에 대한 의문이든다.

이 물음에 답은 다음 문장을 성공적으로 수행했을 때 가능하다.

📌 DooD(Docker out of Docker)를 사용하기 위해 Docker 컨테이너를 실행할 때 호스트 시스템의 Docker 소켓을 컨테이너 내부로 바인딩 할 수 있다.

이번에도 문장의 의미를 한번에 이해할 수 없다. 늘 그랬듯 이 문장의 의미를 해석하기 위해 차근차근 단계를 거쳐가보자!


4. DinD(Docker in Docker) & DooD(Docker out of Docker)

드디어 오늘의 포스트 주제에 대해 이야기 할 수 있는 모든 빌드업이 마무리 됬다.

  1. DinD(Docker in Docker)

이 방식은 간단히 말해서 도커 컨테이너 내부에서 도커 컨테이너를 생성하는 방법을 의미한다.

예를 들어 ubuntu 컨테이너를 실해아고 해당 컨테이너 내에서 다른 컨테이너를 생성하는 과정을 떠올릴 수 있습니다.

하지만 이 방법은 일반적으로 성능과 보안적인 측면 때문에 권장되지는 않습니다.

자세한 내용은 해당 링크를 참고해 주세요!


  1. DooD(Docker out of Docker)

이 방식은 위에서 다룬 문제에 대한 답이기에 단계를 나눠 그 방식을 소개하려고 합니다.

1) Docker 데몬을 컨테이너 내에서 직접 사용한다. 
2) 컨테이너 내부에서 호스트의 Docker 데몬에 접근한다. 
3) Docker 명령을 실행하고 이미지를 다운로드하여 컨테이너를 생성하고 실행한다. 

DooD 방식을 요약하면 이와 같습니다. 핵심은 컨테이너 내부에서 호스트의 Docker 데몬에 접근하는 것 입니다.

그럼 다시 돌아와 이해가 되지 않았던 문장을 다시 회귀해 봅시다.

📌 DooD(Docker out of Docker)를 사용하기 위해 Docker 컨테이너를 실행할 때 호스트 시스템의 Docker 소켓을 컨테이너 내부로 바인딩 할 수 있다.

"DooD를 사용하기 위해 Docker 컨테이너를 실행" 이라는 말의 의미는 jenkins 컨테이너에서 DooD 방식을 통해 Dockerfile을 생성하고 DockerHub에 푸시한다는 것으로 이제 이해할 수있습니다.

그럼 "호스트 시스템의 Docker 소켓을 컨테이너 내부로 바인딩 할 수 있다." 이말의 의미는 무엇일까요?


5. 어떻게 DooD를 구현할 것인가?

결론부터 말하자면 DooD를 구현하겠다는 말을 풀어쓴 문장입니다.

호스트의 Docker 데몬은 Unix 소켓을 통해 통신하는데 DooD사용하기 위해 Docker 컨테이너를 실행할 때 호스트 시스템의 Docker 소켓을 컨테이너 내부로 바인딩 하는 것을 의미합니다.

Docer 소켓의 위치는 /var/run/docker.sock에 위치하고 있으며 이 파일을 jenkins 컨테이너 내부로 바인딩 하는 것을 의미한다고 볼 수 있습니다.

다음은 두 단계를 거쳐 jenkins 컨테이너 내부로 docker 소켓을 바인딩 하는 작업을 소개하겠습니다.

  • 1단계
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 파일입니다.

  • 2단계
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/

0개의 댓글