LainyZine: 프로그래머 가이드 🐣

docker rmi 사용법: Docker 이미지를 삭제하는 방법

Docker 작업을 하다보면 컨테이너와 함께 Docker 이미지도 로컬에 계속 쌓여갑니다. 많으면 수십 수백개의 컨테이너 이미지와 레이어가 로컬에 쌓이고 디스크도 많이 차지합니다. dockre images -a로 현재 사용하지 않는 이미지나, dangling된 이미지를 확인해볼 수 있습니다.

$ docker images -a
REPOSITORY         TAG                IMAGE ID       CREATED        SIZE
nginx              alpine             a64a6e03b055   13 days ago    22.6MB
nginx              1.19               62d49f9bab67   2 weeks ago    133MB
nginx              latest             62d49f9bab67   2 weeks ago    133MB
<none>             <none>             8cf995c0ce5d   6 months ago   893MB
...

컨테이너와 달리 이미지는 용량만 차지할 뿐, 상시적으로CPU나 메모리를 사용하는 것은 아닙니다. 하지만 디스크도 무한한 자원이 아니고, 로컬 이미지가 많으면 관리가 어려워지기 때문에 사용하지 않는 이미지들은 미리 삭제해두는 것이 좋습니다.

docker rmi: Docker 이미지 삭제 명령어

docker rm이 Docker 컨테이너를 삭제하는 명령어라면, 이미지를 삭제하는 명령어는 docker rmi입니다. 여기서 rmremove, i는 이미지의 줄임말입니다. 예를 들어 nginx:alpine 이미지를 삭제하고 싶다면 docker rmi nginx:alpine 명령어를 실행해줍니다.

(아래 예제에서는 nginx:alpine 이미지가 이미 pull 되어있다고 가정합니다.)

$ docker rmi nginx:alpine
Untagged: nginx:alpine
Untagged: nginx@sha256:07ab71a2c8e4ecb19a5a5abcfb3a4f175946c001c8af288b1aa766d67b0d05d2
Deleted: sha256:a64a6e03b0551e1cefa94db6cc6677fb1efed3c557d173f79584ff4ec474b5ae
Deleted: sha256:d950b497e5a0787af1b4a04e0298b693501d756b610b09e5501bc0d1feb02465
Deleted: sha256:01270ad0039edf3793b69b5374505aad02fc2e4464f460215a803fa728eaef8c
.....

출력 결과를 보면 먼저 Untagged 작업이 이루어집니다. 이는 컨테이너 이름과 마찬가지로 이미지 이름도 이미지 ID에 붙여둔 별칭이기 때문입니다. 첫 번째 줄에서는 먼저 이미지 이름 nginx:alpine을 언태깅한 것을 확인할 수 있습니다.

그런데 잘 생각해보면 Docker Hub에서 가져온 nginx:alpine이라는 이미지가 정확히 특정한이미지를 가리키고 있으라는 법은 없습니다. 같은 이름과 태그만 사용하더라도, 이미지 내용은 바뀔 수 있기 때문입니다. 이런 이유로 특정 이미지를 정확하게 가르키기 위한 Digest 태그도 자동으로 태깅이 이루어집니다(docker images --digests 명령어로 이미지의 Digest 값을 확인해볼 수 있습니다). 두 번째 줄의 내용을 보면 이 값도 언태깅됩니다.

또한 이미지는 내부적으로 다층의 레이어로 이루어져있습니다. 이미지와 레이어는 1:1로 매칭하는 개념이 아니기 때문에, docker rmi로 이미지를 지우면 여러 레이어들이 삭제(Deleted)되는 것까지 확인할 수 있습니다.

그럼 docker images로 이미지가 잘 삭제되었는지 확인해봅니다.

$ docker images -a
REPOSITORY         TAG                IMAGE ID       CREATED        SIZE
nginx              1.19               62d49f9bab67   2 weeks ago    133MB
nginx              latest             62d49f9bab67   2 weeks ago    133MB
<none>             <none>             8cf995c0ce5d   6 months ago   893MB
...

nginx:alpine 이미지가 보이지 않는 걸 보니, 잘 삭제되었나 봅니다 😁.

