Docker는 애플리케이션을 Container라는 독립된 환경을 실행하고 관리해주는 툴인데요. 독립된 환경이라고 했지만, 호스트 안에 거의 새로운 Linux 환경을 구축한다는 느낌을 받기도 하죠.
그래서 아래와 같은 질문이 나올 수도 있습니다.
Docker Container 안에 Docker를 설치해서 Host의 Docker를 사용할 수도 있지 않을까?
그렇게 나온 컨셉이 바로, ==Docker In Docker(DID)==입니다.
우리가 Docker를 설치할 때 Docker daemon과 Docker CLI가 함께 설치됩니다. 터미널 환경에서 docker build
, docker run
등의 명령어를 입력하면 Docker CLI가 명령어를 Docker daemon에게 전달해서 해당 동작을 수행하게 하는데요.
Docker CLI가 Docker daemon에게 명령어를 전달하는 과정에서 통로 역할을 하는 파일이 하나 있으니, 바로 docker.sock
입니다.
Docker와 함께 설치되는 docker.sock
파일의 기본 위치는 /var/run/docker.sock
인데요. Docker CLI에서도 해당 위치에 docker.sock
파일이 존재한다는 설정이 기본값으로 지정되어 있습니다.
이렇게 DID라는 개념을 설명드리기 전에 docker.socket
이라는 파일을 먼저 살펴본 것은, Docker In Docker(DID) 구현을 위해 docker.socket
파일을 활용할 예정이기 때문입니다.
위에서 Docker CLI가 Docker daemon에 Docker 명령어를 전달할 때 docker.sock
파일을 이용한다고 했었죠. 이는 곧 외부 Docker CLI가 docker.socket
에 접근할 수 있다면, 이와 연결된 Docker daemon에 명령어를 내릴 수 있다는 의미입니다.는 설정이 기본값으로 지정되어 있습니다.
이렇게 DID라는 개념을 설명드리기 전에 docker.socket
이라는 파일을 먼저 살펴본 것은, Docker In Docker(DID) 구현을 위해 docker.socket
파일을 활용할 예정이기 때문입니다.
위에서 Docker CLI가 Docker daemon에 Docker 명령어를 전달할 때 docker.sock
파일을 이용한다고 했었죠. 이는 곧 외부 Docker CLI가 docker.socket
에 접근할 수 있다면, 이와 연결된 Docker daemon에 명령어를 내릴 수 있다는 의미이기도 합니다.
DID를 사용하는 이유
CI/CD 파이프라인을 구축할 때 ==DID==를 활용하면 편한 경우가 있는데요. 쉬운 설명을 위해 Jenkins가 Docker Container로 동작하는 상황에서 Jenkins 파이프라인을 구성 중이라고 가정해볼게요.
파이프라인이 동작할 때 특정 스테이지에서 Docker Image를 빌드해야 하는 경우가 있을 수 있습니다. 하지만 파이프라인을 실행하는 Jenkins가 Docker Container 상에서 동작 중인 상황이기 때문에 우리는 해당 Container 내부에서 Docker Build 작업을 수행해야 합니다.
이때 위에서 설명한 ==DID 컨셉==을 이용한다면, Container 내부에 Docker CLI를 설치 후, 이미 호스트에 설치된 docker.sock에 접근하는 방식으로 호스트의 Docker daemon으로 Docker Build 작업을 수행할 수 있게 됩니다.
DID를 사용하는 방법
DID 컨셉을 활용하기 위한 가장 핵심은, Docker 명령어 실행이 필요한 컨테이너를 실행할 때 아래 옵션을 추가하는 것입니다.
docker run -v /var/run/docker.sock:/var/run/docker.sock ...
우리가 지금까지 가정했던 상황의 경우, Jenkins가 실행되는 Docker Container가 여기에 해당됩니다.
이 Container가 실행되는 기존 docker run 명령어에 위와 같이 호스트의 docker.sock
파일 경로를 Container 내부의 동일한 경로에 복사하는 -v
옵션을 추가하는 것인데요.
여기에 추가로 해당 Container 내부에 Docker CLI를 설치하면, Container 내 터미널 환경에서 docker 명령어를 바로 수행할 수 있게 됩니다.
DID 사용 시 생각해볼만한 점들
위에서 살펴본 것처럼, ==DID==는 Container 내부의 Docker CLI가 호스트에 설치된 Docker daemon을 사용합니다. 즉, ==Container 안으로 접근만 할 수 있다면 호스트의 Docker daemon을 제한 없이 사용==할 수 있는 것이죠.
만약 이를 외부에서 악용한다면 ==심각한 보안 이슈가 발생==할 수도 있는데요. 그렇기 때문에 DID를 사용할 때엔 Container 접근과 관련된 보안 설비가 충분히 구축되어야 안전하겠습니다.
이와 관련해서 컨테이너 런타임 보안에 대해 지난 글에서 다룬 적이 있으니 참고해보세요 :)