CATEGORY

카테고리 (673)
AI (71)
Language & Specs (260)
FrameWork (36)
Library (20)
App (41)
Git (10)
Build & Dependency (2)
AWS (15)
DataBase (45)
OS (33)
Tool (17)
IT (120)
SEEMINGLY ONLINE

Seemingly
Online

이모저모 방방곡곡 두루두루 개발지식 저장소

RECENT POSTS

Tool/DocKer

docker 이미지 삭제 — none 이미지와 안 지워질 때

반응형

도커 이미지 하나를 지울 때는 docker rmi 이미지, 안 쓰는 것을 몰아서 정리할 때는 docker image prune, 태그가 <none>으로 뜨는 것들이 바로 이 prune 대상입니다. 그런데 지우려 하면 conflict 오류가 나면서 거부되는 경우가 있는데, 원인은 거의 하나 — 그 이미지를 쓰는 컨테이너가 남아 있어서입니다(실행 중이 아니라 중지된 컨테이너여도 막습니다). 아래 명령과 오류 메시지는 전부 Docker Engine 29.5.2에서 직접 실행해 얻은 출력입니다.

1. 지우기 전에 — 무엇이 얼마나 차지하나

# 이미지 목록 (태그 없는 이미지까지 보려면 -a)
docker images
docker images -a

# 디스크 사용량 요약 — 여기서 정리 가능한 양을 먼저 본다
docker system df
⚠️ Docker Engine 29.x에서 docker images의 표가 바뀌었습니다. 예전의 REPOSITORY / TAG / CREATED / SIZE가 아니라 IMAGE / ID / DISK USAGE / CONTENT SIZE / EXTRA로 나오고, 태그 없는 이미지는 기본 목록에서 아예 숨겨집니다. 도움말에도 "-a, --all: 기본값은 중간 이미지와 dangling 이미지를 숨긴다"라고 적혀 있습니다. 옛 글대로 docker images만 쳐서 "<none>이 안 보이니 없구나" 하면 오판입니다.
$ docker images -a
IMAGE                    ID             DISK USAGE   CONTENT SIZE   EXTRA
alpine:latest            d529dd0c6e55       8.42MB             0B
amazonlinux:2023         29839038d787        183MB             0B
nginx:1.27-alpine        96868d9fa38f       49.7MB             0B
<untagged>               1991bd789d71       8.66MB             0B

디스크 사용량 요약은 이렇게 나옵니다.

TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          12        2         371.3MB   363.5MB (97%)
Containers      3         1         0B        0B
Local Volumes   0         0         0B        0B
Build Cache     8         0         68B       56B

RECLAIMABLE이 회수 가능한 용량입니다. 위처럼 97%가 잡혔다면 쓰지 않는 이미지가 대부분이라는 뜻입니다.

2. 이미지 하나 삭제 — docker rmi

docker rmi 이미지이름:태그
docker rmi 3a1b2c4d5e6f          # 이미지 ID로도 된다 (앞 몇 자리만 써도 됨)

# 같은 명령의 정식 이름
docker image rm 이미지이름:태그
💡 "지웠는데 용량이 그대로"라면 태그만 떨어진 것입니다. 공식 문서에도 "이미지에 태그가 여러 개면 태그를 인자로 준 이 명령은 태그만 제거한다"고 적혀 있습니다. 실제로 태그가 둘 달린 이미지를 지우면 출력이 Untagged: rmtest:one 한 줄뿐이고 Deleted: 줄은 나오지 않습니다. 마지막 태그까지 지워야 이미지 본체가 삭제됩니다.

3. <none> 이미지의 정체 — dangling

이름 자리에 <none>(29.x 표에서는 <untagged>)으로 뜨는 이미지들이 있습니다. 같은 태그로 이미지를 다시 빌드하면, 태그가 새 이미지로 옮겨 가면서 이전 이미지가 이름을 잃고 남는 것입니다. 이걸 dangling(매달린) 이미지라고 부릅니다.

# dangling 이미지만 골라 보기 (필터를 주면 -a 없이도 나온다)
$ docker images -f "dangling=true"
IMAGE        ID             DISK USAGE   CONTENT SIZE   EXTRA
<untagged>   1991bd789d71       8.66MB             0B

# ID만 뽑아 다른 명령에 넘길 때
docker images -f "dangling=true" -q

스크립트에서 옛 형식이 필요하면 --format으로 직접 뽑으면 됩니다. 이때는 여전히 <none>:<none>으로 나옵니다.

docker images -f "dangling=true" --format '{{.Repository}}:{{.Tag}} {{.ID}} {{.Size}}'
# <none>:<none> 1991bd789d71 8.66MB

빌드를 반복하는 프로젝트라면 이게 계속 쌓여 용량을 먹습니다. 아래 prune 한 번이면 정리됩니다.

4. 안 쓰는 이미지 몰아서 삭제 — prune

공식 문서의 설명이 정확히 갈립니다 — "모든 dangling 이미지를 제거한다. -a를 주면 어떤 컨테이너도 참조하지 않는 이미지까지 전부 제거한다."