컨테이너에서 사용중인 이미지를 삭제하기

컨테이너로 실행중인 이미지를 삭제하려고 하는 경우 어떻게 될까요? 다시 nginx:alpine 이미지를 풀 받고 간단한 테스트를 해보겠습니다.

컨테이너에서 이미지를 사용하고 있지 않은 경우라면 docker rmi로 이미지가 문제없이 삭제됩니다만, 사용중인 경우에는 얘기가 조금 달라집니다. 아래 예제에서는 nginx:alpine 이미지를 풀 받고, 컨테이너로 실행해줍니다.

$ docker pull nginx:alpine
$ docker run -d nginx:alpine
5681195da9dca79510000da9a062cb8a1b7ed27ed6c41dd60839bd320f7ffe2a
$ docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS     NAMES
5681195da9dc   nginx:alpine   "/docker-entrypoint.…"   47 seconds ago   Up 46 seconds   80/tcp    modest_sanderson

이 상태에서 nginx:alpine 이미지를 삭제해보겠습니다.

$ docker rmi nginx:alpine
Error response from daemon: conflict: unable to remove repository reference "nginx:alpine" (must force) - container 5681195da9dc is using its referenced image a64a6e03b055

5681195da9dc 컨테이너가 실행중이라서 삭제가 불가능하다는 에러가 출력됩니다. 즉, 이미지를 사용중인 컨테이너가 있다면 이미지를 삭제할 수 없습니다. docker rmi에도 이런 상황을 위해서 -f 옵션이 준비되어있습니다.

docker rmi -f: 이미지 강제 삭제(DON’T!)

Docker 컨테이너가 실행중일 때는 컨테이너를 강제로 종료시키고 삭제하는 docker rm -f 명령어를 자주 사용합니다. 이미지의 경우도 마찬가지로, 이미지가 컨테이너에서 사용중이더라도 강제로 삭제하는 -f 옵션이 준비되어있습니다. 하지만, 결론부터 얘기하면 이 옵션을 사용하지 않는 것을 권장합니다.

예를 들어 아래와 같이 nginx:alpine 이미지가 로컬에 있고, 이 이미지로 실행중인 컨테이너가 있다고 가정해보겠습니다.

$ docker images -a
REPOSITORY         TAG                IMAGE ID       CREATED        SIZE
nginx              alpine             a64a6e03b055   13 days ago    22.6MB
nginx              1.19               62d49f9bab67   2 weeks ago    133MB
nginx              latest             62d49f9bab67   2 weeks ago    133MB

$ docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS     NAMES
5681195da9dc   nginx:alpine   "/docker-entrypoint.…"   47 seconds ago   Up 46 seconds   80/tcp    modest_sanderson

앞에서 살펴보았듯이 -f 옵션 없이 docker rmi nginx:alpine를 실행하면 에러가 발생합니다. 강제 삭제를 위해 -f 옵션을 붙여보겠습니다.

$ docker rmi -f nginx:alpine
Untagged: nginx:alpine
Untagged: nginx@sha256:07ab71a2c8e4ecb19a5a5abcfb3a4f175946c001c8af288b1aa766d67b0d05d2

에러가 나지 않고, 언태깅만 이뤄졌습니다. 무슨 일이 벌어진 걸까요? 다시 docker ps로 컨테이너를 확인해봅니다.

$ docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS     NAMES
5681195da9dc   a64a6e03b055   "/docker-entrypoint.…"   29 seconds ago   Up 28 seconds   80/tcp    modest_sanderson

여전히 컨테이너는 잘 실행되고 있습니다만, 이미지 이름이 nginx:alpine에서 a64a6e03b055으로 바뀐 것을 알 수 있습니다. 즉, 실제로 이미지가 삭제된 게 아니라, 그냥 언태깅만 이뤄졌기 때문에 Docker 내부적으로는 컨테이너도 그대로이고, 이미지도 삭제되지 않았습니다.

이제 이미지 목록을 보면 nginx:alpine 이미지가 이름이 없는(<none>) 이미지가 된 것을 확인할 수 있습니다.

