콘텐츠로 이동

Docker 이미지와 도커파일

개요

빌드할 때마다 "어떤 환경에서, 어떤 패키지를, 어떤 순서로 설치할지"를 사람이 기억하고 있긴 어려워요. Docker는 이 빌드 절차를 Dockerfile이라는 텍스트에 적어 두고, 그대로 실행해서 이미지를 만듭니다. 이미지는 애플리케이션과 실행 환경이 통째로 담긴 배포 단위예요. 우리 서비스도 모두 이 이미지로 포장되어 레지스트리(Harbor)에 올라가요.

상위 문서: Docker · 컨테이너 · 네트워킹

핵심 개념

Dockerfile과 빌드 컨텍스트. Dockerfile은 맨 위부터 한 줄씩 실행해 이미지를 만들어요. 각 지시어(FROM, RUN, COPY 등)가 레이어 하나씩을 만듭니다. docker build를 실행할 때 지정한 디렉토리(빌드 컨텍스트)의 파일이 COPY로 들어갈 수 있어요. 컨텍스트 안에 필요 없는 파일이 많으면 빌드가 느려지니 .dockerignore로 걸러 주는 게 좋아요.

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
CMD ["npm", "start"]

레이어와 캐시. 각 지시어가 쌓는 레이어는 재사용 가능해요. 위 파일을 다시 빌드하면, 바뀐 부분 아래의 레이어까지만 다시 만들고 위는 캐시를 써요. 그래서 package*.json을 먼저 복사해 npm ci를 돌리는 순서가 흔한 이유예요. 의존성이 바뀌지 않으면 그 위 레이어 캐시가 그대로 남거든요.

멀티스테이지 빌드. FROM을 여러 번 써서, 빌드에 필요한 도구가 든 스테이지에서 결과물만 골라 다음 스테이지로 복사하는 기법이에요. 최종 이미지에는 빌드 도구 없이 실행물만 들어가서 크기가 확 줄어요.

FROM golang:1.26 AS build
WORKDIR /src
COPY . .
RUN go build -o /bin/app .

FROM alpine:latest
COPY --from=build /bin/app /bin/app
CMD ["/bin/app"]

태그와 변경 불가능한 이미지. 이미지에 이름과 태그를 붙여 저장소에 push해요. 태그는 버전이나 커밋 해시로 남겨서 "이 배포가 어떤 코드였는지"를 되짚을 수 있게 해요. latest만 쓰면 어떤 내용인지 알기 어려우니, 명확한 태그를 붙이는 습관이 중요해요.

실제 적용(데이터스케쳐스)

GitHub Actions에서 코드를 체크아웃한 뒤 이 Dockerfile로 이미지를 빌드하고, 태그를 커밋 해시로 붙여 Harbor에 push해요. 이후 Kubernetes가 그 이미지를 받아 서비스를 띄우죠. 이미지를 만질 때는 신뢰할 수 있는 베이스 이미지를 고르고, 루트가 아닌 사용자로 실행하도록 Dockerfile을 구성해 두는 게 보안의 기본이에요.

더 알아보기