시작하며 (이건 스킵하셔도됩니다. 거의 일기장 수준...)
docker client
와docker daemon
이 같은machine
에 존재하지 않더라도docker client
를 통해 원격으로 docker를 이용할 수 있다는 내용의 글입니다.
이 글을 읽으시는 분들은docker
에 대한 어느 정도 개념이 있다는 전제하에 글을 적습니다.
Docker
를 처음 접했던 건 2019년 봄. 경희대학교는 특이하게 데이터센터 프로그래밍
이라는 과목을 통해 Docker
와 Kubernetes
를 배울 기회가 주어집니다.(데이터센터 프로그래밍 소개 영상)
당시 컨테이너 관련한 내용은 전무했던 제게 Docker는 너무 재미있는 기술이었습니다. 하지만 많이 어려웠던 것도 사실이었습니다.
Docker, Container을 비롯해 애초에 Web이니 REST API니 Server-Client니 하는 내용들조차 제대로 알지 못하던 상태였기에 다 이해하지 못하고 넘어갔던 부분들이 있었습니다. 그 중 가장 이해가 안 되었던 것이 두 가지 있었습니다.
'나는 그냥 내 컴퓨터에서 도커를 깔아서 쓰고있는데, 왜 도커가 Server-Client 구조의 Application이라는거야?'
'난 HTTP를 이용한 API를 이용한 적이 없는데, 왜 도커가 REST API를 이용한다는 거야?'
이 두 가지 의문이 낳았던 또 다른 궁금증은
'그래 다 이해했다치고, 그럼 Server랑 Client가 떨어져있어도 Client가 Server에게 REST API를 이용해서 원격으로 docker을 이용가능하다는 거야?'
이였고, 교수님께 여쭤보았습니다.. 당시 수업을 맡으셨던 교수님 상당히 스스로 문제해결하는 방법을 찾는 능력을 중시하는 분이셨고, '오! 그 내용은 학생이 한 번 찾아볼래요? 아마 되겠죠? 근데 궁금하긴하네요' 라는 답변을 얻었으나, 당시의 저는 답을 찾을 수 없었습니다 ㅜㅜ.....
그렇게 해당 내용이 머릿 속에서 지워져갈 쯤, docker machine
을 이용하면 원격으로 docker command
를 이용할 수 있다는 내용으로부터 '아 맞다 옛날에 server/client 구조를 통한 원격 docker 사용이 되나 궁금했는데'하는 생각이 들었고, 1년간 열심히 공부하며 성장한 것인지, 어렵지 않게 답을 얻을 수 있었습니다.
(진짜로) 시작하며
다른 블로그 등에도 모두 정리되어있는 내용이지만 이해를 돕기 위해 다시 한 번 정리하며 간단히 결론부터 요약하자면
- docker는 server/client 구조로 이루어져있다.
- docker command는
HTTP
라는 프로토콜을 이용하는REST API
이다.예를 들어 우리가 그냥 사용하던docker ps
는 docker server의GET /api-version/containers
으로 HTTP 요청을 보낸 것과 동일한 방식이다. - 보통은 docker daemon(server)와 client가 같은 machine 내에 존재한다.
하지만 설정을 통해 Client가 원격으로 Server에 docker command을 전달할 수 있다.
이번 글에서는 Client가 원격으로 Docker을 이용해보는 내용을 다룰 것입니다. 다음 글에서는 REST API를 이용하는 지에 대한 증거(log)를 확인해보는 작업을 다룰 것입니다.
작업은 AWS EC2 Ubuntu 18.04를 기준으로 이루어졌습니다.
용어정리
우선 docker host
, docker daemon
, docker engine
등 헷갈리는 용어가 많기 떄문에 간단히 정리를 하고 넘어가겠습니다.
주관적인 해석을 해보자면, docker host
란 docker daemon을 실행하고, 실제로 image를 저장하고 container을 돌리는 machine을 의미
docker daemon
은 client에게 받은 docker command
(api)를 실행하여 host machine에서 container을 실행시키거나 image 를 pull/rm하는 등의 명령을 내리는 프로그램
docker engine
의 경우 Official Docker docs에 의하면 client/server(docker daemon) application 통틀어 docker engine이라고 한답니다.
서버-클라이언트 구조의 Docker
official docker docs에 제시된 그림입니다. 수없이 많이 이 그림을 보았지만, 늘 의문이었고 이제야 이해가 됩니다. 보통은 Client와 Server가 한 machine에 붙어있고 우리 눈에는 REST API
를 이용중이라고 느껴지지 않죠.
다만 이 글의 주 내용을 통해 알 수 있듯, Client와 Server(docker daemon)은 같은 host에 존재할 필요도 없고, 따라서 remote server에게 REST API
를 통해 명령을 보낼 수 있습니다. 이 때 http 요청 자체를 보낼 수도 있고 docker command를 이용할 수도 있죠. 우리는 주로 docker command를 이용해왔지만, 이것은 docker cli를 통해 REST API
를 이용한 셈입니다.
이 내용은 다음 글에서 좀 더 자세히 다뤄볼 생각이에요.
Host의 docker daemon 설정하기
이제 실제로 원격 docker daemon에게 client가 명령을 내리기 위한 작업을 시작해봅시다.
/lib/systemd/system/docker.service
의 내용입니다. 기본적으로는 dockerd(docker daemon)을 이용할 때 containerd.socket을 이용하는 모양이네요.(이부분은 확실치않음..)
Quora-Docker Engine & Docker Daemon에서는 기본적으로 도커엔진은 2376번 포트를 이용한다고 적혀있지만, 도커를 이용하더라도 netstat -ntlp
를 통해 열린 port를 찾아봐도 도커 데몬이 이용하는 포트를 찾을 수 없는 경우가 많았습니다.(앞의 글이라 그런 건지 왜 그런 건진 모르겠지만, 어쨌든 local에서는 unix socket을 이용해 통신하고, 네트워크 통신을 할 때에는 tcp socket을 이용한다고 합니다. - 참고http://pyrasis.com/book/DockerForTheReallyImpatient/Chapter14)
/lib/systemd/system/docker.service
에서 ExecStart=
부분을 아래와 같이 바꾸어줍시다.
dockerd
는 docker daemon
, -H
는 host로서 자신이 docker daemon의 호스트로서 이용할 IP와 Port을 적어준다. 아래의 코드는 0.0.0.0:2375를 Host로서 docker daemon을 실행하도록 하는 코드입니다.
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H 0.0.0.0:2375
그리고 변경사항을 적용시켜줍시다. 0.0.0.0:2375는 원격 통신을 할 때 사용하는 호스트이고, unix socket은 local 통신을 할 때 사용하는 socket입니다.
sudo systemctl daemon-reload
sudo systemctl restart docker.service
만약 unix socket을 적어주지 않으면 local에서는 docker command가 제대로 작동하지 않고, IP와 Port를 적어주지 않으면 원격에서 docker command가 제대로 작동하지 않습니다. 아래의 명령어를 통해 변경사항을 적용시켜줍시다.
저의 경우는 AWS EC2 Instance를 이용했기때문에, Security Group
에서 제가 설정한 포트인 2375번
포트를 Inbound
에서 허용시켜줘야했습니다. 일반 Laptop을 이용해서 사용하실 경우 방화벽
이나 포트바인딩
문제로 번거로워질 수 있습니다.
docker daemon
을 설정하는 방법은 https://serverfault.com/questions/843296/how-do-i-expose-the-docker-api-over-tcp 와 Docker docs - Daemon socket option에도 참 잘 나와있습니다.
저는 docker.service에서 host를 직접 적어준 것이고, 다른 한 가지 방법은 daemon.json이란 파일에 host를 적어주는 방법이 있었습니다.
-H unix://...
이외에 fd://
를 이용하는 방법도 바로 위의 Docker docs 링크에 제시되어있습니다.
sudo systemctl restart docker.service
에서 오류가 안났다면 아마 잘 설정되었을 것입니다.
원격으로 docker daemon에게 명령 보내기
docker 가 깔려있는 다른 네트워크 환경의 PC에서 방금 설정한 서버에게 명령을 보내보겠습니다.
0.0.0.0:2375로 docker daemon의 host를 설정하였지만 0.0.0.0
은 자신이 가진 네트워크에 따라 여러 IP를 나타낼 수 있습니다. 저의 경우 15.164.172.173 이라는 IP가 Public IP로 존재하므로 클라이언트는 이를 통해 접속이 가능합니다.
docker --help를 통해 알아보니 -H
를 이용해 연결할 host를 설정하라는 군요.
docker -H {DOCKER_HOST_IP} images
을 입력해봅시다.
이럴수가..!! 저만 신세계인건가요..? 너무도 쉽게 원격으로 docker daemon을 이용할 수 있나봅니다.
믿기지 않으니 한 번 실제로 원격의 client를 이용해 nginx container을 run 시킨 후 접속해보죠.
docker -H {DOCKER_HOST_IP} run -d -p 80:80 --rm --name nginx-container nginx
(AWS를 이용할 경우 Security groups에서 80번 포트에 대한 Inbound를 허용해주어야합니다.)
위의 사진을 Client가 원격으로 docker daemon에게 ps 명령을 보낸 모습이고,
아래 사진은 docker daemon과 같은 machine에 있는 client가 명령을 보낸 모습입니다.
동일한 결과를 얻을 수 있습니다!!!!
저만 감동인가요 이 내용들..? ㅜㅜ
환경변수를 통한 Docker host 설정
여기서 팁 추가! 환경변수
를 이용하면 좀 더 간단하게 docker를 원격으로 이용할 수 있습니다.
DOCKER_HOST
라는 환경변수를 설정해주면 됩니다.
환경변수를 설정해주면, 환경변수가 유효한 동안은 -H
옵션 없이 편하게 바로 원격으로 docker command를 이용할 수 있습니다.
Alias를 통한 Docker host 설정
이 내용은 docker host를 다루는 어디에서도 못 본 내용인데,
docker-compose
를 이용할 때 alias를 이용했던 것이 생각나서 제가 적어봅니다.
alias
를 이용하면 자주 쓰는 명령어들을 편리하게 사용할 수 있는데요. 이 방법은 사실 거의 Docker geek만을 위한 것일 것 같습니다...
~/.bashrc에서 alias를 설정하고 source ~/.bashrc를 통해 적용해줍시다.
(마지막 줄만 보면 됩니다.) 저는 docker ec2라는 의미에서 dec2를 적어보았습니다.
한 번 여러가지 docker command를 시도해보겠습니다.
사진과 같이 잘 작동하네요. 신기신기!!!!! >_<
마치며
묵혀왔던 궁금증을 해결한 탓에 너무 흥분해서 주절주절 적은 건 아닌가싶기도하네요. 오늘 하루의 탐구 덕에 도커에 대해 좀 더 알아갈 수 있었던 것 같아 기분이 좋습니다.ㅎㅎ
사실 그냥 Dockerfile
을 만들고 port binding
만해서 사용하면 누구나 금방 익힐 수 있지만, 이런 deep한 내용도 알면 분명히 다른 기술이나 좀 더 어려운 내용을 접할 때 도움이 될 것이라고 생각합니다.
너무너무 deep하고 흐름을 방해하는 내용들은 약간 생략한 부분도 있고 제가 잘 모르는 부분도 있긴합니다.
예를 들면 unix socket이나 fd://에 대한 내용 등등... 혹시 간략하게 댓글로 설명해주실 분이 계시다면 환영이고, 혹시 저 같은 궁금증을 갖고 계셨던 분이 계시다면 이 글이 도움이 되었으면 좋겠습니다~~
다음 편에서는 docker 가 REST API를 사용하는가에 대해 적어보겠습니다.
참고
각종 도커 documentation-https://docs.docker.com/engine/docker-overview/
가장 빨리 만나는 Docker 14장 Docker Remote API 사용하기-http://pyrasis.com/book/DockerForTheReallyImpatient/Chapter14
docker daemon이란-https://www.quora.com/What-is-the-difference-between-the-Docker-Engine-and-Docker-Daemon
docker daemon 설정법, expose 시키는 법-https://serverfault.com/questions/843296/how-do-i-expose-the-docker-api-over-tcp
'Linux > Docker' 카테고리의 다른 글
Docker가 REST API를 이용함을 확인해보자 (0) | 2020.03.09 |
---|---|
Docker 를 이용해 가장 간단하게 다양한 가상환경에서 작업하기 (0) | 2019.09.08 |
Dockerfile의 CMD와 ENTRYPOINT 차이. docker-compose.yml의 command (0) | 2019.08.26 |
[Docker] Docker 시작하기. 예제를 하나 만들고 실행해보자 (0) | 2019.03.16 |
[Docker] Docker 시작하기. Docker란? Docker와 Container의 개념에 대하여 (0) | 2019.03.16 |