ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • DooD (docker-outside-of-docker) 를 통해 Jenkins 컨테이너에서 docker 사용하기
    docker 2021. 9. 6. 20:55
    반응형

    Jenkins 를 docker 를 통해 컨테이너로 띄우는 것이 아주 편해져서 이제는 docker 로 운영하고 있다.

    그런데, Jenkins 상에서 Docker 관련 작업이 필요하여 단순하게 컨테이너 내부에서 설치를 하려고 했는데, 내부에서 docker 를 띄우는 것과 관련하여 이것저것 이슈가 있다고 한다. (https://jpetazzo.github.io/2015/09/03/do-not-use-docker-in-docker-for-ci/)

    관련해서 좀 더 찾아보았는데, 내부에서 Docker 를 전부 띄우지 말고 외부(호스트 환경) 의 Docker 와 소켓을 공유하여 사용하는 것이 그나만 나은 방법이라고 한다.

    이를 기존의 방식인 Docker-in-docker 와 대비하여 Docker-outside-of-docker 라고 부르는 것 같다. 완전히 정착된 이름은 아닌 것 같지만 이 글에서는 이 이름을 사용하겠다.

     

    공식 Jenkins 이미지: https://hub.docker.com/r/jenkins/jenkins

    공식 Docker 이미지: https://hub.docker.com/_/docker (여기도 Docker-in-docker 를 추천하지 않는다고 쓰여있다.)


    환경

    • 호스트 서버
      • CentOS 7.9
      • Docker server: 20.10.8
      • 사용자는 docker 그룹에 포함되어 있다. (sudo 없이 docker 명령어 입력 가능)
    • Jenkins 컨테이너
      • 기본 이미지: 2.289.3-jdk11
        • 내부에서 Docker 를 사용해야 하기 때문에 이를 베이스로 새로 이미지를 만들 것이다.
      • Docker client: 20.10.8


    1. Jenkins 이미지 만들기

    컨테이너 내부에서 외부(호스트) 도커와 통신해야 하기 때문에 추가로 설치할 것이 있다. 기본 이미지는 현시점 (2021-09-06) 에서 가장 최신의 lts 버전이고, jdk11 이 들어 있는 버전인 2.289.3-jdk11 을 택한다.

    젠킨스 이미지: https://hub.docker.com/r/jenkins/jenkins/tags?page=1&ordering=last_updated&name=2.289.3-jdk11 

     

    Docker client 가 필요하기 때문에 Dockerfile 를 통해 설치하고 이미지를 만든다. 베이스 이미지가 Debian 기반이기 때문에 Debian 환경에 Docker 설치를 위한 가이드를 참고한다.

    공식 가이드: https://docs.docker.com/engine/install/debian/

     

    Dockerfile 은 아래와 같다.

    FROM jenkins/jenkins:2.289.3-jdk11
    
    USER root
    
    RUN apt-get update \
     && apt-get -y install lsb-release \
     && curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \
     && echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \
     && apt-get update \
     && apt-get -y install docker-ce docker-ce-cli containerd.io
    RUN usermod -u {{호스트의사용자아이디}} jenkins && \
        groupmod -g {{호스트의도커그룹아이디}} docker && \
        usermod -aG docker jenkins
    
    USER jenkins

     

    • 사이트에서 요구하는 패키지들이 있는데, 대부분 이미 설치되어 있고, lsb-release 만 추가로 설치하면 된다.
    • 외부(호스트) 도커 서버를 사용할거라서 docker-ce-cli 만 설치해도 되기는 하지만, docker-ce 를 설치해야 docker 그룹이 생긴다. 괜히 건드렸다가 꼬일 것 같아서 그냥 가이드대로 다 설치했다.
    • 컨테이너 내부 사용자 (jenkins) 가 호스트의 파일에 접근이 가능 가능하도록 호스트 사용자 아이디와 동일하도록 맞춰준다. (위 Dockerfile 에서 {{호스트의사용자아이디}})
      • 사용자 아이디는 호스트의 /etc/passwd 에서 확인한다.
    • 컨테이너의 도커 그룹 아이디를 호스트의 도커 그룹 아이디와 동일하게 맞춘다. (위 Dockerfile 에서 {{호스트의도커그룹아이디}})
      • 도커 그룹 아이디는 호스트의 /etc/group 에서 확인한다.

    이미지를 만든다.

    docker build -t my-jenkins:0.1 .

    확인

    [user@host ~]$ docker image ls
    REPOSITORY                 TAG             IMAGE ID       CREATED         SIZE
    my-jenkins                 0.1             df9c3ec43a7c   4 minutes ago   1.15GB
    jenkins/jenkins            2.289.3-jdk11   ea470c80c15d   5 weeks ago     680MB

    2. volume 만들기

    jenkins 설정 및 히스토리를 저장하고 재시작시에도 유지되도록 volume 을 만든다.

    docker volume create jenkins

    확인

    [user@host ~]$ docker volume ls
    DRIVER    VOLUME NAME
    local     jenkins

    3. Jenkins 컨테이너 실행

    docker run -d --name jenkins \
        -v /var/run/docker.sock:/var/run/docker.sock \
        -v jenkins:/var/jenkins_home \
        -p 8080:8080 my-jenkins:0.1
    • 핵심은 docker.sock 을 마운트 하는 것이다. 이를 통해 컨테니어 내부에서 외부(호스트) 의 docker 서버에 접근할 수 있다.
    • volume 을 마운트하고, 접근 포트를 열어준다.

    컨테이너가 잘 떴는지 확인해 보자

    [user@host ~]$ docker ps
    CONTAINER ID   IMAGE            COMMAND                  CREATED         STATUS        PORTS                               NAMES
    d57073d5fec2   my-jenkins:0.1   "/sbin/tini -- /usr/…"   3 seconds ago   Up 1 second   0.0.0.0:8080->8080/tcp, 50000/tcp   jenkins

    jenkins 컨테이너 내부에서도 호스트의 docker 에 접근이 가능한지 내부에서 호출하여 확인해 보자

    [user@host ~]$ docker exec jenkins docker ps
    CONTAINER ID   IMAGE            COMMAND                  CREATED         STATUS         PORTS                               NAMES
    d57073d5fec2   my-jenkins:0.1   "/sbin/tini -- /usr/…"   2 minutes ago   Up 2 minutes   0.0.0.0:8080->8080/tcp, 50000/tcp   jenkins

    호스트의 도커 서버를 공유하고 있기 때문에 같은 결과가 나온다.

    반응형

    댓글

Designed by Tistory.