O Discourse consegue enviar imagens Docker frequentes que não precisam ser bootstrapadas?

Acredito que o launcher foi construído antes do docker compose existir:

1 curtida

O Docker Compose não possui a funcionalidade necessária. A construção de templates de arquivos Docker do Discourse permite resultados flexíveis de Docker. Com o Compose, tudo o que você tem é um conjunto possível de Dockerfiles fixos que podem resultar em um monte de contêineres.

Na minha configuração do Discourse, uso um único contêiner com Discourse e nginx usando um socket UNIX. PostgreSQL e Redis são um serviço no host. Isso é um desvio considerável da configuração padrão, mas é possível de imediato.

É parcialmente possível com o Compose, talvez usando o recurso de perfil, que é mal projetado. Mas mesmo assim, é bastante confuso. Ou você precisaria entregar arquivos Compose diferentes para cada variação.

Você está apenas movendo o problema.

Uma configuração Compose limpa para o Discourse seria os seguintes serviços em contêineres separados:

  • Discourse
  • nginx
  • PostgreSQL
  • Redis

Discourse e nginx precisam compartilhar um volume, nada demais.

PostgreSQL e Redis… são coisas que você pode querer hospedar em outro lugar, e não ter um contêiner específico do Discourse para isso. E agora o docker compose se torna um problema: docker compose up -d iniciará seu PostgreSQL indesejado. Ok, então fazemos docker compose --profile postgresql up -d para iniciar a configuração básica do Discourse e um contêiner PostgreSQL. docker compose --profile postgresql --profile redis up -d para a configuração completa de contêineres do Discourse autossuficiente. É melhor você não esquecer um argumento --profile ..., porque então você terá mais problemas.

Então, para uma melhor experiência do usuário (UX), você cria um launcher para cuidar da criação do comando docker compose desejado. Agora estamos meio que de volta onde estávamos. Exceto que modificações no contêiner nginx ainda não são possíveis. Então eu preciso de um contêiner nginx-http e um contêiner nginx-unix que deveriam ser mutuamente exclusivos? …

Claro, o gerenciamento de plugins poderia ser melhor, mas fazer isso com o docker compose, isso será um inferno.

1 curtida

Então, para resumir. Não haverá uma imagem docker adequada.

Quanto à quantidade inacreditável de conhecimento incorreto sobre o que é o docker e como ele opera: What is Docker? | Docker Docs

Você pode compartilhar contêineres enquanto trabalha e ter certeza de que todos com quem você compartilha recebem o mesmo contêiner que funciona da mesma maneira.

Além disso - com o amado “launcher” - como posso executar o discourse em um cluster k8s, dado que não há imagem docker que eu possa consumir e implantar lá?

Riiight…

Este script deve ser executado como root. Por favor, use sudo ou faça login como root primeiro.

Não, obrigado. Não gosto de executar scripts aleatórios da internet. Eu só quero ter uma imagem Docker agradável que eu possa executar com segurança em isolamento :slight_smile:

Eu implantei com sucesso o Discourse em Produção usando o Docker Compose com a imagem publicada, assim como os clientes.

No entanto, sim, é complicado e envolve uma quantidade razoável de trabalho personalizado.

É muito mais fácil manter a instalação padrão com o lançador CDCK, a menos que você realmente precise usar um método diferente porque tem uma opinião forte, arquitetura específica ou outros requisitos especiais.

1 curtida

Usar uma abordagem que não seja “me pegue pela mão” não é “opinativo, específico ou especial” :roll_eyes:

De qualquer forma - a pista é ter a imagem docker original do discourse. Simples assim.

Tentei usar o guia oficial e o “launcher” apenas para brincar com a configuração - sem sucesso (exceto por uma verificação bastante boba se o usuário é root, o que é pedir por problemas).

Então, recorri à imagem bitnami (e ao seu arquivo compose sugerido) de https://hub.docker.com/r/bitnami/discourse e, após um docker compose up (e um monte de erros SQL [o que não é bom] bem como avisos do ruby [mesma ressalva]), consegui uma instância do discourse em execução:

Puro e complicado e “mágica não padrão”…

Então, novamente - por que não há uma imagem regular?

