도커를 사용하다 보면, 아무런 태그가 달리지 않은 <none>:<none> 같은 이미지를 흔하게 볼 수 있습니다. 이런 이미지는 눈에 거슬리기도 하고, 사용하지도 않기 때문에 보이는 족족 삭제를 하고 있습니다. 그런데 조금만 넋 놓고 살다 보면 그런 이미지들이 한가득 있는 것을 보고, 한 숨을 쉬곤 합니다. 이런 이미지들은 왜 생기는 것이며, 어떻게 하면 쉽게 삭제할 수 있을까요?
우선 시작하기 전에 hello-world 이미지를 만들어보겠습니다. ( https://github.com/docker-library/hello-world ) 리파지토리를 클론 하고, 도커 이미지를 만들어 줍니다.
$ git clone https://github.com/docker-library/hello-world
$ cd hello-world
$ docker build -f Dockerfile.build -t hello-world .
빌드가 완료되면 hello-world 이미지가 만들어진 것을 확인할 수 있습니다.
그런데 이게 끝이 아니예요. "docker images -a"로 이미지를 확인해보면, 방금 만들어진 두 개의 이미지 말고도 달갑지 않은 <none>:<none> 이미지가 여러 개 생성된 것을 볼 수 있습니다.
도커 이미지는 여러개 레이어로 이루어져 있는데, 이 레이어는 서로가 층층이 쌓인 관계를 가집니다. 그리고 이 레이어는 graph 데이터베이스에 저장됩니다. 방금 만들어진 hello-world:latest 이미지는 debian:buster-slim 이미지를 시작으로 16개의 레이어로 이루어진 것을 알 수 있습니다. 여기서 <none>:<none> 이미지들은 hello-world를 만들기 위한 중간 이미지( intermediate image )로써, 이미지를 만드는 과정( 또는 docker pull을 통해서 받아오는 과정 )에서 만들어집니다. 실제로 역할을 하지는 않고, Disk를 차지하지도 않지만, 눈에 거슬리고, ID가 다른데도 이미지명과 태그가 동일하기에 구별도 되지 않습니다.
다행히도 모두 보기("-a")를 하는 경우에만 볼 수 있습니다. 아직까지는...
이번에는 DockerHub에 올라온 hello-world:latest 이미지를 받습니다. 그리고 다시 pull 된 이미지를 확인해봅니다.
$ docker pull hello-world:latest
$ docker images
아까 만들었던 hello-world:lastes가 <none>:<none>으로 바뀌었고, hello-world는 새로 내려받은 이미지에 붙어있습니다. 새로 내려받은 이미지와 아까 만들었던 이미지는 서로 아무런 관계도 없습니다. 그래서 929MB의 공간은 아무런 역할도 하지 않고 차지하는 공간이 돼버렸습니다. 이렇게 다른 곳에서 참조하지 않는 이미지를 Dangling Image라고 합니다. 프로그램에서는 이렇게 아무도 사용하지 않는 메모리가 발생하면 Garbage Collector가 주기적으로 삭제해서 공간을 확보합니다. 하지만 Docker에서는 그렇지 않습니다.
그래서 직접 삭제를 해줘야 합니다. 이미지 삭제는 docker rmi를 사용하면 되고, <none>:<none>을 적을 순 없으므로 ID를 적어줍니다.
$ docker rmi 30021576c6bd
그런데 이런 이미지가 한 두개가 아니라면 명령을 반복해서 수행하거나, Image id를 여러 개 넘겨주어 한꺼번에 삭제할 수 있지만 prune을 이용하면 더 쉽게 할 수 있습니다.
$ docker image prune
images가 아니고 image 임에 유의해야 합니다. ( 제가 자꾸 헷갈려해요 ) prune을 하고 나면 Dangling이미지 전체를 삭제한다고 하고 y라고 응답하면 모든 이미지를 삭제합니다. 아까 만들었던 이미지 중 860Mb가 삭제되었습니다. 929Mb가 삭제되어야 하지 않냐고 의문을 가질 수 있지만 docker-hub로부터 내려받은 hello-world:latest 이미지도 debian:buster-slim이미지와 관계가 있기 때문에 그 용량을 빼면 ( 929-69= ) 860Mb만 삭제되는 것이 이해가 될 것입니다.
지금까지 중간 이미지로 생성된 <none>:<none> 이미지와 동일한 이름과 태그를 사용하는 이미지가 생길 때 ( build or pull ) 생기는 <none>:<none> 의 차이에 대해서 알아봤고, Docker는 가비지 콜렉터가 없으므로 사용자가 직접 삭제해 줘야 하며 삭제하는 방법도 알아봤습니다.