Construtor de Imagens Discourse para Pipelines CI/CD do Gitlab

Olá!

Criamos um repositório chamado RPS Discourse Image Builder que é usado para criar uma imagem OCI do Discourse. Acho que isso pode ser útil para algumas pessoas que procuram por isso. Fizemos isso principalmente para não precisar esperar pela implantação do Discourse, que demora e para poder fixar versões do Discourse de forma confiável.

Escrevemos um script que usa o repositório discourse_docker para construir a imagem com a versão estável da forma mais geral possível.

Há também um arquivo docker-compose que inicia os bancos de dados necessários para a compilação e a imagem do Discourse para testes e a executa para desenvolvimento local. Isso pode ser executado em um GitLab runner com o executor shell, mas você precisa de um sistema com uma versão do docker-compose que suporte perfis.

Abordagem

O script de compilação deve ser executado em nossos pipelines de CI/CD para que possamos atualizar facilmente a versão, de modo que ajustes adicionais sejam feitos em repositórios diferentes com Dockerfiles que se baseiam na imagem criada por este repositório.

Contexto

O Discourse é um software muito bom, mas não é muito fácil de implantar e fixar versões. Este repositório é usado para criar uma imagem docker que pode ser usada para implantar o Discourse.

O problema é que o Discourse tem uma maneira muito peculiar de construir suas imagens docker. Os desenvolvedores do Discourse esperam que você construa a imagem na máquina de destino com o repositório discourse_docker.

Houve longas discussões sobre isso no fórum, TL;DR: Os principais desenvolvedores do Discourse se recusam a dar suporte a uma imagem docker pública que possa ser usada para implantar o Discourse. Eles querem manter o repositório discourse_docker como a única maneira oficial de implantar o Discourse.

As principais desvantagens dessa abordagem são:

  • Não é possível, com base em nossa experiência, fixar versões do Discourse de forma confiável.
  • Leva muito tempo para construir a imagem e, quando a imagem é construída, o serviço não está disponível. Além disso, o Discourse tem o ciclo de iteração DevOps mais longo de todos os serviços que suportamos.
  • Os bancos de dados são gerenciados de forma diferente do que para projetos usuais baseados em docker.
  • A história de implantação oficial do Discourse é incompatível com fluxos de trabalho de desenvolvimento e implantações baseados em OCI, como Kubernetes ou até mesmo Docker-Compose.
  • O launcher discourse_docker faz muitas suposições sobre o ambiente em que está sendo executado. Por exemplo, ele se recusa a ser executado no Podman sem root com um erro sobre volumes de armazenamento ausentes, sem poder contornar isso com um argumento ou variável de ambiente.
2 curtidas

Existe um parâmetro version no arquivo app.yml que pode ser definido para a versão que você deseja executar.

Usando a instalação oficial que é tratada usando Mover de contêiner autônomo para contêineres web e de dados separados.

Verdade, tentamos torná-lo amigável para webmasters do tipo “arraste e solte o conteúdo deste arquivo zip com o FileZilla via FTP”, garantindo que todos executem versões recentes, suportadas e corrigidas de todo o software da pilha, incluindo seus bancos de dados.

Para administradores do Discourse mais experientes, apontar para um banco de dados gerenciado externamente está a uma variável de ambiente de distância, conforme Configurar o Discourse para usar um servidor PostgreSQL separado

Sim, o fluxo baseado no launcher não é compatível “out-of-the-box” com orquestração de contêineres. Dito isso, pode-se torná-lo compatível executando ./launcher bootstrap app e enviando a imagem resultante para um registro de contêiner e, em seguida, executando dita imagem via orquestração.

Agradecemos um pull request para tornar isso possível, pois parece útil em geral. pr-welcome

5 curtidas

Tentamos isso para criar uma implantação a partir de 2.8, mas falha reclamando de uma versão incorreta do Discourse. Como agora podemos reproduzir isso em nosso CI/CD, você pode ver o erro aqui: docker-build (#4121616927) · Jobs · idcohorts / RPS / Discourse Image Builder · GitLab

É basicamente o que estamos fazendo. :slight_smile:

Obrigado, estou nisso.

1 curtida

Isso ocorre porque o Discourse 2.8 não é mais suportado, o que significa que não fizemos o backport da versão mais recente do Ruby para ele, e ele roda em uma versão do Ruby que já está EOL (fim de vida). Ninguém deveria executá-lo em produção.

1 curtida

Feito, veja add bypasses for unsupported docker versions by mkbrechtel · Pull Request #706 · discourse/discourse_docker · GitHub

2 curtidas

Ainda assim, nem sequer é tecnicamente possível (apenas alterando o parâmetro de versão), então não podemos mais reproduzir ambientes antigos.

bem, você pode, você só precisa usar uma imagem base mais antiga.

Como eu faria isso? Pesquisei e não encontrei uma solução…

Você literalmente referencia a imagem base mais antiga (criada aproximadamente na data do lançamento que você está visando - obviamente, ela deve ser posterior)

Existem páginas (e páginas!) delas:

https://hub.docker.com/r/discourse/base/tags

1 curtida

Mas se você tentar fixar em uma versão muito antiga, ela pode não funcionar com versões atualizadas da imagem base do Discourse. Não me lembro de exemplos específicos, mas algo como uma versão antiga do Discourse não funcionará com o Ruby 3.2, então você (às vezes) também precisa fixar discourse_docker se fixar em uma versão antiga do Discourse.

A solução mais segura e, na maioria dos casos, menos desperdiçadora é construir uma imagem e enviá-la para um repositório em vez de construir uma nova imagem a cada implantação. E se você tiver plugins, provavelmente precisará fixar cada um deles também.

Eu fiz isso para vários clientes para ECS, bem como k8s no GCP e AWS.

Tenho quase certeza de que você pode, se também fixar discourse_docker na versão antiga. Como mencionei acima, é mais complicado com plugins, pois você provavelmente precisará fixá-los nas versões antigas também. Se você realmente quiser manter versões antigas, construí-las exatamente uma vez e enviá-las para um repositório é o caminho a seguir. Estou fazendo isso com um cliente para testar caminhos de atualização da produção atual para a mais recente e está funcionando perfeitamente.

1 curtida