솔직히 말씀드리면, 저는 이 플랫폼과 코드베이스에 새로 합류한 사람이라 리빌드가 내부적으로 현재 어떻게 작동하는지 전혀 알지 못합니다. 다만, 제 현재 이해에 따르면 리빌드는 다음과 같은 과정을 거칩니다:
현재 컨테이너를 중지합니다.
소스 트리에서 데이터를 가져와 새로운 컨테이너를 구성합니다.
사용자가 새로운 컨테이너를 시작할 때까지 대기합니다.
DevOps 관점에서 보면, 왜 구 컨테이너가 여전히 실행 중일 때 새 컨테이너를 빌드(예: 다른 브랜치나 임시 디렉터리에서)할 수 없을까요? 그렇게 하면 새 컨테이너로 구 컨테이너를 교체하는 과정이 훨씬 빨라질 것 같습니다(적어도 다운타임 측면에서). 분 단위가 아니라 초 단위로 줄어들 수 있을 것입니다.
컨테이너가 리빌드 시에도 파괴되지 않는 스토리지 볼륨을 사용한다면, 이 사용 사례에서 설정이나 데이터베이스 변경 사항(예: 새로운 메시지)을 특별히 처리할 필요가 없을 수도 있다고 생각합니다. 즉, 컨테이너 빌드가 컨테이너 상태와 그렇게 강하게 결합되어 있을 필요는 없다는 뜻입니다.
이것은 아직 아무도 관심을 기울이지 않은 문제일까요, 아니면 한 컨테이너가 중지되어야만 다른 컨테이너를 빌드할 수 있도록 요구하는 기존 아키텍처 결정이 있는 것일까요?
Discourse 소스, OS 수준의 의존성, Docker 기본 이미지, Ruby gems 등을 업데이트하는 작업은 빌드를 2단계로 나누어 수행함으로써 가능할 수 있습니다. 이때 aforementioned 작업들은 1단계에서 실행하면 됩니다.
이 1단계는 환경에 종속적이지 않으므로 CI 환경에서도 실행할 수 있습니다. 이를 통해 스테이징 및 프로덕션 환경에서 거의 동일한 이미지를 사용할 수 있어, 다른 날짜에 빌드하는 과정에서 발생할 수 있는 오류를 방지할 수 있으며, 다운타임 감소라는 장점도 있습니다.
DB 마이그레이션과 assets:precompile 작업은 여전히 대상 머신에서 실행되어야 합니다. 대부분의 경우 DB 마이그레이션은 빠르게 완료됩니다. 반면, assets:precompile 작업은 시간이 가장 많이 소요되는 단계로 문제가 됩니다. 일부 자산이 실행을 위해 DB에 정의된 환경 정보(예: 일부 CSS 규칙)를 알아야 하기 때문이라고 생각합니다.
이 작업을 2단계로 나누어, 환경에 종속되지 않는 모든 자산을 먼저 CI 환경에서 실행하고, 2단계에서는 DB 등에 종속적인 자산만 컴파일하도록 한다면 매우 훌륭할 것입니다. 다만, 이를 기술적으로 구현하는 것이 얼마나 어려운지는 알지 못합니다.
앱 컨테이너를 2단계로 부트스트랩하는 방법에 대해서는 다음 주제에서 논의하고 있습니다:
제가 수행한 변경 사항은 discourse 웹 템플릿을 3개 파일로 나누는 것뿐이었지만, 작업 자체는 동일합니다. 다만, 웹 템플릿의 향후 변경으로 인해 제가 직접 업데이트할 필요가 없도록 discourse 팀에서 이를 지원해 주신다면 좋겠습니다.