$ docker images -a
REPOSITORY         TAG                IMAGE ID       CREATED        SIZE
<none>             <none>             a64a6e03b055   13 days ago    22.6MB
nginx              1.19               62d49f9bab67   2 weeks ago    133MB
nginx              latest             62d49f9bab67   2 weeks ago    133MB

이렇게 강제로 언태깅을 하게 되면, 오히려 이미지 관리가 더 번거로워 질 수 있습니다. 따라서 docker rmi -f는 사용하지 않는 것이 좋습니다.

특정 이미지를 사용하는 컨테이너를 전부 종료하고, 이미지 삭제하기

그럼 컨테이너가 실행중인 이미지를 삭제하고 싶다면 어떻게 해야할까요? 먼저 해당 이미지를 사용하는 컨테이너를 다 찾아서 종료한 다음에 삭제하는 것을 추천합니다. 하나씩 작업하기엔 귀찮은데요. 😥

docker ps --filter 기능을 사용하면 좀 더 쉽게 해결할 수 있습니다. --filter의 인자로 ancestor 키를 사용하면 특정 이미지를 사용하는 컨테이너만 검색할 수 있습니다.

$ docker ps -a --filter ancestor=nginx:alpine
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS        PORTS     NAMES
c0d45e286e56   nginx:alpine   "/docker-entrypoint.…"   2 seconds ago   Up 1 second   80/tcp    bold_leavitt

docker rm 사용법에서 소개한 셸 기법을 활용해보겠습니다.

로컬 시스템의 모든 Docker 컨테이너를 삭제하려면 docker rm -f $(docker ps -aq) 이 명령어를 실행하면 됩니다. 여기서 $() 안의 값을 위에서 필터한 내용으로 변경하면, 특정 이미지를 사용하는 컨테이너들만 한꺼번에 종료할 수 있습니다. 이 명령어가 동작하는, 더 자세한 원리에 대해서는 docker rm 사용법 글을 참고해주세요.

$ docker rm -f $(docker ps -aq --filter ancestor=nginx:alpine)
9fc9bccac814
.....

그리고 docker rmi로 이미지를 삭제해줍니다.

$ docker rmi nginx:alpine
Untagged: nginx:alpine
Untagged: nginx@sha256:07ab71a2c8e4ecb19a5a5abcfb3a4f175946c001c8af288b1aa766d67b0d05d2
Deleted: sha256:a64a6e03b0551e1cefa94db6cc6677fb1efed3c557d173f79584ff4ec474b5ae
Deleted: sha256:d950b497e5a0787af1b4a04e0298b693501d756b610b09e5501bc0d1feb02465
Deleted: sha256:01270ad0039edf3793b69b5374505aad02fc2e4464f460215a803fa728eaef8c

그럼 이미지와 레이어가 잘 삭제되는 것을 확인할 수 있습니다. 😚

이 명령어는 세트로 사용해주세요.

docker rm -f $(docker ps -aq --filter ancestor=[IMAGE])
docker rmi [IMAGE]

docker image rm

Docker에는 컨테이너나 이미지 이외에도 볼륨, 네트워크 등 다양한 오브젝트들이 있습니다. rm이나 rmi와 같은 서브 커맨드는 어떤 오브젝트를 조작하는 건지 직관적으로 알기 어려워서, docker containerdocker image와 같이 오브젝트 별 서브 커맨드가 추가되었습니다.

docker image rm 명령어로도 Docker 이미지를 삭제할 수 있습니다. 사용법은 docker rmi와 같습니다.

모든 Docker 이미지를 삭제하는 방법

로컬 시스템의 모든 Docker 컨테이너는 다음 명령어로 삭제할 수 있습니다.

docker rm -f $(docker ps -aq)

마찬가지로, 다음 명령어를 사용하면 로컬 시스템의 모든 Docker 이미지를 삭제할 수 있습니다(주의: 삭제한 이미지는 복구할 수 없습니다 😱).

docker rmi $(docker images -q)

이 명령어는 docker images -q 명령어로 모든 이미지 ID를 가져와서 docker rmi 명령어에 넘겨줍니다. 자세한 동작 원리는 docker rm 명령어 글에서 다루고 있습니다.

