Docker
Docker 이미지를 빌드하는 것은 모든 종류의 애플리케이션을 배포하는 일반적인 방법입니다. 그러나 monorepo에서 이를 수행하는 것에는 몇 가지 과제가 있습니다.
Good to know:
This guide assumes you're using create-turbo or a repository with a similar structure.문제점
monorepo에서는 관련 없는 변경 사항이 앱을 배포할 때 Docker가 불필요한 작업을 수행하게 만들 수 있습니다.
다음과 같은 monorepo가 있다고 가정해 봅시다:
Docker를 사용하여 apps/api를 배포하려고 하므로 Dockerfile을 만듭니다:
이렇게 하면 루트 package.json과 루트 lockfile이 Docker 이미지로 복사됩니다. 그런 다음 종속성을 설치하고, 앱 소스를 복사하고, 앱을 시작합니다.
또한 node_modules가 앱의 소스와 함께 복사되는 것을 방지하기 위해 .dockerignore 파일을 만들어야 합니다.
lockfile이 너무 자주 변경됩니다
Docker는 앱을 배포하는 방법에 대해 매우 똑똑합니다. Turborepo와 마찬가지로 가능한 한 적은 작업을 수행하려고 합니다.
우리 Dockerfile의 경우, 이미지에 있는 파일이 이전 실행과 다른 경우에만 npm install을 실행합니다. 그렇지 않으면 이전에 있던 node_modules 디렉터리를 복원합니다.
즉, package.json, apps/api/package.json 또는 package-lock.json이 변경될 때마다 Docker 이미지가 npm install을 실행합니다.
이것은 훌륭하게 들리지만, 우리는 무언가를 깨닫습니다. package-lock.json은 monorepo에 대해 전역입니다. 즉, apps/web 내부에 새 패키지를 설치하면 apps/api가 재배포됩니다.
대규모 monorepo에서는 monorepo의 lockfile에 대한 변경 사항이 수십 또는 수백 개의 배포로 이어지기 때문에 엄청난 시간 손실이 발생할 수 있습니다.
해결 방법
해결 방법은 Dockerfile에 대한 입력을 엄격하게 필요한 것으로만 제한하는 것입니다. Turborepo는 간단한 해결책인 turbo prune을 제공합니다.
이 명령을 실행하면 ./out 디렉터리 내에 monorepo의 축소된 버전이 생성됩니다. api가 의존하는 워크스페이스만 포함합니다. 또한 lockfile을 축소하여 관련 node_modules만 다운로드됩니다.
--docker 플래그
기본적으로 turbo prune은 모든 관련 파일을 ./out 내부에 넣습니다. 그러나 Docker로 캐싱을 최적화하려면 파일을 두 단계로 복사하는 것이 이상적입니다.
먼저, 패키지를 설치하는 데 필요한 것만 복사하려고 합니다. --docker를 실행하면 ./out/json 내부에서 찾을 수 있습니다.
그런 다음 ./out/full의 파일을 복사하여 소스 파일을 추가할 수 있습니다.
이렇게 종속성과 소스 파일을 분리하면 종속성이 변경될 때만 npm install을 실행할 수 있으므로 훨씬 더 큰 속도 향상을 얻을 수 있습니다.
--docker 없이는 모든 축소된 파일이 ./out 내부에 배치됩니다.
예제
상세한 with-docker 예제는 prune을 최대한 활용하는 방법에 대해 자세히 설명합니다. 편의를 위해 Dockerfile을 복사했습니다.
monorepo의 루트에서 Dockerfile을 빌드합니다:
이 Dockerfile은 standalone output
mode를
사용하는 Next.js 앱용으로 작성되었습니다.
Remote Caching
Docker 빌드 중에 원격 캐시를 활용하려면 빌드 컨테이너가 Remote Cache에 액세스할 수 있는 자격 증명을 가지고 있어야 합니다.
Docker 이미지에서 시크릿을 처리하는 방법은 여러 가지가 있습니다. 여기서는 최종 이미지에 대해 숨겨질 빌드 인수로 시크릿을 사용하는 다단계 빌드를 사용하는 간단한 전략을 사용합니다.
위와 유사한 Dockerfile을 사용한다고 가정하고, turbo build 바로 전에 빌드 인수에서 일부 환경 변수를 가져옵니다:
turbo는 이제 Remote Cache에 도달할 수 있습니다. 캐시되지 않은 Docker 빌드 이미지에 대한 Turborepo 캐시 적중을 보려면 프로젝트 루트에서 다음과 같은 명령을 실행하세요: