Gitlab CI/CD 파이프라인용 Discourse Image Builder

안녕하세요!

RPS Discourse Image Builder라는 저장소를 만들었습니다. 이 저장소는 Discourse OCI 이미지를 생성하는 데 사용됩니다. 이곳에서 정보를 찾는 분들께 도움이 될 것 같습니다. 우리는 주로 Discourse 배포를 기다릴 필요가 없도록 하고, Discourse 버전을 안정적으로 고정(version pinning)할 수 있도록 하기 위해 이 저장소를 만들었습니다.

discourse_docker 저장소를 사용하여 안정 버전으로 이미지를 가장 일반적인 방식으로 빌드하는 스크립트를 작성했습니다.

빌드 및 테스트용 Discourse 이미지와 빌드에 필요한 데이터베이스를 실행하는 docker compose 파일도 있습니다. 이 파일은 로컬 개발을 위해 실행할 수 있으며, shell 실행기를 사용하는 GitLab 러너에서 실행할 수 있지만, 프로필을 지원하는 docker-compose 버전이 설치된 시스템이 필요합니다.

접근 방식

빌드 스크립트는 CI/CD 파이프라인 내에서 실행되어야 하며, 이렇게 하면 버전을 쉽게 업데이트할 수 있습니다. 추가적인 조정은 이 저장소에서 생성된 이미지를 기반으로 하는 Dockerfile을 가진 다른 저장소들에서 수행됩니다.

배경

Discourse는 매우 훌륭한 소프트웨어이지만, 배포와 버전 고정이 쉽지 않습니다. 이 저장소는 Discourse를 배포하는 데 사용할 수 있는 Docker 이미지를 생성하는 데 사용됩니다.

문제는 Discourse가 Docker 이미지를 빌드하는 방식이 매우 독특하다는 점입니다. Discourse 개발자들은 discourse_docker 저장소를 사용하여 대상 머신에서 이미지를 빌드할 것을 기대합니다.

포럼에서 이에 대해 긴 논의가 이루어졌으며, 요약하면: Discourse 리드 개발자들은 Discourse를 배포하는 데 사용할 수 있는 공개 Docker 이미지를 지원하지 않기를 원합니다. 그들은 discourse_docker 저장소를 Discourse를 배포하는 유일한 공식 방법으로 유지하기를 원합니다.

이 방식의 주요 단점은 다음과 같습니다:

  • 우리의 경험상, Discourse 버전을 안정적으로 고정하는 것이 불가능합니다.
  • 이미지를 빌드하는 데 오랜 시간이 걸리며, 이미지가 빌드되는 동안 서비스는 사용할 수 없습니다. 또한 Discourse는 우리가 지원하는 모든 서비스 중 DevOps 반복 주기가 가장 깁니다.
  • 데이터베이스는 일반적인 Docker 기반 프로젝트와 다른 방식으로 관리됩니다.
  • 공식 Discourse 배포 방식은 Kubernetes나 Docker-Compose와 같은 OCI 기반 개발 워크플로우 및 배포와 호환되지 않습니다.
  • discourse_docker 런처는 실행 환경에 대해 많은 가정을 합니다. 예를 들어, 루트리스(rootless) Podman에서는 저장소 볼륨이 없다는 오류를 내며 실행을 거부하는데, 이를 인자나 환경 변수로 우회할 수 없습니다.

app.yml 파일에는 실행하려는 버전을 설정할 수 있는 version 매개변수가 있습니다.

스탠드얼론 컨테이너에서 웹 및 데이터 컨테이너로 분리하기에서 다룬 대로 공식 설치 방식을 사용하면 됩니다.

맞습니다. 우리는 "FileZilla로 FTP를 통해 이 zip 파일의 내용을 드래그 앤 드롭"하는 방식에 익숙한 웹마스터들을 위해 친근하게 만들되, 스택 내의 모든 소프트웨어(데이터베이스 포함)가 최신이고 지원되며 패치가 적용된 버전으로 실행되도록 보장하려고 노력합니다.