명령 지우는 대상 위험도
docker image prune 태그 없는 dangling 이미지만 낮음 — 평소 정리용
docker image prune -a 컨테이너가 안 쓰는 이미지 전부 높음 — 다시 받아야 함
docker image prune --filter label=팀=백엔드 조건에 맞는 것만 낮음 — 범위를 좁힐 때
$ docker image prune -f --filter label=rmtest=1
Deleted Images:
deleted: sha256:95b7638244c0ee02063ee353ee9f9a9f21384255a7528b66665d5c3690b071be

Total reclaimed space: 0B

-f는 확인 질문을 건너뛰는 옵션입니다. --filter until=24h처럼 시간으로도 좁힐 수 있어서, "하루 지난 빌드 잔여물만 치우기" 같은 정리가 됩니다.

⚠️ docker image prune -a는 지금 컨테이너로 안 떠 있는 이미지를 전부 지웁니다. 사내 레지스트리에서 받은 것, 로컬에서만 빌드해 둔 것도 함께 사라져 다시 받거나 다시 빌드해야 합니다. 실행 전에 docker images로 무엇이 있는지 먼저 보세요. docker system prune -a --volumes는 여기에 볼륨(=데이터)까지 지우므로 더 조심해야 합니다.

5. 안 지워질 때 — 오류 메시지별 원인

실제로 재현한 두 가지 오류입니다. 메시지가 비슷해 보여도 원인과 해법이 다릅니다.

중지된 컨테이너가 참조 중

$ docker rmi rmtest:solo
Error response from daemon: conflict: unable to remove repository reference
"rmtest:solo" (must force) - container 748b9000b6a5 is using its referenced image c65e07c887a3

컨테이너가 돌고 있지 않아도 막습니다. docker ps로는 안 보이니 -a를 붙여야 범인이 나옵니다.

# 중지된 것까지 포함해 보기
docker ps -a

# 그 컨테이너를 지우고 다시 시도
docker rm 748b9000b6a5
docker rmi rmtest:solo

실행 중 컨테이너가 쓰는 중

$ docker rmi c65e07c887a3
Error response from daemon: conflict: unable to delete c65e07c887a3 (cannot be forced)
- image is being used by running container f5361637a360

메시지 안의 cannot be forced가 앞의 must force와 다른 지점입니다. 실행 중인 컨테이너가 붙잡고 있으면 -f로도 이미지 본체를 못 지웁니다. 컨테이너를 먼저 멈추고 지워야 합니다.

docker stop f5361637a360
docker rm f5361637a360
docker rmi c65e07c887a3
💡 헷갈리는 부분 하나. 실행 중인 상태에서도 docker rmi -f 이미지:태그는 성공한 것처럼 Untagged:를 찍습니다. 하지만 이건 태그만 뗀 것이고 이미지 본체는 그대로 남아 <none>으로 목록에 다시 나타납니다. 용량은 하나도 안 줄어듭니다.

6. 전부 지우고 처음부터 하고 싶을 때

# 1) 컨테이너부터 정리 (이게 없으면 이미지가 안 지워진다)
docker rm -f $(docker ps -aq)

# 2) 이미지 전부
docker rmi -f $(docker images -aq)

# 3) 확인
docker system df

컨테이너를 다루는 명령이 낯설다면 docker 컨테이너 접속 글을 먼저 보면 흐름이 잡힙니다.

자주 묻는 질문 (FAQ)

Q. docker rmi와 docker image rm은 다른가요?
같습니다. 공식 문서에 docker image remove·docker rmi가 별칭(alias)으로 명시돼 있습니다.

Q. 이미지를 지우면 레지스트리(도커 허브)에서도 지워지나요?
아닙니다. 문서에 "이 명령은 레지스트리에서 이미지를 제거하지 않는다"고 적혀 있습니다. 로컬에서만 사라지므로 필요하면 다시 pull 하면 됩니다.

Q. 이미지를 지웠는데 디스크가 안 줄어듭니다.
세 가지를 확인하세요. ① 태그만 떨어진 건 아닌지 — docker images가 아니라 docker images -a로 봐야 <untagged>가 보입니다. ② 빌드 캐시가 남았는지(docker system df의 Build Cache 행 → docker builder prune, 29.x에서는 docker buildx prune으로 안내됩니다). ③ 도커 데스크톱은 가상 디스크를 쓰기 때문에 내부에서 지워도 호스트 파일 크기는 바로 줄지 않을 수 있습니다.

Q. <none> 이미지를 그냥 둬도 되나요?
동작에는 지장이 없지만 용량만 차지합니다. docker image prune은 dangling만 지우므로 비교적 안전한 정리 명령입니다.

마무리

정리하면 이렇습니다. ① 하나는 docker rmi, 몰아서는 docker image prune. ② <none>은 재빌드로 이름을 잃은 dangling 이미지. ③ conflict 오류는 컨테이너가 붙잡고 있다는 뜻이고, 중지된 컨테이너도 막습니다(docker ps -a로 확인). ④ must force는 -f로 풀리지만 cannot be forced는 컨테이너를 멈춰야 합니다. ⑤ prune -a는 되돌리기 어려우니 목록을 먼저 확인하고 실행하세요.


📚 참고 출처 (2026년 7월 29일 확인 · Docker Engine 29.5.2 실행)
· Docker Docs — docker image rm
· Docker Docs — docker image prune
· Docker Docs — docker system df

반응형

COMMENTS