Solução de problemas de falhas de bootstrap no Discourse

Ainda estou com dificuldades com o novo processo de “pré-empacotamento”. O bootstrap falha na minha instância de teste e não sei o motivo. Note que esta é uma configuração com um banco de dados PostgreSQL externo. Os containers são executados atrás de um haproxy como acelerador SSL. Aqui, estou fazendo o bootstrap apenas do container web_only. A versão atual da build (antes do bootstrap) é 3.5.0.beta8-dev, Commits · discourse/discourse · GitHub

Este é o arquivo yml que está falhando no momento:

# IMPORTANTE: DEFINA UMA SENHA SECRETA no Postgres para o Usuário Discourse
# TODO: altere SOME_SECRET neste modelo

templates:
  - "templates/web.template.yml"
  ## Descomente a próxima linha para ativar o ouvinte IPv6
  #- "templates/web.ipv6.template.yml"
  - "templates/web.ratelimited.template.yml"
  - "templates/web.socketed.template.yml"
  ## Descomente estas duas linhas se desejar adicionar o Lets Encrypt (https)
  #- "templates/web.ssl.template.yml"
  #- "templates/web.letsencrypt.ssl.template.yml"

## quais portas TCP/IP este container deve expor?
## Se você deseja que o Discourse compartilhe uma porta com outro servidor web como Apache ou nginx,
## consulte https://meta.discourse.org/t/17247 para detalhes
expose:
  - "80:80"   # http
  - "443:443" # https

# Use a chave 'links' para vincular containers, ou seja, use a flag Docker --link.
links:
  - link:
      name: redis
      alias: data

# algum argumento extra para o Docker?
# docker_args:

params:
  ## Qual revisão do Git este container deve usar? (padrão: tests-passed)
  #version: tests-passed

env:
  LC_ALL: en_US.UTF-8
  LANG: en_US.UTF-8
  LANGUAGE: en_US.UTF-8
  DISCOURSE_DEFAULT_LOCALE: de

  ## Quantas solicitações web simultâneas são suportadas? Depende de memória e núcleos de CPU.
  ## será definido automaticamente pelo bootstrap com base nas CPUs detectadas, ou você pode substituir
  UNICORN_WORKERS: 4

  ## TODO: O nome de domínio ao qual esta instância do Discourse responderá
  DISCOURSE_HOSTNAME: 'forum2.netzwissen.de'

  ## Descomente se quiser que o container seja iniciado com o mesmo
  ## hostname (opção -h) especificado acima (padrão "$hostname-$config")
  #DOCKER_USE_HOSTNAME: true

  ## TODO: Lista de e-mails separados por vírgula que serão administradores e desenvolvedores
  ## no cadastro inicial, exemplo 'user1@example.com,user2@example.com'
  DISCOURSE_DEVELOPER_EMAILS: 'admin@netzwissen.de'

  ## TODO: O servidor de e-mail SMTP usado para validar novas contas e enviar notificações
  # ENDEREÇO SMTP, nome de usuário e senha são obrigatórios
  # AVISO: o caractere '#' na senha SMTP pode causar problemas!
  DISCOURSE_SMTP_ADDRESS: mail.netzwissen.de
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: discourse@netzwissen.de
  DISCOURSE_SMTP_PASSWORD: [xxxxxxxxxxxxxxxxx}
  #DISCOURSE_SMTP_ENABLE_START_TLS: true           # (opcional, padrão true)
  #DISCOURSE_SMTP_DOMAIN: discourse.example.com    # (obrigatório para alguns provedores)
  DISCOURSE_NOTIFICATION_EMAIL: discourse@netzwissen.de    # (endereço para enviar notificações)

  ## Se você adicionou o modelo Lets Encrypt, descomente abaixo para obter um certificado SSL gratuito
  #LETSENCRYPT_ACCOUNT_EMAIL: me@example.com

