"Docker가 REST API를 이용한다는 글은 많이 봤는데, 솔직히 난 잘 이해가 안돼. 사실인지 알아보고싶어!"
시작하며
docker machine
과 docker swarm
등에 대해 공부하던 중 우연히 다시금 docker
의 구조에 대해 다시 생각해볼 시간을 갖게 되었고, 이에 저번 글에서는 docker가 server-client 구조를 갖는다는 점을 이용해 client가 원격으로 docker을 이용할 수 있다는 내용을 알아보았습니다. 이번엔 docker의 server와 client가 REST API를 이용해 통신한다는 내용에 대해 알아보겠습니다. 구글에 docker rest api
나 docker remote api
라는 키워드로 검색하면 몇 가지 글이 나오긴하지만, 이해를 명확히 돕는 눈에 보이는 자료들은 부족하다고 느껴져 정리해보겠습니다.
Docker daemon의 log를 통해 실제로 docker가 REST API를 이용하고 있음을 눈으로 확인해보는 내용의 글입니다. 이 글을 읽는 분들은 docker에 대한 어느 정도 개념이 있다는 전제하에 진행합니다.
작업 순서
작업순서는 크게 아래 네 가지 흐름으로 요약할 수 있습니다. 대부분의 작업은 root 권한으로 진행합니다.
- 원래 running 중이던
docker daemon
을 중지시키고foreground
모드(백그라운드가 아닌 실시간으로 로그가 보이는 모드)로 run 시킨다. - client가 직접
HTTP
Request를 통해 dockerAPI
를 이용해본다. - 전 편에서 다뤘듯이 docker daemon과 다른 host의 client에서 원격으로
docker cli
를 통해 docker command를 이용해 명령을 내려본다. - log가 같음을 확인한다.
원래 running 중이던 docker daemon을 중지시키고, foreground 모드로 docker daemon을 run 시킨다.
만약 현재 docker daemon(process 이름은 dockerd
)가 실행 중이라면, foreground로 dockerd
를 다시 실행할 때 에러가 발생합니다.
ps -ef | grep dockerd
를 통해 dockerd
가 실행 중인지 확인해볼 수 있습니다.
dockerd
가 실행 중일 때 foreground로 dockerd를 실행시키려하면 다음의 에러가 발생합니다.
root@ip-172-31-36-180:/home/ubuntu# dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --debug
INFO[2020-03-08T10:26:57.710749235Z] Starting up
failed to start daemon: pid file found, ensure docker is not running or delete /var/run/docker.pid
docker을 종료시키거나 /var/run/docker.pid를 지우랍니다.
docker을 종료하는 방법은 우분투 기준으로 systemctl stop docker.service
이고, docker.pid
를 지우는 방법은 말 그대로 해당 파일을 지워주면 됩니다.
/var/run/docker.pid
는 말 그대로 docker daemon의 process id
를 담고 있군요.
성공적으로 background에서 실행 중이던 dockerd를 중지시켰다면 ps -ef | grep dockerd
에서 dockerd process가 삭제되었을 것입니다.
원래는 systemctl start docker.service
를 이용해 dockerd를 background에서 돌렸지만 이번엔 실시간으로 로그를 확인해보기 위해 foreground에서 실행시켜보겠습니다.
dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --debug
좀 더 자세한 configuration은 Official docker docs 에서 찾아보실 수 있습니다. 간단히 내용을 말하자면, docker daemon을 foreground mode로 run하는데, 외부에선 tcp://0.0.0.0:2375
, 로컬에선 /var/run/docker.sock
을 이용하도록 하는 것입니다. 그리고 debug
옵션을 달아준 이유는 제가 확인하고 싶은 로그가 생략되지 않도록 하기 위함입니다.
Client가 직접 HTTP Request를 통해 docker API 이용해보기.
Docker docs endpoints
(https://docs.docker.com/engine/api/v1.24/)을 통해 다양한 docker API의 Endpoint
에 대한 내용을 참고할 수 있습니다. 방금 제시한 링크는 검색을 통해 나오는 api version 1.24 에 대한 documentation입니다. 하지만, 제가 직접 api를 이용해보니 version 1.40을 이용하길래 해당 documentation의 링크를 1.40으로 바꿔보았더니 좀 더 신 버전의 documentation도 존재하더군요. 필요할 시 참고하시면 되겠습니다.(https://docs.docker.com/engine/api/v1.40/) 저는 1.40 version의 api documentation을 참고했습니다.
documentation에 나온 API 명세 중 일부입니다. /containers/json이라는 endpoint를 통해 container의 목록을 받아올 수 있는 모양입니다. 그리고 Endpoint 자체에 대한 설명을 조금 참고해보자면 다음과 같습니다.
If you omit the version-prefix, the current version of the API (v1.40) is used. For example, calling /info is the same as calling /v1.40/info - docker engine docs
즉 현재 글을 쓰는 시점 기준으로는 endpoint에서 version을 생략하면 기본적으로 v1.40을 이용한다는 것입니다. 저는 그냥 /v.1.40/containers/json
이런 식으로 version을 명시시켜주겠습니다. 그럼 Postman을 통해 한 번 직접 HTTP
Request를 만들어보죠.
우와... 이게 진짜 되네..! 현재 container가 존재하지 않아서 빈 array가 리턴되긴했지만, 로그를 보니 요청이 성공적으로 들어왔고 response도 성공적으로 전달된 것을 알 수 있습니다. 그럼 이번엔 container을 생성하고 start 시켜본 뒤 다시 container의 list를 얻어와보겠습니다.
API v1.40에 대한 docs를 참고하여 HTTP Request를 보내어봤습니다.
http://13.125.221.179:2375/v1.40/containers/create?name=nginx-container
는 container 을 create 할 뿐 start 시키진 않습니다.
아까 foreground로 실행시켜놓은 docker daemon에도 log 가 성공적으로 적힌 것 같습니다. 로그의 앞에 DEBUG
라는 Prefix가 적힌 것을 보아 dockerd command를 실행헀을 때 --debug
옵션을 주지 않았더라면 보지 못했을 로그임을 알 수 있습니다.
response로 얻은 Id
를 이용해 http://13.125.221.179:2375/v1.40/containers/701572c0dd534757134da87ff8a78ec91229523d25ce9ee07f4eca601a14417e/start
으로 container을 start 시킵시다. start API는 별다른 response가 없군요. 이제 다시 한 번 container list를 얻어오는 API를 이용해보겠습니다. 방금 만든 nginx container가 존재한다면 좋겠네요!
감동의 도가니입니다..!! 다른 내용은 생략하였습니다만 아까 저희가 query로 전달한 name=nginx-container
인 컨테이너가 생겨났군요!! 실제로 동작한 지 확인하기 위해서 docker daemon과 같은 host 내에서 docker command 를 이용해 container을 조회해보겠습니다.
docker cli를 통해 command를 수행하는 것과 HTTP Request를 보내는 것은 같은 작업이다.
자, 방금 한 작업에서 우리가 확인할 수 있는 중요한 점이 있습니다. 몇 번 요청을 보내고 command를 수행하면서 로그를 보시면 알게되시겠지만 바로 docker cli 또한 우리가 http request를 만들었던 것과 동일하게 API를 이용한다는 점입니다.
docker ps
와 /v1.40/containers/json
요청 모두 동일한 작업입니다. 즉 우리(저만 간과하고 있었던 것일 수도 있어용ㅎㅎ;;)가 간과하고있었으나 docker cli는 내부적으로 docker API를 이용하고 있었던 것임을 로그를 통해 눈으로 확인할 수 있는 것입니다.
이점, 보완할 점
docker
가 REST API
를 이용한다는 내용을 여기저기서 주워듣기도 해보았고, 이래저래 설명을 하는 글을 보기도 했지만, 내용이 직관적이지 않았고, 실제로 docker cli가 REST API를 이용하고 있는것인지 확인할 수 있는 내용은 찾기 힘들었는데, 이번에 로그를 직접 보면서 좀 더 명확히 이해할 수 있게된 듯 합니다.
이 내용을 통해 별도의 agent를 이용하는 Deploy pipeline을 이용하지 않더라도 docker REST API
를 이용해서도 deploy를 진행할 수도 있을 것 같습니다. (하지만 대부분의 경우 agent나 deployment tool 이용하는 게 편해보이긴합니다.)
보완할 점은 현재는 어떤 client라도 expose된 IP:Port를 통해 docker API를 실행할 수 있도록 설정되어있기 때문에, 혹시라도 실제로 사용하시게 된다면, docker REST API를 이용할 수 있는 client IP를 제한하거나 인증과정을 추가하는 등을 통해 보안적 이슈를 조금 신경써줘야할 듯합니다.
'Linux > Docker' 카테고리의 다른 글
docker daemon 설정을 이용해 원격으로 docker 이용하기 (0) | 2020.03.08 |
---|---|
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 |