AWS/CICD

[Gitlab] dind 란?, 트러블 슈팅, error during connect: Post http://dind:2375/v1.40/auth: dial tcp: lookup dind on 172.31.0.2:53: no such host

Jaden Park 2021. 10. 30. 01:03

dind 란?

젠킨스에서 보는 dind

깃랩에서의 dind

Gitlab runner 에서 마주한 에러

해결방법

 

 


Docker in Docker (DinD) 란?

도커 안에 도커라는 의미이다.

도커 바이너리를 설정하고 컨테이너 내부의 격리된 Docker 데몬을 실행하는 작업

CI 측면에서 접근한다면 job(task)을 수행하는 Executor(Agent)가 Docker Client와 Docker Daemon 역할까지 하게 되어 도커 명령을 수행하는데 문제가 없어진다.

 

하지만, Docker 공식 입장은 DinD 사용하는 것을 권장하지 않는다.

단순하게 말하면, Host_container가 Host_machine에서 할 수 있는 거의 모든 작업을 할 수 있는 치명적인 결함이 있기 때문이다.

 

도커에서 사용하려면 실제 데몬을 동작시켜야 하기 때문에 도커 데몬에 추가 권한이 필요하다.

DinD 도커를 만들 때 명령을 살펴보면 --privileged 모드를 사용해 추가 권한을 부여하는 명령이 포함되어야 한다.

privilieged 플래그를 사용하면 Host_container가 Host_machine에서 할 수 있는 모든 작업을 할 수 있게 된다.

# docker run --privileged --name jadenpark_dind -d docker:19-dind

 

 


젠킨스에서 보는 dind

깃랩을 살펴보기 전에 젠킨스에서 개념을 간단히 알아보자.

 

젠킨스에서는 Docker를 사용하려는 경우 여러 옵션이 있다.

 

1. socket 마운트

2. 기본 이미지의 패키징 시스템을 사용하여 Docker CLI 설치

3. Docker API 사용

 

2, 3번은 해당 글에서 다루지않고, 대표적으로 사용하는 1번 방법을 소개하자면 아래 사진과 같다.

 

/var/run/docker.sock 파일이 로컬 시스템에서 도커 데몬과 통신할 수 있는 소켓 파일인데 이 부분을 Host_container에게 마운트하는 것이다.

따라서, 1번 방법은 Docker-in-Docker 처럼 느껴지지만 사실은 아니다.

컨테이너를 생성할 때 해당 컨테이너는 최상위 Docker에 생성되기 때문이다.

하지만, 소켓 마운트를 통해  Host_machine 엔진을 사용할 수 있는 것이다.

 

그래서, DooD 라고 따로 지칭하는 단어도 존재한다. (하지만, Gitlab 공식문서에서는 dind에서 dind방식과 소켓방식으로 나눠 설명한다.)


깃랩에서의 dind

 

깃랩 공식문서를 보면 3가지 방법으로 CI/CD 작업에서 docker 명령 활성화를 제공하고 있다.

 

1. 쉘 executor 를 사용하는 방법

2. dind 방법

3. 도커 소켓 바인딩 방법

 

(나는 가장 많이 사용하는 2번 방법을 사용했고 오류를 겪었다.)

2번 방법은 DinD의 개념과 부합하고

3번 방법은 DooD의 개념과 부합한다.

 

2번 방법은 gitlab-runner 버전 11.11 이상, docker 버전 19.03.12 이상이여야 사용이 가능하다.

깃랩과 도커 오피셜은 모두 최신버전 사용을 권장하기 때문에 지속가능한 dind 사용방법이라고 할 수 있다.

 

3번 방법은 Gitlab에서 사실상 지원이 끊겼다. (깃랩러너 11.11 버전 미만, docker 19.03.12 버전 미만의 경우만 사용가능) 

gitlab runner 오피셜Repo 에서 깃랩 러너 11.10 이하 버전은 관리대상이 아니다.

 


Gitlab runner 에서 마주한 에러

 

내가 사용한 .gitlab-ci.yml 파일이다.

stages:
  - build
  - deploy
  
variables:
  DOCKER_REGISTRY: 00000000000.dkr.ecr.ap-northeast-2.amazonaws.com
  APP_NAME: jadenpark
  DOCKER_HOST: tcp://docker:2375
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: ""
  GRADLE_OPTS: "-Dorg.gradle.daemon=false"

