Docker 컨테이너는 일종의 소프트웨어 패키지이기 때문에 컴퓨터 간에 자유롭게 복사하고 이동할 수 있습니다. 하지만 이 주제는 자주 다뤄지지 않는데, 아마도 규모가 큰 조직들은 자체 저장소(repository)를 구축해 이미지를 직접 커스터마이징하고 서버에 배포하기 때문일 것입니다. 그러나 가끔 한두 개의 컨테이너만 옮기면 되는 상황에서 굳이 자체 배포 체계를 구축할 필요는 없습니다.
로컬 컴퓨터에서 작업하던 Docker 인스턴스를 더 강력한 서버로 옮기고 싶을 수도 있고, 커스터마이징한 컨테이너를 여러 대의 컴퓨터에 "복사해서 붙여넣듯" 배포하고 싶을 수도 있습니다. 또는 클라우드 제공업체가 마음에 들지 않아 다른 곳으로 이전하려는 경우도 있겠죠. 어떤 상황이든 아래에서 소개하는 비교적 간단한 절차를 따르면 됩니다.
소스 호스트에서 컨테이너 이미지 저장하기
컨테이너를 먼저 중지해야 하는 것은 아니지만, 중지하는 것을 강력히 권장합니다. Docker 인스턴스의 데이터 스냅샷을 생성하는 작업인데, 실행 중인 상태에서 진행하면 일부 파일이 불완전한 상태로 스냅샷에 담길 가능성이 있습니다. 예를 들어 누군가 500MB 파일을 업로드하는 도중 250MB가 전송된 시점에 docker commit 명령을 실행했다고 가정해 봅시다. 업로드는 계속되지만, 나중에 다른 호스트에서 이 Docker 이미지를 복원하면 500MB 중 250MB만 존재하게 될 수 있습니다.
따라서 가능하다면 먼저 인스턴스를 중지하세요.
docker stop NAME_OF_INSTANCE
Docker 컨테이너는 범용 초기 이미지를 기반으로 만들어집니다. 시간이 지나면서 이 베이스 이미지 위에 여러분의 변경 사항이 추가되고, 컨테이너 내부에서 실행 중인 프로세스들이 데이터를 저장하거나 다른 변경을 가하기도 합니다. 이 모든 것을 보존하려면 현재 상태를 새 이미지로 커밋(commit)하면 됩니다.
인스턴스가 실행 중이라면 이 작업이 진행되는 동안 일시적으로 멈춥니다. 컨테이너에 많은 데이터가 쌓여 있다면 완료까지 오래 걸릴 수 있습니다. 이러한 일시 중지를 피하고 싶다면 다음 명령 대신 docker commit -p=false NAME_OF_INSTANCE mycontainerimage를 사용하면 됩니다. 하지만 정말 필요한 경우가 아니라면 사용하지 마세요. 이 경우 데이터가 불일치하거나 불완전한 이미지가 생성될 확률이 높아집니다.
이 튜토리얼에서는 결과 이미지 이름으로 mycontainerimage라는 일반적인 이름을 사용했습니다. 원하는 이름으로 바꿔도 되며, 그럴 경우 이후 등장하는 모든 명령에서 해당 이름을 바꾸는 것을 잊지 마세요.
docker commit NAME_OF_INSTANCE mycontainerimage
이제 이 이미지를 파일로 저장하고 압축합니다.
docker save mycontainerimage | gzip > mycontainerimage.tar.gz
다음으로 선호하는 파일 전송 방식을 사용해 mycontainerimage.tar.gz 파일을 컨테이너를 마이그레이션할 호스트로 복사합니다.
대상 호스트에서 컨테이너 이미지 불러오기
이미지를 전송받은 호스트에 로그인한 후 Docker로 가져옵니다(import).
gunzip -c mycontainerimage.tar.gz | docker load
이 컨테이너를 해당 호스트에서 초기화한 적이 없으므로 docker start로는 시작할 수 없습니다. 대신 처음 이 Docker 인스턴스를 실행했을 때 사용했던 것과 동일한 명령을 입력하되, 끝부분의 이미지 이름만 "mycontainerimage"로 바꾸면 됩니다.
다음 명령은 단순한 예시입니다. 상황에 맞지 않다면 그대로 복사해서 붙여넣지 마세요. (처음 이미지를 실행했을 때 특별한 매개변수가 필요하지 않았던 경우)
docker run -d --name=PICK_NAME_FOR_CONTAINER mycontainerimage
반면, 호스트 머신의 80번 포트를 컨테이너의 80번 포트로 포워딩하기 위해 --publish 매개변수가 필요했던 경우의 명령 예시는 다음과 같습니다.
docker run -d --name=http-server --publish 80:80 mycontainerimage
이후에는 docker stop과 docker start 명령으로 컨테이너를 평소처럼 중지하고 시작할 수 있습니다.
파일 생성 없이 이미지 전송하기
mycontainerimage.tar.gz 파일을 만드는 과정을 생략하고 싶을 때가 있습니다. 컨테이너에 데이터가 많아 디스크 공간이 부족한 경우가 대표적입니다. 다음 명령 하나로 이미지를 저장, 압축, 전송, 압축 해제, 로드까지 모두 처리할 수 있습니다. 앞서 설명한 docker commit 명령을 실행한 후 아래 명령을 사용하세요.
docker save mycontainerimage | gzip | ssh root@203.0.113.1 'gunzip | docker load'
Windows에도 이제 기본 SSH 클라이언트가 내장되어 있으므로(더 이상 PuTTY가 필요 없음) Windows 환경에서도 정상적으로 작동합니다.
이후에는 상황에 맞는 docker run 명령으로 마무리하면 됩니다.
결론
docker save와 docker load는 컨테이너를 가끔씩 옮겨야 할 때 유용한 임시방편입니다. 하지만 이런 작업을 자주 수행한다면 자체 프라이빗 저장소(private repository)를 구축하는 편이 좋습니다.
이미지 출처: Air Force Medical Service