더 숙련된 Discourse 관리자의 경우, Discourse를 별도의 PostgreSQL 서버로 사용하도록 구성하기에 따라 외부에서 관리되는 데이터베이스를 가리키도록 설정하는 것은 환경 변수 하나만 변경하면 됩니다.

네, 런처 기반 플로우가 컨테이너 오케스트레이션과 기본적으로 호환되지 않습니다. 그렇더라도 ./launcher bootstrap app을 실행하여 생성된 이미지를 컨테이너 레지스트리에 푸시한 후, 해당 이미지를 오케스트레이션을 통해 실행함으로써 호환 가능하도록 만들 수 있습니다.

이것은 일반적으로 유용해 보이므로, 이를 가능하게 하는 풀 리퀘스트를 환영합니다. pr-welcome

2.8 버전에서 배포를 만들기 위해 그렇게 해보았지만, 잘못된 Discourse 버전에 대한 오류 메시지와 함께 실패했습니다. 이제 CI/CD에서 이를 재현할 수 있으므로, 여기에서 오류를 확인할 수 있습니다: docker-build (#4121616927) · Jobs · idcohorts / RPS / Discourse Image Builder · GitLab

우리는 기본적으로 그렇게 하고 있습니다. :slight_smile:

감사합니다. 진행 중입니다.

Discourse 2.8은 이제 지원되지 않기 때문입니다. 즉, 최신 Ruby를 해당 버전으로 역포트(back port)하지 않았으며, 이미 EOL(지원 종료) 상태인 Ruby 버전을 사용하고 있습니다. 누구도 프로덕션 환경에서 이를 실행해서는 안 됩니다.

완료되었습니다. add bypasses for unsupported docker versions - Pull Request #706 - discourse/discourse_docker - GitHub 를 참고하세요.

그래도 단순히 버전 매개변수만 변경하는 것만으로는 기술적으로조차 불가능하므로, 더 이상 이전 환경을 재현할 수 없습니다.

가능합니다. 단순히 이전 버전의 베이스 이미지를 사용하면 됩니다.

어떻게 하면 될까요? 검색해 보았지만 해결책을 찾지 못했습니다…

정확히 말해, 더 오래된 기본 이미지(타겟으로 삼고 있는 릴리스의 날짜 전후에 생성된 것으로, 당연히 그 날짜 이후여야 함)를 참조합니다.

그런 이미지가 페이지를 가득 채울 정도로 많습니다:

하지만 너무 오래된 버전을 고정(pinning)하려고 하면 업데이트된 Discourse 기본 이미지와 호환되지 않을 수 있습니다. 구체적인 예시를 떠올리지는 못하지만, 오래된 버전의 Discourse는 Ruby 3.2와 호환되지 않는 경우가 있습니다. 따라서 Discourse의 오래된 버전을 고정하는 경우, 때로는 discourse_docker도 고정해야 합니다.

가장 안전하고 대부분의 경우 가장 비효율적이지 않은 해결책은 매 배포 시마다 새로운 이미지를 빌드하는 대신, 이미지를 빌드하여 리포지토리에 푸시하는 것입니다. 그리고 플러그인을 사용 중이라면 각 플러그인도 고정해야 할 가능성이 높습니다.

저는 ECS 및 GCP와 AWS의 k8s 환경에서 여러 클라이언트를 위해 이 작업을 수행한 바 있습니다.

discourse_docker도 이전 버전으로 고정하면 재현할 수 있을 것이라고 확신합니다. 위에서 언급했듯이, 플러그인의 경우 더 복잡하며, 플러그인도 이전 버전으로 고정해야 할 가능성이 높습니다. 정말로 이전 버전을 유지 관리하고 싶다면, 이를 정확히 한 번만 빌드하여 리포지토리에 푸시하는 것이 최선의 방법입니다. 저는 현재 프로덕션 환경에서 최신 버전으로 업그레이드하는 경로를 테스트하기 위해 한 클라이언트와 함께 이 방식을 적용하고 있으며, 순조롭게 작동하고 있습니다.