Por que "rebuild" está tão acoplado ao status de execução do container?

Em boa fé, devo começar dizendo que sou novo na plataforma e na base de código e, portanto, não faço ideia de como o rebuild funciona atualmente nos bastidores. No entanto, meu entendimento atual é que o rebuild:

  1. para o container atual
  2. constrói um novo container com dados da árvore de origem
  3. aguarda que você inicie o novo container

De uma perspectiva voltada para DevOps, por que não é possível construir o novo container (talvez em outra branch ou diretório temporário) enquanto o antigo ainda está em execução? Isso pareceria tornar a troca do novo container pelo antigo um processo muito mais rápido (pelo menos em termos de tempo de inatividade), talvez na ordem de segundos em vez de minutos.

Se os containers estiverem usando volumes de armazenamento que não são destruídos quando o container é reconstruído, nem mesmo tenho certeza de que alterações de configuração ou de banco de dados (por exemplo, novas mensagens) precisem ser tratadas de forma especial para esse caso de uso, o que significa que a construção do container não deveria estar tão acoplada ao status do container.

Isso é simplesmente uma questão que ninguém ainda voltou sua atenção, ou existe uma decisão arquitetural existente que exige que um container seja interrompido antes que outro possa ser construído?

Rebuild é uma atualização abrangente que pode:

  • Atualizar o código-fonte do Discourse
  • Atualizar dependências no nível do sistema operacional, como a versão principal do Ruby
  • Atualizar para versões mais recentes e incompatíveis do PostgreSQL, cuidando automaticamente da atualização do formato do disco de dados para a nova versão
  • Atualizar a imagem do Docker. Apenas como exemplo, no início deste ano, mudamos do Ubuntu 16.04 para a última versão do Debian, e tudo foi transparente para o usuário; basta digitar ./launcher rebuild app.

Rebuilds não são necessários o tempo todo; são obrigatórios apenas algumas vezes ao ano, quando ocorre uma grande atualização de dependências. Para todas as outras atualizações, você pode realizar atualizações com 0 tempo de inatividade clicando no atualizador web na interface administrativa.

Para mais pontos relacionados a “devops”, você pode tentar:

e muito mais em #howto:sysadmin

Posso estar errado, mas sinto que a pergunta do @CodeGnome sobre reconstruções sem tempo de inatividade ainda merece mais investigação.

Se entendi o Docker corretamente, os seguintes aspectos do Discourse poderiam ser reconstruídos em segundo plano em um novo container enquanto o container existente ainda estiver em execução:

  • Atualizar o código-fonte do Discourse
  • Atualizar dependências no nível do sistema operacional, como a versão principal do Ruby
  • Atualizar a imagem do Docker. Apenas como exemplo, no início deste ano, mudamos do Ubuntu 16.04 para o Debian mais recente, e tudo foi transparente para o usuário; basta digitar ./launcher rebuild app.

Quanto às mudanças que quebram compatibilidade no PostgreSQL, isso é mais delicado devido ao volume de dados, que, suponho, é compartilhado entre os containers antigo e novo.

Talvez o site pudesse ser colocado no modo somente leitura no início da reconstrução, com o container antigo mantendo seu volume existente, enquanto o banco de dados em construção operaria dentro de um novo volume do Docker?

Sobre a atualização da fonte do Discourse, dependências de nível de sistema operacional, a imagem base do Docker, gems do Ruby e afins, é possível fazer isso realizando a build em duas etapas e executando as tarefas mencionadas na primeira etapa.

Essa primeira etapa é independente do ambiente e pode ser executada até mesmo em um ambiente de CI (assim, você pode usar uma imagem quase idêntica nos ambientes de staging e produção, evitando possíveis erros decorrentes de rebuilds em datas diferentes, sem falar na redução do tempo de inatividade).

As tarefas de migração do banco de dados e assets:precompile ainda precisariam ser executadas na máquina de destino. A migração do banco de dados, na maioria dos casos, seria rápida. Por outro lado, a tarefa assets:precompile é um problema porque é a etapa que mais consome tempo. Acredito que isso ocorra porque alguns ativos precisam conhecer certas configurações do ambiente definidas no banco de dados, como algumas regras CSS, para serem executados.

Seria extremamente útil se essa tarefa fosse dividida em duas partes: primeiro, todos os ativos que não dependem do ambiente seriam compilados e poderiam ser executados em um ambiente de CI; e, na segunda etapa, seriam compilados apenas os ativos que dependem de dados do banco de dados, etc. Dito isso, não sei quão difícil seria, tecnicamente, implementar isso.

Discuto sobre o bootstrap do contêiner do aplicativo em duas etapas no seguinte tópico:

As alterações que fiz foram apenas sobre dividir o template web do Discourse em três arquivos, mas as tarefas permanecem as mesmas. No entanto, seria ótimo se a equipe do Discourse desse suporte a isso, para que eu não precisasse atualizá-las devido a futuras alterações no template web.