빌드가 시작도 전에 멈춰 있던 이유 — 빌드 컨텍스트 전송
문제 발생
docker build를 실행하면 첫 줄에서 한참 멈춰 있었습니다.
=> transferring context: 412.30MB 38.4sDockerfile은 소스 몇 개만 복사하는데도 매번 이랬고, 소스 한 줄만 고쳐도 캐시가 전부 무효화됐습니다.
원인 분석
빌드에 필요한 파일만 전송되는 게 아닙니다. Docker 문서는 빌드 컨텍스트를 빌드가 접근할 수 있는 파일들의 집합으로 정의하고, 그 전체가 빌더로 전송된다고 설명합니다. 원격 빌더를 쓰면 네트워크로 넘어갑니다.
그래서 . 을 컨텍스트로 주면 node_modules, .git, 로컬 빌드 산출물, .env까지 전부 포함됩니다. 문서가 .dockerignore의 역할을 이렇게 적습니다 — 원치 않는 파일과 디렉터리를 빌더에 보내지 않게 해서 빌드 속도를 개선하며, 특히 원격 빌더를 쓸 때 그렇습니다.
캐시가 매번 깨진 것도 같은 원인입니다. COPY . . 같은 명령의 캐시 키는 컨텍스트 파일들의 내용이라, 무관한 파일(로그, 로컬 캐시)이 바뀌기만 해도 그 아래 레이어가 전부 다시 만들어집니다.
보안 문제도 함께입니다. .env나 키 파일이 컨텍스트에 있으면 COPY . . 한 줄로 이미지 안에 들어가고, 그 이미지는 레지스트리에 올라갑니다.
해결 방안
.dockerignore를 만듭니다. 문서 설명대로.gitignore와 비슷한 제외 패턴을 지원합니다.
.git
node_modules
**/node_modules
.next
dist
coverage
*.log
.env
.env.*-
.git을 반드시 넣습니다. 오래된 저장소에서는 이것만으로 컨텍스트가 수백 MB 줄어듭니다. -
COPY를 좁힙니다. 의존성 설치 레이어와 소스 복사 레이어를 나누면 캐시가 훨씬 오래 삽니다.
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .-
이미지 크기는 별개 문제입니다. 문서가 권하는 대로 작은 베이스 이미지는 이식성과 다운로드 속도뿐 아니라 의존성으로 들어오는 취약점 수도 줄여주고, 있으면 좋을 것 같아서 불필요한 패키지를 설치하는 것은 피해야 합니다. 멀티스테이지 빌드와 함께 씁니다.
-
전송량을 확인하며 조정합니다. 빌드 출력의
transferring context줄이 바로 그 지표입니다 — 몇 MB 수준이 될 때까지 줄입니다. -
CI에서도 같은 파일이 쓰이는지 확인합니다. 로컬에만 있고 저장소에 커밋되지 않으면 CI 빌드는 그대로 느립니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.