ODM(Open Drone Map) 라이브러리 사용과 Object Detection & Semantic Segmentation 추론 모델을 위해 Docker의 Remote API에 대한 개념 이해가 필요했다. 이들은 모두 Docker 컨테이너를 통해 실행되기 때문이다. 이와 함께 dockerode 라이브러리를 사용해서 원격 서버에서 Docker 컨테이너를 실행하는 작업을 해보았다.
Docker가 설치되어 있지 않은 로컬 PC에서도 외부 서버의 Docker를 사용하는 방법이다. Remote API를 통해 원격으로 Docker daemon에서 Docker 명령을 실행할 수 있다.
Docker CLI로 흔히 사용하는 run, start, stop, ps, exec 등의 명령어들은 로컬의 Docker만 제어할 수 있다. 도커는 이처럼 하나의 서버에 client와 daemon을 함께 구성하거나 서로 다른 서버에 위치할 수 있다. 같은 서버에서 통신할 때는 UNIX 소켓을 사용하지만, 각각 다른 곳에 있으면 TCP 소켓을 이용해 원격으로 커맨드를 주고받는다.
Remote API의 종류는 도커 명령어의 개수만큼 있으며, API에 따라 사용하는 방법이 도커 명령어와 조금씩 다른 부분도 있으므로 HTTP 도구로 직접 API 요청을 전송하기보다는 특정 언어로 바인딩 된 라이브러리를 사용하는 것이 일반적이라고 한다.
(참고: 시작하세요! 도커/쿠버네티스)
원격 서버의 Docker를 제어하기 위해 나의 로컬 PC에서 remote 설정을 해야 한다는 생각에 사로잡혀 초반에 시간을 많이 잡아먹었다. 관련된 포스트를 모두 찾아보다가 ‘다른 컴퓨터에서 원격으로 이용할 것이니 TCP 소켓을 열어준다.’
라는 문장을 보고 회사 서버로 들어가 TCP를 열어줄 생각을 하게 되었다.
ps aux | grep docker ## dockerd 확인
sudo service docker stop
sudo dockerd -H tcp://0.0.0.0:연결포트4자리 -H # Docker의 localhost - 0.0.0.0 unix:///var/run/docker.sock # 배포 서버 IP에서 TCP 포트 열어주기
failed to start daemon: pid file found, ensure docker is not running or delete /var/run/docker.pid
docker를 종료하거나 pid 파일 삭제하라는 에러가 나와 삭제하고 재진행했다.
다른 방법
sudo systemctl stop docker ## 도커 컨테이너 정지
sudo vi /lib/systemd/system/docker.service ## docker.service 설정 파일 아래처럼 수정
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:연결포트4자리 --containerd=/run/containerd/containerd.sock
## 도커 시작
sudo systemctl daemon-reload
sudo systemctl start docker
## Remote API 확인
curl http://127.0.0.1:연결포트4자리/version
import Docker from 'dockerode';
...
constructor(private configService: ConfigService) {
this.docker = new Docker({
host: process.env.REMOTE_DOCKER_HOST,
port: process.env.REMOTE_DOCKER_PASSWORD,
});
}
...
// 도커 이미지와 버전을 받아 실행하는 Service dockerode 로직
async dockerRun(name, version) {
try {
await this.docker.run(
`${name}:${version}`,
['-e', 'TZ=Asia/Seoul'],
process.stdout,
{
AttachStdin: true,
AttachStdout: true,
AttachStderr: true,
Cmd: ['컨테이너 실행에 필요한 CMD 옵션들'],
HostConfig: {
Binds: [process.env.BIND_SOURCE],
AutoRemove: true,
IpcMode: 'host',
DeviceRequests: [ // gpu 사용을 위한 도커 컨테이너 설정
{
Driver: 'nvidia',
DeviceIDs: ['서버 인덱스 번호'], // Count 옵션과 공존할 수 없다.
Capabilities: [['gpu']],
},
],
},
},
);
} catch (err) {
this.logger.error(err);
}
}