- Published on
Docker 빌드 no space left 캐시 정리 실전
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서버에서 Docker 빌드를 돌리다 보면 어느 순간 no space left on device가 튀어나옵니다. 문제는 “디스크가 꽉 찼다”는 사실 자체보다, 무엇이 공간을 잡아먹는지(이미지 레이어, 빌드 캐시, 중지된 컨테이너, dangling 볼륨, BuildKit 캐시 등)와 어디까지 지워도 되는지가 헷갈린다는 점입니다.
이 글은 다음 순서로 정리합니다.
- 어떤 저장소가 찼는지 빠르게 진단
- 가장 안전한 정리부터 단계적으로 실행
- BuildKit 사용 여부에 따른 캐시 정리 차이
- CI 환경(GitHub Actions 등)에서 재발 방지
운영 환경에서 무작정 prune -a를 치기 전에, 아래 체크리스트대로 진행하면 “지워도 되는 것만” 지우면서도 공간을 빠르게 확보할 수 있습니다.
1) 증상: 같은 에러라도 원인이 다르다
no space left on device는 보통 아래 상황에서 발생합니다.
- Docker 데이터 루트(기본은
/var/lib/docker)가 꽉 참 - 빌드 과정에서 임시 파일이
/tmp같은 다른 파티션을 채움 - 파일시스템 inode 고갈(디스크 용량은 남았는데 파일 개수가 한도)
- OverlayFS 레이어가 과도하게 쌓임(특히 CI에서 반복 빌드)
따라서 “디스크가 100%”만 보고 끝내면 재발합니다. 먼저 어떤 파티션/리소스가 고갈인지 확인합니다.
2) 3분 진단: 어디가 찼는지 먼저 확인
2.1 파티션 용량 확인
df -h
여기서 /var/lib/docker가 별도 마운트인지, 루트(/) 아래인지 확인합니다. Docker 데이터가 루트에 붙어 있으면 루트가 차는 순간 빌드가 같이 죽습니다.
2.2 inode 고갈 확인
df -ih
IUse%가 100%면 용량이 아니라 inode 문제입니다. 이 경우 작은 파일이 과도하게 생성되는 빌드(예: node_modules, 캐시 디렉터리)가 원인일 수 있습니다.
2.3 Docker가 얼마나 먹는지 요약
docker system df
출력에서 아래 항목을 봅니다.
- Images: 사용 중/미사용 이미지 용량
- Containers: 중지된 컨테이너가 남아있는지
- Local Volumes: dangling 볼륨(컨테이너 삭제해도 남는 데이터)
- Build Cache: BuildKit/legacy 빌드 캐시
여기서 Build Cache가 수십 GB 이상이면 캐시 정리가 가장 빠른 해결책입니다.
3) 가장 안전한 정리 순서(추천)
정리는 “안전한 것부터” 단계적으로 합니다.
3.1 중지된 컨테이너만 제거
docker container prune
- 실행 중인 컨테이너에는 영향 없음
- 중지된 컨테이너가 많을수록 효과 큼
3.2 dangling 이미지(태그 없는 레이어)만 제거
docker image prune
- 태그가 없는 중간 레이어 정리
- 일반적으로 안전
3.3 빌드 캐시 정리(대부분 여기서 해결)
BuildKit을 쓰는 경우가 많으므로 아래를 우선 시도합니다.
docker builder prune
대화형 확인 없이 바로 지우려면:
docker builder prune -f
캐시가 매우 크면 전체 삭제도 가능하지만, CI 빌드 시간이 늘 수 있습니다.
3.4 사용하지 않는 네트워크 정리
docker network prune
네트워크는 용량을 크게 먹지 않지만, 오래된 프로젝트가 많으면 정리 가치가 있습니다.
3.5 dangling 볼륨 정리(주의)
docker volume prune
볼륨은 “컨테이너가 없어도 데이터가 남는” 저장소라서, 개발 환경에서는 오래된 테스트 DB 볼륨 등이 쌓이기 쉽습니다. 다만 운영에서 볼륨을 잘못 지우면 데이터 유실이므로, 적용 전 아래로 확인하세요.
docker volume ls
4) 한 방에 정리: docker system prune의 정확한 의미
가장 많이 쓰는 명령이지만 옵션에 따라 위험도가 달라집니다.
4.1 기본(상대적으로 안전)
docker system prune
정리 대상:
- 중지된 컨테이너
- 사용하지 않는 네트워크
- dangling 이미지
- 빌드 캐시
4.2 모든 미사용 이미지까지 삭제(주의)
docker system prune -a
-a는 dangling뿐 아니라 미사용 이미지 전체를 지웁니다. 즉, 현재 컨테이너가 사용 중이지 않지만 다음 배포/롤백에서 필요할 수 있는 이미지도 삭제됩니다.
4.3 볼륨까지 포함(매우 주의)
docker system prune --volumes
볼륨은 데이터가 포함될 수 있으니 운영 서버에서는 특히 조심합니다.
5) BuildKit 캐시를 더 정교하게 제어하기
5.1 특정 기간 이상 캐시만 정리
최근 캐시는 남기고 오래된 캐시만 치우는 방식이 안전합니다.
docker builder prune --filter 'until=240h' -f
위는 240시간(10일)보다 오래된 캐시만 삭제합니다.
5.2 캐시 상한을 두고 정리
docker builder prune --keep-storage 10GB -f
빌드 캐시를 10GB 정도로 유지하고 나머지를 정리합니다.
5.3 Buildx를 쓰는 경우
멀티플랫폼 빌드에서 buildx를 쓰면 별도의 빌더 인스턴스 캐시가 쌓일 수 있습니다.
docker buildx ls
필요 없는 빌더를 정리하거나, 캐시를 prune합니다.
docker buildx prune -f
6) 실제로 무엇이 큰지 추적하는 법
docker system df만으로 감이 안 오면, Docker 데이터 루트에서 큰 디렉터리를 직접 확인합니다.
6.1 Docker Root Dir 확인
docker info | grep -i 'Docker Root Dir'
예: /var/lib/docker
6.2 큰 폴더 탐색
sudo du -h -d 1 /var/lib/docker | sort -h
OverlayFS를 쓰면 overlay2가 가장 큰 경우가 많습니다. 이때 “폴더를 직접 삭제”하면 메타데이터가 꼬여 Docker가 깨질 수 있으니, 반드시 prune 계열 명령으로 정리하는 것을 권장합니다.
7) 빌드 단계에서 공간을 덜 쓰게 만드는 Dockerfile 팁
캐시를 지우는 것도 중요하지만, 애초에 레이어가 불필요하게 커지지 않게 만드는 것이 재발 방지에 효과적입니다.
7.1 패키지 캐시 제거를 같은 레이어에서 처리
FROM ubuntu:22.04
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl ca-certificates \
&& rm -rf /var/lib/apt/lists/*
apt-get 캐시 삭제를 다른 RUN으로 분리하면 이전 레이어에 캐시가 남아 이미지가 커집니다.
7.2 멀티스테이지 빌드로 빌드 산출물만 남기기
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-slim
WORKDIR /app
COPY /app/dist ./dist
COPY package*.json ./
RUN npm ci --omit=dev
CMD ["node", "dist/server.js"]
빌드 도구/캐시/소스 전체를 런타임 이미지에 남기지 않아 이미지와 레이어가 작아집니다.
7.3 .dockerignore로 불필요한 컨텍스트 전송 차단
node_modules
.git
.next
dist
coverage
*.log
빌드 컨텍스트가 커지면 전송/압축 과정에서 디스크와 inode를 같이 잡아먹습니다.
8) CI에서 반복 발생할 때: 캐시 전략을 바꾸기
CI 러너는 빌드가 반복되며 레이어/캐시가 기하급수로 쌓입니다. 특히 GitHub Actions에서 캐시가 기대대로 동작하지 않으면 매번 새로 빌드하면서 Docker 레이어가 누적됩니다.
- 캐시 키 설계/경로가 잘못되면 캐시 미스가 계속 발생
- 그 결과 Docker 빌드 캐시가 의미 없이 커짐
이 경우 아래 글의 체크리스트가 직접적으로 도움이 됩니다.
또한 Kubernetes 노드에서 빌드/풀을 반복하다 노드 디스크가 꽉 차면 Pod가 연쇄적으로 불안정해질 수 있는데, 증상이 CrashLoopBackOff로 보이는 경우도 있습니다. 이런 상황이라면 아래 글의 “노드 리소스/스토리지” 관점도 같이 점검하세요.
9) 운영에서 안전하게 적용하는 권장 절차
운영 서버에서의 추천 루틴은 다음과 같습니다.
df -h와docker system df로 원인 범주 확정docker container prune로 중지 컨테이너 제거docker image prune로 dangling 이미지 제거docker builder prune --filter 'until=168h' -f로 오래된 빌드 캐시만 정리- 그래도 부족하면
docker system prune적용 - 마지막 수단으로만
docker system prune -a또는--volumes고려
정리 후에는 다시 확인합니다.
docker system df
10) 자주 묻는 질문
Q1. prune가 컨테이너를 멈추게 하나요?
docker container prune는 중지된 컨테이너만 삭제합니다. 실행 중인 컨테이너는 영향이 없습니다. 다만 system prune --volumes처럼 범위를 넓히면 서비스 데이터에 영향이 생길 수 있으니 옵션을 정확히 구분해야 합니다.
Q2. 디스크는 남았는데 계속 no space left가 나요
df -ih로 inode 확인- 빌드 중 사용하는 파티션(
/tmp등)이 별도로 작고 꽉 찼는지 확인 - Docker 데이터 루트가 예상과 다른 디스크에 있는지 확인
Q3. 캐시를 지우면 빌드가 느려지지 않나요?
느려질 수 있습니다. 그래서 무조건 전체 삭제보다는 until 필터나 keep-storage로 “최근 캐시를 남기는 정리”가 운영/CI 모두에서 균형이 좋습니다.
no space left on device는 Docker 자체의 문제라기보다, 캐시와 레이어가 누적되는 구조에서 자연스럽게 발생하는 운영 이슈입니다. 핵심은 “무엇을 지우는지 정확히 알고” 가장 안전한 prune부터 단계적으로 적용하는 것입니다. 위 절차대로만 해도 대부분은 서비스 영향 없이 수 분 내로 복구할 수 있습니다.