단, 앞에서 살펴본 것처럼 이미지를 삭제하기 위해서는 먼저 이미지를 사용하고 있는 컨테이너를 종료해야합니다. 따라서 시스템 상의 모든 이미지를 삭제하고자 할 때는 1. 모든 컨테이너를 종료하고, 2. 모든 이미지를 삭제하는 것을 추천합니다.

docker rm -f $(docker ps -aq)
docker rmi $(docker images -q)

사용하지 않는 이미지만 삭제하는 방법

prune 명령어를 사용하면 사용하지 않는 이미지만 골라서 삭제할 수 있습니다. prune은 필요없는 부분을 제거한다는 의미를 가지고 있으며, 기본적으로 docker image prune의 대상이 되는 이미지는 dangling된 이미지들입니다. dangling되었다는 의미는 아무런 태그도 가지고 있지 않다는 의미입니다(일반적으로 같은 이름으로 이미지를 빌드할 때 기존 이미지가 언태깅되면서 dangling 상태가됩니다).

$ docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Deleted Images:
deleted: sha256:f7c5c7a3bbf08fbaefe57672bb3d7eb0f6c4a60fc2bd303ede54aacf29031ad3
.....
deleted: sha256:d7d5f3f6791131da7f70f52b086f0acec373e5c6f0d66d7fbcd5276b47468e28

Total reclaimed space: 17.29MB

dangling된 이미지는 일반적으로 다시 사용되지 않기 때문에 삭제해도 무방합니다.

prune 명령어는 dangling된 이미지를 비롯해 현재 컨테이너에서 사용되고 있지 않은 이미지들을 골라서 삭제해주는 옵션도 제공해주고 있습니다. 먼저 어떤 옵션이 있는지 확인해봅니다.

$ docker image prune --help

Usage:  docker image prune [OPTIONS]

Remove unused images

Options:
  -a, --all             Remove all unused images, not just dangling ones
      --filter filter   Provide filter values (e.g. 'until=<timestamp>')
  -f, --force           Do not prompt for confirmation

-a 옵션으로 컨테이너에서 사용중이지 않은 모든 이미지도 함께 일괄 삭제할 수 있습니다(주의: 한 번 삭제한 이미지는 복구할 수 없습니다 😱).

$ docker image prune -a
WARNING! This will remove all images without at least one container associated to them.
Are you sure you want to continue? [y/N] y
Deleted Images:
untagged: nginx:alpine
.....
deleted: sha256:8297c7fdbce878a917039ca3aaeb58ffa852201e85138a200b8a993872ebc69c

Total reclaimed space: 2.168GB

Docker 이미지 삭제 방법 요약

이 글에서 다룬 이미지 삭제 방법을 총 정리해봅니다.

docker rmi [IMAGE_NAME]

docker rmi 명령어에 이미지 이름을 지정해 이미지를 삭제할 수 있습니다.

docker rmi [IMAGE1] [IMAGE2] [IMAGE3] ...

docker rmi 명령어는 여러개의 이미지를 한꺼번에 지울 수 있습니다.

# DON'T
docker rmi -f [IMAGE]

-f 옵션을 사용하면 컨테이너에서 이미지가 사용중이더라도 이미지를 삭제할 수 있지만, 아래 방법을 추천합니다.

$ docker rm -f $(docker ps -aq --filter ancestor=[IMAGE])
$ docker rmi [IMAGE]

이 명령어들은 [IMAGE]를 사용하는 모든 컨테이너를 종료한 후에, 이미지를 삭제합니다.

docker image rm [CONTAINER]

docker image rm 명령어는 docker rmi 명령어와 같습니다. 지정한 이미지를 삭제합니다.

docker rm -f $(docker ps -aq)
docker rmi $(docker images -q)

현재 로컬 시스템의 모든 이미지를 삭제합니다. 이미지는 복구가 불가능하니 주의가 필요합니다.

docker image prune

docker image prune 명령어는 dangling 된 이미지들을 한꺼번에 삭제합니다.

docker image prune -a

-a 옵션을 사용하면, dangling된 이미지와 함께 컨테이너에서 사용중이지 않은 모든 이미지를 삭제합니다.

추천 문서

LainyZine은 쿠팡 파트너스 활동에 따른 수수료를 제공받습니다.