애플리케이션과 그것이 돌아가는 데 필요한 라이브러리·설정을 하나로 묶어, 어느 기계에서든 같은 상태로 실행되게 하는 container 도구다.

같은 코드가 내 노트북에서는 되는데 서버에서는 안 되는 일은 대개 파이썬 버전, 시스템 라이브러리, 환경변수처럼 코드 바깥의 차이에서 온다. Docker 는 그 바깥까지 이미지에 담아버려서 차이가 생길 자리를 없앤다.

virtual machine 과의 차이

가상 머신은 guest OS 를 통째로 올린다. 커널부터 따로 돌기 때문에 격리가 강하지만 기동에 수십 초가 걸리고 메모리도 OS 몫만큼 더 쓴다.

container 는 host 커널을 그대로 공유하고, 프로세스를 격리된 것처럼 보이게 만드는 리눅스 커널 기능(namespace 로 파일시스템·네트워크·프로세스 목록을 분리하고, cgroup 으로 CPU·메모리 사용량을 제한)을 쓴다. 그래서 기동이 수백 밀리초 단위이고, 이미지 크기도 OS 전체가 아니라 필요한 사용자 공간 파일만큼이다.

대신 커널을 공유하므로 격리 수준은 가상 머신보다 약하고, host 와 다른 커널이 필요한 경우(리눅스 host 에서 윈도우 container)는 쓸 수 없다.

핵심 개념

용어
Dockerfile이미지를 만드는 절차를 적은 파일
image실행에 필요한 파일시스템 스냅샷. 읽기 전용이고 계층으로 쌓인다
container이미지를 실행한 상태. 이미지 위에 쓰기 가능한 계층 하나가 얹힌다
registry이미지를 올려두고 받아가는 저장소 (Docker Hub 등)

이미지가 계층으로 쌓인다는 점이 실무에서 중요하다. Dockerfile 의 각 명령이 한 계층을 만들고, 바뀌지 않은 계층은 다시 빌드하지 않고 캐시를 쓴다. 그래서 자주 바뀌는 명령(소스 복사)을 뒤쪽에, 잘 안 바뀌는 명령(의존성 설치)을 앞쪽에 두면 빌드가 빨라진다.

container 는 기본적으로 stateless 로 다룬다. 안에서 쓴 파일은 container 를 지우면 함께 사라지므로, 남겨야 하는 데이터는 volume 으로 host 나 외부 저장소에 연결한다.

여러 대를 다룰 때

container 하나를 띄우는 것과 수십 대를 굴리는 것은 다른 문제다. 어느 노드에 배치할지, 죽으면 어떻게 되살릴지, 트래픽을 어떻게 나눌지는 orchestrator 가 맡고, 사실상의 표준이 Kubernetes 다.

ML 서빙에서는 모델·프레임워크·CUDA 버전 조합이 제각각이라, 모델마다 이미지를 따로 만들어 배포하는 방식이 기본이 됐다.