## configure a conectividade com os bancos de dados
  DISCOURSE_DB_SOCKET: ''
  DISCOURSE_DB_USERNAME: [xxxxxxxxxxx]
  DISCOURSE_DB_NAME: [xxxxxxxxxxxxxxx]
  DISCOURSE_DB_HOST: [xxxxxxxxxxxxxxx]
  DISCOURSE_DB_PASSWORD: [xxxxxxxxxxxxxxx]
  ## cache redis no container vizinho
  DISCOURSE_REDIS_HOST: redis

  ## O endereço CDN http ou https para esta instância do Discourse (configurado para buscar)
  ## consulte https://meta.discourse.org/t/14857 para detalhes
  #DISCOURSE_CDN_URL: https://discourse-cdn.example.com

  ## O ID da conta Maxmind e a chave de licença para consultas de endereço IP
  ## consulte https://meta.discourse.org/t/-/173941 para detalhes
  #DISCOURSE_MAXMIND_ACCOUNT_ID: 123456
  #DISCOURSE_MAXMIND_LICENSE_KEY: 1234567890123456

volumes:
  - volume:
      host: /mnt/data/discourse/shared/web-only
      guest: /shared
  - volume:
      host: /mnt/data/discourse/shared/web-only/log/var-log
      guest: /var/log

## Plugins vão aqui
## consulte https://meta.discourse.org/t/19157 para detalhes
hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/discourse/discourse-shared-edits.git
# alguns plugins foram removidos, pois agora estão agrupados com o núcleo
# https://meta.discourse.org/t/bundling-more-popular-plugins-with-discourse-core/373574
## = agora agrupado
##          - git clone https://github.com/discourse/discourse-chat-integration.git
##          - git clone https://github.com/discourse/discourse-openid-connect.git
##          - git clone https://github.com/discourse/discourse-calendar.git
##          - git clone https://github.com/angusmcleod/discourse-events.git
##          - git clone https://github.com/discourse/discourse-data-explorer.git
##          - git clone https://github.com/discourse/discourse-reactions.git
##          - git clone https://github.com/discourse/discourse-chat.git
##          - git clone https://github.com/discourse/discourse-ai.git
##          - git clone https://github.com/discourse/discourse-topic-voting.git
##          - git clone https://github.com/discourse/discourse-post-voting.git
##          - git clone https://github.com/discourse/discourse-user-notes.git
##          - git clone https://github.com/discourse/discourse-solved.git
          - git clone https://github.com/discourse/discourse-docs-card-filter.git
          - git clone https://github.com/discourse/discourse-doc-categories.git
##          - git clone https://github.com/discourse/discourse-assign.git
##          - git clone https://github.com/discourse/discourse-templates.git
          - git clone https://github.com/discourse/discourse-saved-searches.git
          - git clone https://github.com/discourse/discourse-tooltips.git
          - git clone https://github.com/discourse/discourse-category-experts.git
          - git clone https://github.com/discourse/discourse-activity-pub.git
          - git clone https://github.com/discourse/discourse-follow.git
          - git clone https://github.com/nathan-nz/discourse-wikified-posts.git
          - git clone https://github.com/discourse/discourse-whos-online.git
          - git clone https://github.com/merefield/discourse-workflow.git

## Lembre-se, esta é sintaxe YAML - você só pode ter um bloco com um nome
run:
  - exec: echo "Início dos comandos personalizados"

  ## Se quiser configurar o login por senha para root, descomente e altere:
  ## Use apenas uma das linhas a seguir:
  #- exec: /usr/sbin/usermod -p 'PASSWORD_HASH' root
  - exec: /usr/sbin/usermod -p "$(mkpasswd -m sha-256 'xxxxxxxxxxxxxxx')" root

