광고 차단 프로그램이 감지되었습니다

이 사이트는 광고 수익을 통해 무료로 콘텐츠와 서비스를 제공하고 있습니다.

더 나은 서비스를 위해 광고 차단 프로그램을 비활성화 해주세요.

광고 차단 해제 방법 보기
Loading...

도커 빌드가 왜 이렇게 느려? 10GB 빌드 컨텍스트의 비극 😱

도커 빌드가 왜 이렇게 느려? 10GB 빌드 컨텍스트의 비극 😱에 대한 img

아... 이게 아니었구나

제가 며칠 전에 정말 바보같은 실수를 하나 발견했어요. 몇 달째 도커 빌드할 때마다 "왜 이렇게 오래 걸리지?"하면서 답답해하고 있었거든요. 특히 회사에서 새로운 마이크로서비스 프로젝트를 도커 컴포즈로 구성하면서부터 빌드 시간이 말도 안 되게 길어졌어요.

처음엔 그냥 "프로젝트가 커져서 그런가보다" 하고 넘어갔는데... 빌드할 때마다 터미널에 뜨는 "Sending build context to Docker daemon: 10.2GB" 이 메시지가 계속 신경 쓰였어요.

음... 10기가라니? 아무리 생각해도 제 코드가 그렇게 클 리가 없는데 말이죠.


범인을 찾아라!

결국 참다못해 프로젝트 폴더를 뒤져보니까... 아, 이런. 😅

my-project/
├── docker-compose.yml
├── .dockerignore        # 🚨 문제의 위치!
├── media/              # 영상, 이미지 파일들이 수 기가씩...
├── app/
│   ├── Dockerfile
│   └── src/
└── api/
    ├── Dockerfile
    └── src/

.dockerignore 파일을 프로젝트 루트에 둔 게 문제였어요! 도커 컴포즈와 같은 위치에 놨더니, 각 서비스의 Dockerfile이 있는 위치에서는 이 파일을 읽지 못하는 거였죠.

그래서 app/ 폴더에서 도커 빌드할 때 상위 디렉토리의 media/ 폴더까지 모조리 빌드 컨텍스트에 포함되어 버린 거예요. 몇 달 동안 매번 몇 기가씩 되는 영상 파일들을 도커 데몬에게 보내고 있었던 거죠... 🤦♂️


원리를 알고 나니 뻔한 일이었네

나중에 도커 공식 문서를 다시 찾아보니까, 빌드 컨텍스트는 docker build 명령을 실행하는 위치가 기준이 되더라고요.

도커 빌드가 어떻게 작동하는지 보면:

  1. docker build . 명령을 실행하면 현재 디렉토리(.)가 빌드 컨텍스트가 됨
  2. .dockerignore 파일은 빌드 컨텍스트의 루트에 있어야 함
  3. 도커는 빌드 컨텍스트의 모든 파일을 도커 데몬에게 전송

제가 실수한 부분은 도커 컴포즈에서 각 서비스의 build.context를 상위 디렉토리로 설정해놨는데, .dockerignore는 각 서비스 디렉토리에 없었던 거예요.

# docker-compose.yml
services:
  app:
    build:
      context: ./app    # 빌드 컨텍스트는 ./app
      dockerfile: Dockerfile

이 경우 ./app/.dockerignore가 있어야 하는데, 저는 계속 루트에만 둬놨으니 당연히 미디어 파일들이 다 포함될 수밖에요.

Docker 공식 문서에서도 ".dockerignore file must be in the root of the build context for it to be effective"라고 명시하고 있고, Google의 컨테이너 베스트 프랙티스에서도 각 서비스별로 적절한 .dockerignore를 배치하라고 권하고 있더라고요.


해결 과정

일단 급한 불부터 끄자

# 각 서비스 디렉토리에 .dockerignore 생성
echo "media/" > app/.dockerignore
echo "media/" > api/.dockerignore
echo "*.log" >> app/.dockerignore
echo "node_modules/" >> app/.dockerignore

더 정교하게 튜닝

# app/.dockerignore
media/
uploads/
*.log
.git/
.gitignore
README.md
docker-compose.yml
.env
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

결과 확인

$ docker build ./app
Sending build context to Docker daemon: 234.5MB  # 🎉 10GB → 234MB!

와... 진짜 10기가에서 200메가로 줄어들더라고요! 빌드 시간도 5분에서 30초로 단축됐고요.


추가로 배운 팁들

빌드 컨텍스트 크기 미리 확인하기

# 빌드 전에 컨텍스트 크기 확인
du -sh ./app

어떤 파일들이 제외되는지 확인

docker build --no-cache --progress=plain ./app 2>&1 | grep "excluding"

프로젝트 구조별 전략

  • 모노레포: 루트에 공통 .dockerignore + 각 서비스별 추가 파일
  • 멀티레포: 각 서비스별 독립적인 .dockerignore
  • 개발/운영 분리: 환경별로 다른 .dockerignore 템플릿 사용


아직도 헷갈리는 부분들

솔직히 말하면 아직도 완벽하게 이해했다고 할 수는 없어요. 특히:

  • 복잡한 멀티스테이지 빌드에서의 최적화는 아직 연구 중이고
  • CI/CD 파이프라인에서의 캐시 전략도 더 공부해야 할 것 같아요
  • 큰 바이너리 파일들을 어떻게 효율적으로 관리할지도 고민이에요

제가 경험한 건 비교적 단순한 Node.js + 미디어 파일 케이스라서, 다른 환경에서는 또 다른 이슈가 있을 수 있겠더라고요.


마무리하며...

이런 실수를 하면서 느낀 건, 기본기의 중요성이에요. 도커를 몇 년째 쓰고 있으면서도 빌드 컨텍스트의 정확한 동작 원리를 제대로 이해하지 못했던 거죠.

혹시 비슷한 경험 있으신 분들 계신가요? 아니면 제가 놓친 다른 최적화 방법이 있다면 댓글로 공유해 주세요!

앞으로는 새 프로젝트 시작할 때마다 .dockerignore 배치를 첫 번째로 체크하는 습관을 들이려고 해요. 여러분도 혹시 빌드가 느리다 싶으면 빌드 컨텍스트 크기부터 확인해보세요! 😊

이 글의 정보는 2025년 8월 기준이며, 도커 버전이나 환경에 따라 다를 수 있습니다. 더 정확한 정보는 공식 문서를 참고해 주세요.

목차
목차를 불러오는 중...

댓글

Loading...

댓글 로딩 중...

구글 검색