build:
  stage: build
  image: gradle:7.2.0
  extends:
    - .rules
  before_script:
    - export GRADLE_USER_HOME=`pwd`/.gradle
  script: gradle --build-cache assemble
  cache:
    key: "$CI_COMMIT_REF_NAME"
    policy: push
    paths:
      - build
      - .gradle
  
deploy:
  stage: deploy
  image: docker:19.03.12
  extends:
    - .rules
  services:
    - docker:19-dind
  before_script:
    - apk add --no-cache curl jq python3 py3-pip
    - pip install awscli
    - aws ecr get-login-password | docker login --username AWS --password-stdin $DOCKER_REGISTRY
    - aws --version
    - docker info
    - docker --version
  script:
    - docker build -t $DOCKER_REGISTRY/$APP_NAME:0.0.$CI_PIPELINE_IID .
    - docker push $DOCKER_REGISTRY/$APP_NAME:0.0.$CI_PIPELINE_IID
  cache:
    key: "$CI_COMMIT_REF_NAME"
    policy: pull
    paths:
      - build
      - .gradle

.rules:
  rules:
    - if: $CI_COMMIT_REF_NAME == "main"
      when: always
    - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"
      when: always
    - when: never

 

 

error during connect: Post http://dind:2375/v1.40/auth: dial tcp: lookup dind on 172.31.0.2:53: no such host

 

Docker 명령어 사용이 되지 않는것이다.

Deploy 실패를 하며 삽질을 시작했다.

 

이전까지는 Shared Runner 를 사용해서 따라하기 실습을 했기에 해당 문제를 운좋게 만나지 못했다. 

 

하지만, EC2 인스턴스에 gitlab-runner 를 띄워 Group Runner 를 등록/사용하며 문제를 겪었다. (Shared Runner 라고 모두 설정되어 있는 것은 아니더라), (runner 설정 방법은 이전 포스팅을 참고)

 

 

왜일까?

Gitlab-runner 등록 시 Executor로 지정한 Docker 의 privileged 플래그 Default가 False 이기 때문이다.

그러니, 당연히 도커 데몬에 대한 권한이 없기에 docker 명령어 사용이 되지 않는다.

 


해결방법

privileged 플래그를 True로 바꿔주면 된다.

이 작업을 활성화하면 도커 데몬에서의 --docker-privileged 가 활성화된다.

 

해결방법은 러너가 등록되지 않았을 때와 등록된 러너일 때 2가지로 나눴다.

1. 초기등록하는 러너라면

2. 기존등록된 러너라면

 

초기등록하는 러너라면

gitlab-runner를 초기 등록할 때 명령형으로 옵션을 추가해줄 수도 있다.

기존 등록했으면 등록된 러너를 모두 제거한 뒤 새로 등록하면 된다.

# 기존 등록된 러너 모두 제거

sudo gitlab-runner unregister --all-runners
# 명령형으로 gitlab-runner 등록 url과 token값은 각자 프로젝트에서

sudo gitlab-runner register -n \
  --url YOUR_URL \
  --registration-token YOUR_REGISTRATION_TOKEN \
  --executor docker \
  --description "My Docker Runner" \
  --docker-image "docker:19.03.12" \
  --docker-privileged

 

기존등록된 러너라면

config.toml 에서 privileged 플래그를 True으로 변경 후 gitlab-runner를 재시작하면 된다.

 

 


TLS 활성화가 필요하다면

만약, 추후에 TLS 활성화를 사용할 일이 있다면 각각 아래와 같이 수행.

sudo gitlab-runner register -n \
  --url YOUR_URL \
  --registration-token YOUR_REGISTRATION_TOKEN \
  --executor docker \
  --description "My Docker Runner" \
  --docker-image "docker:19.03.12" \
  --docker-privileged \
  --docker-volumes "/certs/client"

 

볼륨 마운트 경로에 미리 넣어 클라이언트가 해당 디렉토리 인증서를 사용하는데 필요한 서비스 및 빌드 컨테이너를 탑재해두는 것도 번거로움을 줄일 수 있는 방법이다.

 

추가로 TLS 활성화 시에는 .gitlab-ci.yml 에서 variables 값 DOCKER_TLS_CERTDIR: "/certs" 경로를 넣어주어야 한다.