Docker
Dockerfile 빌드가 로컬에선 되는데 배포에서 실패할 때
도커 이미지는 빌드 환경에 따라 다르게 나온다. 캐시, 네트워크, 권한 문제가 숨어있을 수 있다.
Dockerfile로 로컬에선 docker build 후 docker run이 잘 되는데, 배포 파이프라인에서 실패한다. 이럴 땐 보통 빌드 컨텍스트, 캐시, 또는 시스템 환경 차이다.
먼저 빌드 캐시를 의심한다
# 캐시 없이 빌드해보기
docker build --no-cache -t my-app:latest .
# 빌드 과정을 자세히 보기
docker build --progress=plain -t my-app:latest .
CI/CD에서 여러 번 빌드하면 캐시가 쌓인다. 어떤 레이어의 캐시가 오래된 패키지를 써서 문제가 생길 수 있다. --no-cache 플래그로 캐시를 무시하고 빌드해보자.
두 번째: 빌드 중 네트워크 의존성 확인
# 문제 있을 수 있는 패턴
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci # 네트워크가 필요함
# 더 안전한 패턴
RUN npm ci --prefer-offline --no-audit && npm cache clean --force
배포 환경의 네트워크가 제한적이면 npm install이 시간초과될 수 있다. npm ci를 쓰고, 필요하면 타임아웃을 늘린다.
세 번째: 빌드 단계의 환경변수 확인
# 빌드 시에만 필요한 변수
ARG NODE_ENV=production
ARG API_URL
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN NODE_ENV=${NODE_ENV} npm ci
COPY . .
RUN npm run build
빌드 시점에 필요한 환경변수(API URL, 빌드 플래그 등)가 제대로 전달되지 않으면 빌드가 실패한다. CI/CD 설정에서 --build-arg 옵션을 확인하자.
네 번째: 파일 권한 문제
# 로컬에서 빌드할 때 실행 파일 권한이 있는지 확인
ls -la scripts/
# Dockerfile에서 명시적으로 권한 설정
COPY scripts/entrypoint.sh /app/
RUN chmod +x /app/entrypoint.sh
특히 스크립트 파일이 실행 권한 없이 복사되면 런타임에 실패한다.
다섯 번째: 베이스 이미지 버전 확인
# 위험: 항상 최신 버전을 쓴다
FROM node:latest # 이미지가 매번 달라질 수 있음
# 안전: 구체적인 버전
FROM node:18.17.1-alpine3.18
latest 태그는 언제든 이미지가 바뀐다. 특정 버전을 명시해야 예측 가능한 빌드를 할 수 있다.
배포 환경에서 확인하는 체크리스트
docker build --no-cache로 캐시 영향을 제거한다- 빌드 로그에서 실패 지점을 본다
--build-arg로 필요한 환경변수를 모두 전달하는지 확인한다- 베이스 이미지 버전을 고정한다
- 실제로
docker run해서 이미지가 동작하는지 테스트한다
Docker 빌드 문제는 환경 차이에서 생기는 경우가 많다. 로컬과 배포 환경의 Dockerfile을 동일하게 유지하고, 빌드 스크립트에서 자주 변하는 값들을 명시적으로 제어하자.