단순히 도커를 이용해 이미지를 만들고 띄우는 개발자라면 docker client와 docker daemon이 분리되어 있는 것을 인지하지 못할 수 있다. 반면 CI(Continuous Integration/지속적 통합)툴을 사용하며 agent를 세팅하는 DevOps쪽 개발자라면 docker관련 task를 수행하면서 이 사실을 쉽게 접하게된다.
그림처럼 docker시스템 유닛은 크게 3개로 분리되며, Client, Host(Daemon), Registry가 그것이다.
대부분의 현대 CI 도구들(travis, circle, gocd, jenkins)등이 agent를 통해 docker관련 Task를 수행을 하기 때문에 docker daemon은 호스트머신에서 동작하면서 컨테이너로 동작하는 agent들이 docker-client역할을 하는 경우가 많다. 그래서 데브옵스 개발자들은 쉽게 daemon과 client의 분리를 고려하며 docker container에서 agent가 호스트 머신에 위치한 docker daemon에게 어떻게 도커 명령을 전달해야할지 고민하게된다.
Docker측에서는 Docker 컨테이너 위에서 도커명령을 실행하는 것을 권장하지 않았다.
그리고 더 나아가 client를 분리해서 사용하는 것에 대해서 통합하는 방향으로 가닥을 잡았다.
docker 설치가이드 문서들을 살펴보면 설치 전에 old version을 uninstall할 것을 오더하고있다. old version은 docker-client와 docker-engine이 확실하게 분리되어 있었다.
<docker-ce로 통합된 최신 도커를 사용할 것을 권장하고있는 공식 doc>
도커 안에 도커는 도커 바이너리를 설정하고 컨테이너 내부의 격리된 Docker 데몬을 실행하는 작업을 의미한다. 즉, 도커데몬이 2개가 뜨는 것이다. CI측면에서 접근한다면 Task를 수행하는 Agent가 Docker Client와 Docker Daemon 역할까지 하게되어 도커 명령들을 수행하는데 문제가 없어진다. 이렇게 말로만 들으면 아름답고 문제가 없어보이지만 이 접근에는 큰 단점이 존재한다.
호스트 도커 컨테이너가 privilieged mode로 실행되어야 한다.
$ docker run --privileged --name dind1 -d docker:1.8-dind