Analisando as fontes e repositórios, descobri que a imagem base é usada (https://hub.docker.com/r/discourse/base/) embora sua versão/marcação me surpreendeu (https://hub.docker.com/r/discourse/base/tags)… Não há versões sensatas, me perguntei? E de fato, olhando o repositório principal, não parecia haver nenhum lançamento, mas ei - pelo menos existem versões devidamente marcadas (Tags · discourse/discourse · GitHub).

Agora, alguém se pergunta - por que não há imagens correspondentes no docker hub principal?

Então, sim - dando uma olhada em como as coisas estão organizadas, concordo:

:smiley:


Por outro lado (ou melhor: “como as coisas deveriam ser”), projeto de exemplo (menor em escopo, mas o raciocínio se mantém): GitHub - miniflux/v2: Minimalist and opinionated feed reader.

Ele tem lançamentos sensatos: Releases · miniflux/v2 · GitHub

Que têm imagens correspondentes corretamente marcadas: https://hub.docker.com/r/miniflux/miniflux/tags

E então a atualização é apenas trocar a versão de x para y (ou usar a tag latest, então um simples stop/pull/start fornecerá a versão atualizada (que executará todas as migrações necessárias automaticamente).

(ah, e a imagem é tipo 70x menor, mas isso é outra história)

Bom trabalho!

Apenas duas perguntas… o que são erros SQL e avisos ruby? Não estou familiarizado com isso. Mas talvez seja porque eu usei o docker e essas coisas de forma totalmente errada :thinking:

Você faz algo assim:

./launcher bootstrap myimage
# o comando que envia essa imagem para o seu local preferido para iniciar imagens
./launcher start-cmd

e isso lhe dá as variáveis de ambiente que você precisa definir para iniciar sua imagem.

Não é realmente tão difícil. Você pode até integrá-lo a uma ação do GitHub para que ele crie sua imagem e a envie para o seu repositório docker. Olhando os commits para docker_compose, parece que há movimentos em andamento para produzir uma imagem que não precise ser inicializada, ou pelo menos facilitar que ela faça algumas das coisas necessárias (migrar o banco de dados, pré-compilar ativos e enviar para s3 e assim por diante). Eu fiz isso para clientes que queriam usar k8s ou o “launcher” de imagens da AWS (não me lembro o nome).

Algumas vezes considerei oferecer tais imagens pré-construídas como um serviço, mas nunca encontrei ninguém que quisesse pagar por isso.

Mas há um monte de pequenas partes. Pelo que entendi, a CDCK usa o launcher para construir imagens, mas elas as iniciam e gerenciam com outras ferramentas, assim como você quer. E quando começaram, o docker-compose ainda não era uma maneira decente de fazer isso e, quando foi, eles já tinham feito o launcher funcionar, então encontrar uma maneira de migrar todos do launcher para outra coisa realmente não era uma opção.

Se as imagens bitnami funcionarem para você, então use-as, mas se não funcionarem, você precisará obter ajuda de alguém que as use, o que é a maioria de ninguém aqui.

2 curtidas

Eh… I already deleted the file and whole setup as I found NodeBB which feels less user hostile when it comes to deployment (guide: Docker - NodeBB Documentation; simple docker-compose file with 3 services: nodebb, postgres and redis: NodeBB/docker-compose-pgsql.yml at master · NodeBB/NodeBB · GitHub; and nicely tagged images: Package nodebb · GitHub)

However, I got the image and here are the relevant errors:

  1. seems like sql schema issue:
postgresql-1  | 2025-07-06 17:15:40.518 GMT [155] ERROR:  relation "translation_overrides" does not exist at character 523
postgresql-1  | 2025-07-06 17:15:40.518 GMT [155] STATEMENT:  SELECT a.attname, format_type(a.atttypid, a.atttypmod),
postgresql-1  | 	       pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
postgresql-1  | 	       c.collname, col_description(a.attrelid, a.attnum) AS comment,
postgresql-1  | 	       attidentity AS identity,
postgresql-1  | 	       attgenerated as attgenerated
postgresql-1  | 	  FROM pg_attribute a
postgresql-1  | 	  LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
postgresql-1  | 	  LEFT JOIN pg_type t ON a.atttypid = t.oid
postgresql-1  | 	  LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
postgresql-1  | 	 WHERE a.attrelid = '"translation_overrides"'::regclass
postgresql-1  | 	   AND a.attnum > 0 AND NOT a.attisdropped
postgresql-1  | 	 ORDER BY a.attnum
postgresql-1  |
postgresql-1  | 2025-07-06 17:15:40.616 GMT [156] ERROR:  relation "translation_overrides" does not exist at character 523
postgresql-1  | 2025-07-06 17:15:40.616 GMT [156] STATEMENT:  SELECT a.attname, format_type(a.atttypid, a.atttypmod),
postgresql-1  | 	       pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
postgresql-1  | 	       c.collname, col_description(a.attrelid, a.attnum) AS comment,
postgresql-1  | 	       attidentity AS identity,
postgresql-1  | 	       attgenerated as attgenerated
postgresql-1  | 	  FROM pg_attribute a
postgresql-1  | 	  LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
postgresql-1  | 	  LEFT JOIN pg_type t ON a.atttypid = t.oid
postgresql-1  | 	  LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
postgresql-1  | 	 WHERE a.attrelid = '"translation_overrides"'::regclass
postgresql-1  | 	   AND a.attnum > 0 AND NOT a.attisdropped
postgresql-1  | 	 ORDER BY a.attnum
  1. ruby warnings (both in discourse as well as sidekiq containers, which kinda makes sense as they use same image :D):
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:5: warning: already initialized constant DiscourseAutomation::Scripts::ADD_USER_TO_GROUP_THROUGH_CUSTOM_FIELD
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:5: warning: previous definition of ADD_USER_TO_GROUP_THROUGH_CUSTOM_FIELD was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:6: warning: already initialized constant DiscourseAutomation::Scripts::APPEND_LAST_CHECKED_BY
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:6: warning: previous definition of APPEND_LAST_CHECKED_BY was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:7: warning: already initialized constant DiscourseAutomation::Scripts::APPEND_LAST_EDITED_BY
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:7: warning: previous definition of APPEND_LAST_EDITED_BY was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:8: warning: already initialized constant DiscourseAutomation::Scripts::AUTO_RESPONDER
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:8: warning: previous definition of AUTO_RESPONDER was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:9: warning: already initialized constant DiscourseAutomation::Scripts::AUTO_TAG_TOPIC
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:9: warning: previous definition of AUTO_TAG_TOPIC was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:10: warning: already initialized constant DiscourseAutomation::Scripts::BANNER_TOPIC
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:10: warning: previous definition of BANNER_TOPIC was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:11: warning: already initialized constant DiscourseAutomation::Scripts::CLOSE_TOPIC
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:11: warning: previous definition of CLOSE_TOPIC was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:12: warning: already initialized constant DiscourseAutomation::Scripts::FLAG_POST_ON_WORDS
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:12: warning: previous definition of FLAG_POST_ON_WORDS was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:13: warning: already initialized constant DiscourseAutomation::Scripts::GIFT_EXCHANGE
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:13: warning: previous definition of GIFT_EXCHANGE was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:14: warning: already initialized constant DiscourseAutomation::Scripts::GROUP_CATEGORY_NOTIFICATION_DEFAULT
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:14: warning: previous definition of GROUP_CATEGORY_NOTIFICATION_DEFAULT was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:15: warning: already initialized constant DiscourseAutomation::Scripts::PIN_TOPIC
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:15: warning: previous definition of PIN_TOPIC was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:16: warning: already initialized constant DiscourseAutomation::Scripts::POST
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:16: warning: previous definition of POST was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:17: warning: already initialized constant DiscourseAutomation::Scripts::SEND_PMS
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:17: warning: previous definition of SEND_PMS was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:18: warning: already initialized constant DiscourseAutomation::Scripts::SUSPEND_USER_BY_EMAIL
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:18: warning: previous definition of SUSPEND_USER_BY_EMAIL was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:19: warning: already initialized constant DiscourseAutomation::Scripts::TOPIC
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:19: warning: previous definition of TOPIC was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:20: warning: already initialized constant DiscourseAutomation::Scripts::TOPIC_REQUIRED_WORDS
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:20: warning: previous definition of TOPIC_REQUIRED_WORDS was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:21: warning: already initialized constant DiscourseAutomation::Scripts::USER_GLOBAL_NOTICE
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:21: warning: previous definition of USER_GLOBAL_NOTICE was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:22: warning: already initialized constant DiscourseAutomation::Scripts::USER_GROUP_MEMBERSHIP_THROUGH_BADGE
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:22: warning: previous definition of USER_GROUP_MEMBERSHIP_THROUGH_BADGE was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:23: warning: already initialized constant DiscourseAutomation::Scripts::ZAPIER_WEBHOOK
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:23: warning: previous definition of ZAPIER_WEBHOOK was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:5: warning: already initialized constant DiscourseAutomation::Triggers::AFTER_POST_COOK
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:5: warning: previous definition of AFTER_POST_COOK was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:6: warning: already initialized constant DiscourseAutomation::Triggers::API_CALL
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:6: warning: previous definition of API_CALL was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:7: warning: already initialized constant DiscourseAutomation::Triggers::CATEGORY_CREATED_EDITED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:7: warning: previous definition of CATEGORY_CREATED_EDITED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:8: warning: already initialized constant DiscourseAutomation::Triggers::PM_CREATED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:8: warning: previous definition of PM_CREATED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:9: warning: already initialized constant DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:9: warning: previous definition of TOPIC_TAGS_CHANGED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:10: warning: already initialized constant DiscourseAutomation::Triggers::POINT_IN_TIME
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:10: warning: previous definition of POINT_IN_TIME was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:11: warning: already initialized constant DiscourseAutomation::Triggers::POST_CREATED_EDITED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:11: warning: previous definition of POST_CREATED_EDITED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:12: warning: already initialized constant DiscourseAutomation::Triggers::RECURRING
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:12: warning: previous definition of RECURRING was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:13: warning: already initialized constant DiscourseAutomation::Triggers::STALLED_TOPIC
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:13: warning: previous definition of STALLED_TOPIC was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:14: warning: already initialized constant DiscourseAutomation::Triggers::STALLED_WIKI
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:14: warning: previous definition of STALLED_WIKI was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:15: warning: already initialized constant DiscourseAutomation::Triggers::TOPIC
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:15: warning: previous definition of TOPIC was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:16: warning: already initialized constant DiscourseAutomation::Triggers::USER_ADDED_TO_GROUP
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:16: warning: previous definition of USER_ADDED_TO_GROUP was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:17: warning: already initialized constant DiscourseAutomation::Triggers::USER_BADGE_GRANTED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:17: warning: previous definition of USER_BADGE_GRANTED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:18: warning: already initialized constant DiscourseAutomation::Triggers::USER_FIRST_LOGGED_IN
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:18: warning: previous definition of USER_FIRST_LOGGED_IN was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:19: warning: already initialized constant DiscourseAutomation::Triggers::USER_PROMOTED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:19: warning: previous definition of USER_PROMOTED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:20: warning: already initialized constant DiscourseAutomation::Triggers::USER_REMOVED_FROM_GROUP
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:20: warning: previous definition of USER_REMOVED_FROM_GROUP was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:21: warning: already initialized constant DiscourseAutomation::Triggers::USER_UPDATED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:21: warning: previous definition of USER_UPDATED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/recurring.rb:6: warning: already initialized constant DiscourseAutomation::Triggers::Recurring::RECURRENCE_CHOICES
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/recurring.rb:6: warning: previous definition of RECURRENCE_CHOICES was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/stalled_wiki.rb:6: warning: already initialized constant DiscourseAutomation::Triggers::StalledWiki::DURATION_CHOICES
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/stalled_wiki.rb:6: warning: previous definition of DURATION_CHOICES was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb:7: warning: already initialized constant DiscourseAutomation::Triggers::TopicTagsChanged::TriggerOn::TAGS_ADDED_OR_REMOVED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb:7: warning: previous definition of TAGS_ADDED_OR_REMOVED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb:8: warning: already initialized constant DiscourseAutomation::Triggers::TopicTagsChanged::TriggerOn::TAGS_ADDED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb:8: warning: previous definition of TAGS_ADDED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb:9: warning: already initialized constant DiscourseAutomation::Triggers::TopicTagsChanged::TriggerOn::TAGS_REMOVED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb:9: warning: previous definition of TAGS_REMOVED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb:11: warning: already initialized constant DiscourseAutomation::Triggers::TopicTagsChanged::TriggerOn::MODES
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb:11: warning: previous definition of MODES was here
sidekiq-1     | 2025-07-06T17:15:52.699Z pid=1 tid=4ox INFO: Booted Rails 7.2.2.1 application in production environment

Esse é um excelente ponto. Não há realmente uma boa razão pela qual este script não possa ser executado como não-root.

O script de configuração é o único que realmente precisa de root, pela parte assustadora onde ele sugere executar o script de instalação do docker a partir da internet. Então, até mesmo isso pode ser alterado para ser executado como não-root.

O script do lançador não precisa de root, ele apenas precisa de acesso de escrita a /var/discourse e permissão para gerenciar contêineres docker.

1 curtida

Eh… :slight_smile:

O script nem sequer precisa de acesso a /var/discourse (por que ele tem?).

Todo o problema decorre de algumas coisas:

  1. enorme mal-entendido sobre o que é docker, como funciona e o que ele possibilita
  2. colagem da noção de que docker = docker-compose (não é!)

Você pode ter uma configuração completamente contida que virtualmente não toca no ambiente do host…

Após muita pesquisa, parece que todo o script de “configuração” foi criado para tornar a instalação o mais simples possível para a pessoa muito não técnica. Ele verifica, guia o usuário e configura tudo. Isso pode ser algo bom, mas falha completamente em qualquer coisa que tente se desviar, mesmo que minimamente, do caminho previsto.

Na configuração mais básica, você pode nem precisar de acesso a nenhum diretório do host - tudo ficará contido dentro de um ambiente limitado (a imagem será usada para criar o contêiner e todo o armazenamento necessário seria tratado via volumes docker [isso tem problemas quando você quer migrar para outro lugar ou acessar os arquivos, mas estamos falando do básico]).

Ele também tenta garantir que o DNS esteja correto, tenta configurar certificados, proxy reverso, SMTP e o que mais - novamente, completamente bom fornecer essa configuração fácil.

MAS!

O problema NÃO é jogar isso fora, mas ALÉM DISSO fornecer uma imagem docker simples (ela já existe, é usada pelos scripts e modelos usados pelo script! discourse_docker/templates/postgres.template.yml at main · discourse/discourse_docker · GitHub & discourse_docker/launcher at main · discourse/discourse_docker · GitHub) com

  1. versionamento adequado: você marca a imagem com a versão lançada do discourse (3.4.5 ou o que for)
  2. documentação sensata e simples das variáveis de ambiente esperadas (controlando a conectividade do banco de dados/redis/etc.) e possíveis caminhos/volumes que podem ser montados no host.

Apenas isso…

Dê uma olhada no guia miniflux mencionado anteriormente: Miniflux Installation with Docker - ele fornece detalhes sobre a imagem (e quais repositórios as servem) e as variáveis de ambiente possíveis para configurá-la.
Ou a imagem docker do MySQL: https://hub.docker.com/_/mysql - a mesma coisa - um guia que explica o que é possível configurar (veja especialmente a seção: “Variáveis de Ambiente”).

Ninguém diz: “você tem que usar o launcher do mysql para construir a imagem do mysql para que você possa usá-la”, ou redis para isso - neste caso, você simplesmente usa imagens existentes e essa é a pista e o cerne do uso do docker. No entanto, no caso do discourse, de repente essa é uma solução “ruim” e todos gritam: “você tem que construir sua própria imagem!” – por quê!?

Não. Por causa de plugins.

1 curtida

Uhm… tive que pesquisar um pouco sobre plugins e, novamente, tenho que dizer/citar:

:smiley:

Então, o que eu fiz - fui para a seção de plugins, cliquei no primeiro plugin procurando por instruções e guia de instalação (Plugin directory | Discourse - Civilized DiscussionSign in with Apple | Discourse - Civilized DiscussionDiscourse Apple AuthenticationInstall plugins on a self-hosted site) e… meu Deus - que “bagunça” complicada.

Por que você precisaria de uma nova imagem apenas para ter plugins? Com o docker você pode apenas especificar um diretório de montagem para plugins e colocá-lo lá…

Eu não sou um cara de Ruby, então as coisas podem ser mais estranhas aqui, mas, por exemplo, no mundo Java, você apenas solta um jar com o plugin para que ele seja carregado e pronto - você o tem em execução. E você está usando a mesma imagem que todo mundo…

(Não estou dizendo que não está confuso, apenas explicando por que as coisas são como são)

Por causa do pipeline de assets do Ember.

O que também seria uma bagunça, porque você não quer ter essas dependências externamente.

2 curtidas

Este aqui: GitHub - ember-engines/ember-asset-loader: Asset loading support for Ember applications?

Por que não, então?

Plugins podem ser processados em tempo real, isso também é feito ao atualizar um plugin. Com um pouco de mágica, você também pode adicionar um novo plugin a uma instância em execução sem reconstruir o contêiner. Portanto, montar um volume de plugin em um contêiner deve ser possível (com um monte de mudanças).

O principal problema que vejo é com a atualização do Discourse. Isso pode ser feito atualmente com uma instância em execução. A atualização basicamente reconstrói o Discourse. Se o Discourse vier de uma imagem pré-construída, você não poderá alterar esses arquivos. Portanto, atualizar com tempo de inatividade zero/mínimo provavelmente exigirá bastante trabalho.

Isso é algo que eu não entendo (provavelmente falta contexto em termos de Ruby…).

Em geral, com docker/containers/orquestração, você pode ter implantações blue-green/red-black onde você prepara um novo contêiner com a nova versão e muda o tráfego assim que estiver pronto. No entanto, em geral, para implantações menores, isso não deveria ser um problema, pois na maioria das vezes a inicialização do serviço (contêiner) deve levar apenas alguns segundos, então o tempo de inatividade da troca de versões deve ser mínimo (o maior problema é ter que executar atualizações de esquema, mas isso se aplica independentemente de você reconstruir a imagem ou não).

Sim, mas não é assim que funciona atualmente, então essa é a parte que precisa de trabalho. Como você vai fazer isso a partir da interface de administração do Discourse. Como você vai reduzir o contêiner azul enquanto inicia o contêiner verde (os sistemas não têm recursos infinitos, então antes de iniciar o azul, você quer reduzir os workers do unicorn no verde.) Ou você pode simplesmente fazer com que o verde esteja inativo e o azul suba.

Há muitas coisas que precisam ser descobertas e resolvidas. Tanto de uma perspectiva técnica quanto de uma perspectiva de administrador. A atualização com um clique a partir da interface de administração é um recurso valioso.

1 curtida

Plugins e imagens personalizadas ainda precisam ser criados, mas para a construção vanilla para o compose está se tornando ao alcance nos dias de hoje - fiz um pequeno experimento de prova de conceito aqui para quem estiver curioso.

Obviamente, como estes são todos os meus repositórios (não da Discourse™), isto não é nada oficial, então o seu resultado pode variar, e definitivamente não espere suporte oficial :dragon: Estou lançando isto aqui, já que foi mencionado que as pessoas já estão executando bitnami e outras formas não sancionadas de execução.

As imagens postgres (ou pgvector) prontas para uso não funcionam para o Discourse - o Discourse precisa alterar a configuração padrão, não se conecta via superusuário, suporta locais e precisa suportar atualizações do postgres sem que um administrador do Discourse precise despejar/restaurar.

4 curtidas

Eh… essa é, acho que a diferença crucial e essa “atualização da interface de administração” é um tanto uma lembrança dos velhos tempos, quando você só tinha “hospedagem web” com interpretador php, então tudo era construído em torno dessa noção. E acho que isso se transferiu para como o Discourse funciona e se espera que seja gerenciado.

Bem, essa é outra coisa que notei - o discourse é bastante pesado (o contêiner começou a consumir recursos durante a inicialização em um nível assustador), então sim - pode ser um problema.

Como eles são “criados” no contexto de Ruby (que é em sua maioria uma linguagem interpretada e não compilada)?

Não seria melhor tentar usar soluções prontas? Mesmo para a configuração do postgres, ela pode ser facilmente alterada simplesmente fornecendo/montando um arquivo postgresql.conf personalizado, sem a necessidade de uma imagem totalmente personalizada com configuração embutida… e mesmo assim - se isso for necessário, o discourse poderia fornecer tal imagem pré-construída que seria apenas baixada em vez de reconstruída toda vez…

Esta “interface de atualização de administrador” é um plugin (chamado “docker manager”). Você não precisa incluí-lo se tiver outra maneira de fazer atualizações online.