## para operação atrás do balanceador de carga haproxy com nginx local no host do container
  - replace:
      filename: /etc/nginx/conf.d/discourse.conf
      from: "types {"
      to: |
        set_real_ip_from 127.0.0.1/24;
        set_real_ip_from 10.0.0.0/24;
        real_ip_header X-Forwarded-For;
        real_ip_recursive on;
        proxy_set_header Host $http_host;
        proxy_set_header X-Request-Start "t=${msec}";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https; # substituiu $thescheme;
        proxy_set_header X-Real-IP $remote_addr;
        types {

  ## Se quiser autorizar usuários adicionais, descomente e altere:
  #- exec: ssh-import-id username
  #- exec: ssh-import-id anotherusername

  - exec: echo "Fim dos comandos personalizados"
  - exec: awk -F\# '{print $1;}' ~/.ssh/authorized_keys | awk 'BEGIN { print "Chaves SSH autorizadas para este container:"; } NF\u003e=2 {print $NF;}'

Mesmo quando adiciono um bloco rm -rf no yml:

- rm -rf discourse-chat-integration  
- rm -rf discourse-openid-connect         
- rm -rf discourse-calendar         
- rm -rf discourse-events         
- rm -rf discourse-data-explorer         
- rm -rf discourse-reactions         
- rm -rf discourse-chat         
- rm -rf discourse-ai         
- rm -rf discourse-topic-voting         
- rm -rf discourse-post-voting         
- rm -rf discourse-user-notes         
- rm -rf discourse-solved         
- rm -rf discourse-assign         
- rm -rf discourse-templates

O bootstrap ainda falha com:

/usr/local/lib/ruby/gems/3.3.0/gems/pups-1.3.0/lib/pups.rb
/usr/local/bin/pups --stdin

FALHA
--------------------
Pups::ExecError: cd /var/www/discourse && su discourse -c 'bundle exec rake db:migrate' falhou com retorno #<Process::Status: pid 669 exit 1>
Localização da falha: /usr/local/lib/ruby/gems/3.3.0/gems/pups-1.3.0/lib/pups/exec_command.rb:131:in `spawn'
exec falhou com os parâmetros {"cd"=>"$home", "tag"=>"migrate", "hook"=>"db_migrate", "cmd"=>["su discourse -c 'bundle exec rake db:migrate'"]}

Eu interpretaria isso como um erro na migração do banco de dados em “bundle exec rake db:migrate”. Mas qual é a causa raiz aqui? O banco de dados discourse2 já tem a extensão vector, que era necessária para o plugin discourse-ai (já instalado anteriormente):

postgres=# \c discourse2  
psql (15.12 (Ubuntu 15.12-1.pgdg22.04+1), server 13.20 (Ubuntu 13.20-1.pgdg22.04+1))  
Você agora está conectado ao banco de dados "discourse2" como usuário "postgres".  
discourse2=# \dx  
                                   Lista de extensões instaladas  
  Nome   | Versão |   Esquema   |                            Descrição                               
----------+---------+------------+-------------------------------------------------------------------  
hstore   | 1.7     | public     | tipo de dados para armazenar conjuntos de pares (chave, valor)  
pg_trgm  | 1.5     | public     | medição de similaridade de texto e busca de índice baseada em trigramas  
plpgsql  | 1.0     | pg_catalog | linguagem procedural PL/pgSQL  
unaccent | 1.1     | public     | dicionário de busca de texto que remove acentos  
vector   | 0.8.0   | public     | tipo de dado vetorial e métodos de acesso ivfflat e hnsw  
(5 linhas)

Mais tarde, também vejo as dicas de plugin, embora as linhas “git clone” estejam todas comentadas no yml:

---
DICA: O plugin 'discourse-openid-connect' agora está agrupado com o Discourse e não deve ser incluído na configuração do seu container.
Remova a linha 'git clone https://github.com/discourse/discourse-openid-connect' do seu arquivo containers/web_only.yml e tente novamente.
Para mais informações, consulte https://meta.discourse.org/t/373574
---

Para ser honesto, estou um pouco perdido agora ::sleepy_face:

o que free -h retorna?

root@docker3a:/var/discourse/containers# free -h
total used free shared buffers cache available
Mem: 3,8Gi 2,0Gi 1,1Gi 3,8Mi 969Mi 1,8Gi

provavelmente 4 GB de swap

Desculpe, minha culpa, a saída foi cortada

root@docker3a:~# free -h
total used free shared. Buff/Cache available
Mem: 3.8Gi 2.0Gi 1.1Gi 3.8Mi 971Mi 1.8Gi
Swap: 974Mi 0B 974Mi

A VM já tem 4 GB de memória. Adicionei mais 2 GB e iniciei outro ./launcher rebuild web_only^, resultando no mesmo erro. Então duvido que tenhamos um problema de compilação relacionado a espaço aqui…

Bem, eu precisava de 2 GB de swap com 8 GB de RAM.

Tentei novamente com 8 GB de RAM, com o mesmo resultado de erro. Note que esta é uma máquina virtual baseada em Kernel (KVM) em um host proxmox (Features - Proxmox Virtual Environment).

Um guest QEMU/KVM solicita memória do host conforme o sistema operacional guest precisa, mas não retorna a memória de volta para o host automaticamente se o sistema operacional guest não precisar mais dela. Se o host precisar de memória, o kernel pedirá aos processos para retornarem RAM não utilizada, assim o QEMU tentará recuperar alguma memória, mas depende do sistema operacional guest liberá-la primeiro.

Nunca tive problemas de memória com a configuração de 4 GB de RAM e 4 CPUs, nem mesmo com o plugin discourse-ai. Problemas de bootstrap só apareceram após este anúncio de agrupamento…

Espere, este plugin discourse-openid-connect está em algum lugar no seu arquivo yml?

Este é um problema de migração, você pode rolar para cima para encontrar o que falhou na migração?

O plugin discourse-openid-connect está em algum lugar no seu arquivo yml?

Este é um problema de migração, você pode rolar para cima para encontrar o que falhou na migração?

Até agora, eu tinha discourse-openid-connect na minha lista de plugins. Removi-o para a “build pós-empacotamento”. Agora, tenho apenas estes plugins restantes no yml de build:

## plugins não empacotados
- git clone https://github.com/discourse/docker_manager.git\\`
- git clone https://github.com/discourse/discourse-shared-edits.git`
- git clone https://github.com/discourse/discourse-docs-card-filter.git`
- git clone https://github.com/discourse/discourse-doc-categories.git`
- git clone https://github.com/discourse/discourse-saved-searches.git`
- git clone https://github.com/discourse/discourse-tooltips.git`
- git clone https://github.com/discourse/discourse-category-experts.git`
- git clone https://github.com/discourse/discourse-activity-pub.git`

  • git clone https://github.com/discourse/discourse-follow.git
  • git clone ``https://github.com/nathan-nz/discourse-wikified-posts.git
  • git clone https://github.com/discourse/discourse-whos-online.git
  • git clone \\\https://github.com/merefield/discourse-workflow.git\\

A build parece travar em ‘bundle exec rake db:migrate’. Mas algumas linhas acima, vejo um

Gem::LoadError: não é possível ativar multipart-post-2.4.0, já ativado multipart-post-2.4.1 (Gem::LoadError)

[… ]
discourse-wikified-posts já está na versão compatível mais recente discourse-workflow já está na versão compatível mais recente docker_manager já está na versão compatível mais recente I,
[2025-07-28T06:34:13.916393 #1] INFO -- : ` cd /var/www/discourse `&` & su discourse -c 'bundle exec rake db:migrate' rake abortou! Gem::LoadError: não é possível ativar multipart-post-2.4.0, já ativado multipart-post-2.4.1 (Gem::LoadError) /var/www/discourse/lib/plugin_gem.rb:25:in `load' /var/www/discourse/lib/plugin/instance.rb:861:in `gem' [… ]

Não tenho conhecimento sobre ruby, mas talvez este seja um conflito de pacotes entre multipart-post-2.4.0 e multipart-post-2.4.1 ?

Obrigado!
Thommie

E fez com que duas das minhas construções caíssem. Pelo menos um dos plugins da CDCK está usando uma versão antiga.

Este é o sistema funcionando como projetado.

Quando gerenciamos dependências de gem usando Gemfile e Gemfile.lock, temos o dependbot verificando atualizações, mantemos atualizado usando nossos processos internos.

Como designer de plugin, você agora pode depender das dependências de gem que enviamos no núcleo.

Isso significa que você deve excluir multipart-post do plugin.rb do seu plugin e simplesmente requisitá-lo de onde você o está usando.

Menos uma coisa com que os autores de plugins precisam se preocupar.

Feedback útil, obrigado.

@Thomas_Rother Removi a dependência do plugin, tente compilar novamente.

@merefield @sam :smiley: - sucesso!! Com o commit 6be7a44 no plugin do Robert GitHub - merefield/discourse-workflow: A workflow system for Topics that implements a configurable multi-stage process a compilação foi bem-sucedida. Obrigado pela análise e correção!