BuildKit — 도커가 빌드를 실행하는 엔진
BuildKit — 도커가 빌드를 실행하는 새로운 엔진
도커로 이미지를 만들 때 실은 두 가지 빌더 중 하나를 쓰고 있어요. 과거 버전이 쓰던 레거시 빌더를 대체해서 지금 기본값으로 자리 잡은 게 바로 BuildKit이에요. 성능과 저장 공간 관리, 확장성에서 확연히 나아졌고, 빌드를 훨씬 똑똑하게 최적화해 주죠.
본문
BuildKit이 바뀌어 놓은 것들
레거시 빌더와 비교해서 BuildKit이 개선한 지점을 하나씩 꼽아볼게요. 우선 빌드를 더 빠르게 만들어줘요. 실행할 필요가 없는 빌드 스테이지를 알아서 찾아내 건너뛰고, 서로 의존하지 않는 스테이지는 병렬로 실행해요. 그리고 빌드 컨텍스트에서 수정된 파일만 다음 빌드로 전송하거나, 아예 쓰이지 않는 파일은 전송 자체를 생략해 버리죠.
이런 성능 향상의 토대에는 완전히 동시성을 갖춘 빌드 그래프 해석기(concurrent build graph solver)가 있어요. 의존성만 맞다면 빌드 단계를 병렬로 돌리고, 최종 결과에 영향을 주지 않는 명령은 최적화로 제거해 버려요. 로컬 소스 파일 접근도 최적화되어서, 이전 빌드 이후 바뀐 부분만 추적하기 때문에 파일을 다시 읽거나 업로드하느라 기다릴 필요가 없어요.
성능 외에 저장 공간 관리와 확장성도 레거시 빌더보다 개선된 핵심 영역이에요. 덕분에 더 복잡한 시나리오까지 지원하죠.
LLB — BuildKit의 심장
BuildKit의 핵심에는 LLB(Low-Level Build) 라는 정의 형식이 있어요. LLB는 중간 단계의 바이너리 형식으로, 개발자가 BuildKit을 직접 확장할 수 있게 해주는 벡엔드 형식이에요. 콘텐츠 주소 방식(content-addressable)의 의존성 그래프를 정의해서 복잡한 빌드 정의를 조립할 수 있고, Dockerfile에서는 드러나지 않는 기능(예컨대 데이터 직접 마운트나 중첩 실행)까지 지원해요.
(빌드스텝 A) ──┐
├── (최종 이미지)
(빌드스텝 B) ──┘
빌드의 실행과 캐싱에 관한 모든 결정은 LLB가 내려요. 캐싱 모델도 레거시 빌더와 완전히 다시 쓰였어요. 예전에는 이미지를 비교하는 휴리스틱을 썼지만, LLB는 빌드 그래프와 특정 연산에 마운트된 콘텐츠의 체크섬을 직접 추적해요. 그 덕분에 훨씬 빠르고 정밀하며 이식성도 좋아졌어요. 빌드 캐시를 레지스트리에 내보내 두면, 어떤 호스트에서든 후속 빌드가 그 캐시를 필요할 때 받아 쓸 수 있어요.
LLB는 골랭 클라이언트 패키지(github.com/moby/buildkit/client/llb)로 직접 생성할 수도 있어요. Go언어 기본 요소로 빌드 연산 사이의 관계를 정의하는 방식이라, 상상할 수 있는 거의 모든 것을 실행할 수 있는 강력함을 주지만, 대부분의 사용자가 매일 쓸 방식은 아니에요. 보통은 프론트엔드 컴포넌트나 LLB 중첩 실행으로 준비된 빌드 단계를 돌리는 쪽을 쓰죠.
프론트엔드
프론트엔드는 사람이 읽을 수 있는 빌드 형식을 LLB로 변환해서 BuildKit이 실행할 수 있게 해주는 컴포넌트예요. 프론트엔드는 이미지 형태로 배포될 수 있고, 사용자가 자기 정의에서 쓰는 기능이 보장되는 특정 버전의 프론트엔드를 지정할 수도 있어요.
예를 들어 Dockerfile을 BuildKit으로 빌드하려면 외부 Dockerfile 프론트엔드를 쓰는 방식으로 진행해요.
시작하기
BuildKit은 Docker Desktop과 Docker Engine 사용자에게 기본 빌더예요. 다만 예외가 하나 있어요. Windows 컨테이너를 빌드할 때는 레거시 빌더가 쓰여요.
BuildKit on Windows
BuildKit은 리눅스 컨테이너 빌딩만 완전히 지원해요. Windows 컨테이너(WCOW) 지원은 0.13 버전부터 실험적으로 제공되어요. 실험 기능이니 프로덕션보다는 미리 시도해보고 싶을 때 다뤄볼게요.
시작하려면 먼저 몇 가지가 갖춰져야 해요.
- 아키텍처:
amd64,arm64(바이너리는 제공되지만 공식 테스트는 아직) - OS: Windows Server 2019, Windows Server 2022, Windows 11
- 베이스 이미지:
ServerCore:ltsc2019,ServerCore:ltsc2022,NanoServer:ltsc2022 - Docker Desktop 4.29 이상
아래 명령들은 PowerShell 터미널에서 관리자 권한이 필요해요. 먼저 Hyper-V와 Containers Windows 기능을 켜세요. RestartNeeded가 True로 나오면 재부팅 후 관리자 PowerShell을 다시 여세요.
Windows 컨테이너 모드로 전환한 뒤, containerd 1.7.7 이상을 설치하고 BuildKit 최신 릴리스를 받아 압축을 풀어요.
$version = "v0.22.0" # specify the release version, v0.13+
$arch = "amd64" # arm64 binary available too
curl.exe -LO https://github.com/moby/buildkit/releases/download/$version/buildkit-$version.windows-$arch.tar.gz
# there could be another `.\bin` directory from containerd instructions
# you can move those
mv bin bin2
tar.exe xvf .\buildkit-$version.windows-$arch.tar.gz
## x bin/
## x bin/buildctl.exe
## x bin/buildkitd.exe
해석하자면, bin/buildctl.exe와 bin/buildkitd.exe라는 두 실행 파일이 압축에서 풀려요. 만약 dockerd가 관리하는 containerd 프로세스를 쓰고 있다면 그 주소를 지정해주면 돼요.
buildkitd.exe --containerd-worker-addr "npipe:////./pipe/docker-containerd"
이후 관리자 권한 터미널에서 로컬 BuildKit 데몬을 쓰는 원격 빌더를 만들고, docker buildx inspect로 연결을 확인해요. 출력에 빌더 플랫폼이 Windows로, 엔드포인트가 named pipe로 표시되면 정상이에요. 그 다음 Dockerfile을 만들어 hello-buildkit 이미지를 빌드하고 레지스트리에 푸시한 뒤 docker run으로 실행해보면 돼요.