Dépannage des échecs de bootstrap dans Discourse

Je lutte toujours avec le nouveau processus de « pré-emballage » (pre-bundling). Le bootstrap échoue sur mon instance de test et je ne sais pas pourquoi. Notez qu’il s’agit d’une configuration avec une base de données PostgreSQL externe. Les conteneurs s’exécutent derrière un haproxy agissant comme accélérateur SSL. Je ne bootstrap ici que le conteneur web_only. La version de build actuelle (avant le bootstrap) est 3.5.0.beta8-dev, Commits · discourse/discourse · GitHub

Voici le fichier yml qui échoue actuellement :

# IMPORTANT: DÉFINISSEZ UN MOT DE PASSE SECRET dans Postgres pour l'utilisateur Discourse
# TODO: remplacez SOME_SECRET dans ce modèle

templates:
  - "templates/web.template.yml"
  ## Décommentez la ligne suivante pour activer l'écouteur IPv6
  #- "templates/web.ipv6.template.yml"
  - "templates/web.ratelimited.template.yml"
  - "templates/web.socketed.template.yml"
  ## Décommentez ces deux lignes si vous souhaitez ajouter Lets Encrypt (https)
  #- "templates/web.ssl.template.yml"
  #- "templates/web.letsencrypt.ssl.template.yml"

## quels ports TCP/IP ce conteneur doit-il exposer ?
## Si vous souhaitez que Discourse partage un port avec un autre serveur web comme Apache ou nginx,
## consultez https://meta.discourse.org/t/17247 pour plus de détails
expose:
  - "80:80"   # http
  - "443:443" # https

# Utilisez la clé 'links' pour lier les conteneurs entre eux, c'est-à-dire utiliser le drapeau Docker --link.
links:
  - link:
      name: redis
      alias: data

# des arguments supplémentaires pour Docker ?
# docker_args:

params:
  ## Quelle révision Git ce conteneur doit-il utiliser ? (par défaut : 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

  ## Combien de requêtes web simultanées sont prises en charge ? Dépend de la mémoire et des cœurs CPU.
  ## sera défini automatiquement par le bootstrap en fonction des CPU détectés, ou vous pouvez le remplacer
  UNICORN_WORKERS: 4

  ## TODO: Le nom de domaine auquel cette instance Discourse répondra
  DISCOURSE_HOSTNAME: 'forum2.netzwissen.de'

  ## Décommentez si vous souhaitez que le conteneur soit démarré avec le même
  ## nom d'hôte (option -h) que spécifié ci-dessus (par défaut "$hostname-$config")
  #DOCKER_USE_HOSTNAME: true

  ## TODO: Liste d'e-mails séparés par des virgules qui seront définis comme administrateurs et développeurs
  ## lors de l'inscription initiale, par exemple 'user1@example.com,user2@example.com'
  DISCOURSE_DEVELOPER_EMAILS: 'admin@netzwissen.de'

  ## TODO: Le serveur de messagerie SMTP utilisé pour valider les nouveaux comptes et envoyer des notifications
  # L'adresse, le nom d'utilisateur et le mot de passe SMTP sont requis
  # ATTENTION : le caractère '#' dans le mot de passe SMTP peut causer des problèmes !
  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           # (optionnel, par défaut true)
  #DISCOURSE_SMTP_DOMAIN: discourse.example.com    # (requis par certains fournisseurs)
  DISCOURSE_NOTIFICATION_EMAIL: discourse@netzwissen.de    # (adresse d'envoi des notifications)

  ## Si vous avez ajouté le modèle Lets Encrypt, décommentez ci-dessous pour obtenir un certificat SSL gratuit
  #LETSENCRYPT_ACCOUNT_EMAIL: me@example.com

## configurez la connectivité aux bases de données
  DISCOURSE_DB_SOCKET: ''
  DISCOURSE_DB_USERNAME: [xxxxxxxxxxx]
  DISCOURSE_DB_NAME: [xxxxxxxxxxxxxxx]
  DISCOURSE_DB_HOST: [xxxxxxxxxxxxxxx]
  DISCOURSE_DB_PASSWORD: [xxxxxxxxxxxxxxx]
  ## mise en cache redis sur le conteneur voisin
  DISCOURSE_REDIS_HOST: redis

  ## L'adresse CDN http ou https pour cette instance Discourse (configurée pour récupérer)
  ## voir https://meta.discourse.org/t/14857 pour plus de détails
  #DISCOURSE_CDN_URL: https://discourse-cdn.example.com

  ## L'ID de compte et la clé de licence Maxmind pour les recherches d'adresses IP
  ## voir https://meta.discourse.org/t/-/173941 pour plus de détails
  #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

## Les plugins vont ici
## voir https://meta.discourse.org/t/19157 pour plus de détails
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
# certains plugins ont été supprimés, car ils sont désormais intégrés au noyau
# https://meta.discourse.org/t/bundling-more-popular-plugins-with-discourse-core/373574
## = désormais intégré
##          - 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

## Rappelez-vous, ceci est une syntaxe YAML - vous ne pouvez avoir qu'un seul bloc avec un nom
run:
  - exec: echo "Début des commandes personnalisées"

  ## Si vous souhaitez configurer la connexion par mot de passe pour root, décommentez et modifiez :
  ## N'utilisez qu'une seule des lignes suivantes :
  #- exec: /usr/sbin/usermod -p 'PASSWORD_HASH' root
  - exec: /usr/sbin/usermod -p "$(mkpasswd -m sha-256 'xxxxxxxxxxxxxxx')" root

## pour une opération derrière un équilibreur de charge haproxy avec nginx local sur l'hôte du conteneur
  - 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; # remplace $thescheme;
        proxy_set_header X-Real-IP $remote_addr;
        types {

  ## Si vous souhaitez autoriser des utilisateurs supplémentaires, décommentez et modifiez :
  #- exec: ssh-import-id username
  #- exec: ssh-import-id anotherusername

  - exec: echo "Fin des commandes personnalisées"
  - exec: awk -F\# '{print $1;}' ~/.ssh/authorized_keys | awk 'BEGIN { print "Clés SSH autorisées pour ce conteneur:"; } NF\u003e=2 {print $NF;}'

Même lorsque j’ajoute un bloc rm -rf dans le 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

Le bootstrap échoue toujours avec :

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

ÉCHEC
--------------------
Pups::ExecError: cd /var/www/discourse && su discourse -c 'bundle exec rake db:migrate' a échoué avec le retour #<Process::Status: pid 669 exit 1>
Emplacement de l'échec : /usr/local/lib/ruby/gems/3.3.0/gems/pups-1.3.0/lib/pups/exec_command.rb:131:in `spawn'
exec a échoué avec les paramètres {"cd"=>"$home", "tag"=>"migrate", "hook"=>"db_migrate", "cmd"=>["su discourse -c 'bundle exec rake db:migrate'"]}

J’interprète cela comme une erreur lors de la migration de la base de données à “bundle exec rake db:migrate”. Mais quelle est la cause racine ici ? La base de données discourse2 possède déjà l’extension vector requise pour le plugin discourse-ai (déjà installé précédemment) :

postgres=# \c discourse2  
psql (15.12 (Ubuntu 15.12-1.pgdg22.04+1), serveur 13.20 (Ubuntu 13.20-1.pgdg22.04+1))  
Vous êtes maintenant connecté à la base de données "discourse2" en tant qu'utilisateur "postgres".  
discourse2=# \dx  
                                   Liste des extensions installées  
  Nom    | Version | Schéma   |                            Description                               
----------+---------+------------+-------------------------------------------------------------------  
hstore   | 1.7     | public     | type de données pour stocker des ensembles de paires (clé, valeur)  
pg_trgm  | 1.5     | public     | mesure de similarité de texte et recherche d'index basée sur les trigrammes  
plpgsql  | 1.0     | pg_catalog | langage procédural PL/pgSQL  
unaccent | 1.1     | public     | dictionnaire de recherche de texte supprimant les accents  
vector   | 0.8.0   | public     | type de données vectoriel et méthodes d'accès ivfflat et hnsw  
(5 lignes)

Plus tard, je vois également les indices sur les plugins bien que les lignes “git clone” soient toutes commentées dans le yml :

---
HINT: Le plugin 'discourse-openid-connect' est désormais intégré à Discourse et ne doit pas être inclus dans votre configuration de conteneur.
Supprimez la ligne 'git clone https://github.com/discourse/discourse-openid-connect' de votre fichier containers/web_only.yml, puis réessayez.
Pour plus d'informations, consultez https://meta.discourse.org/t/373574
---

Pour être honnête, je suis un peu perdu maintenant ::sleepy_face:

que retourne free -h ?

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

probablement 4 Go de swap

Désolé, ma faute, la sortie a été coupée

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

La VM a déjà 4 Go de mémoire. J’en ai ajouté 2 Go de plus et j’ai lancé un autre ./launcher rebuild web_only^, ce qui a abouti à la même erreur. Je doute donc que nous ayons ici un problème de build lié à l’espace…

Eh bien, j’avais besoin de 2 Go de swap avec 8 Go de RAM.

J’ai réessayé avec 8 Go de RAM, avec le même résultat d’erreur. Notez qu’il s’agit d’une machine virtuelle basée sur le noyau (KVM) sur un hôte proxmox (Features - Proxmox Virtual Environment).

Un invité QEMU/KVM demande de la mémoire à l’hôte au fur et à mesure que le système d’exploitation invité en a besoin, mais il ne retourne pas la mémoire à l’hôte automatiquement si le système d’exploitation invité n’en a plus besoin. Si l’hôte a besoin de mémoire, le noyau demandera aux processus de libérer la RAM inutilisée, ainsi QEMU essaiera de récupérer de la mémoire, mais cela dépend du système d’exploitation invité pour la libérer en premier.

Je n’ai jamais eu de problèmes de mémoire avec la configuration de 4 Go de RAM et 4 CPU, même pas avec le plugin discourse-ai. Les problèmes de démarrage n’ sont apparus qu’après cette annonce de regroupement…

Attendez, est-ce que ce plugin discourse-openid-connect se trouve quelque part dans votre fichier yml ?

C’est un problème de migration, pouvez-vous remonter pour trouver ce qui a échoué lors de la migration ?

Ce plugin discourse-openid-connect se trouve-t-il quelque part dans votre fichier yml ?

C’est un problème de migration, pouvez-vous remonter pour trouver ce qui n’a pas pu être migré ?

Jusqu’à présent, j’avais discourse-openid-connect dans ma liste de plugins. Je l’ai supprimé pour la « construction post-bundling ». Maintenant, il ne me reste que ces plugins dans le fichier yml de construction :

## plugins non inclus dans le bundle
- 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\`
    `
    La construction semble planter à « bundle exec rake db:migrate ». Mais quelques lignes plus haut, je vois un

Gem::LoadError: impossible d'activer multipart-post-2.4.0, déjà activé multipart-post-2.4.1 (Gem::LoadError)

[… ]
discourse-wikified-posts est déjà à la dernière version compatible discourse-workflow est déjà à la dernière version compatible docker_manager est déjà à la dernière version compatible I,
[2025-07-28T06:34:13.916393 #1] INFO -- : `> cd /var/www/discourse `&`& su discourse -c 'bundle exec rake db:migrate' rake aborted! Gem::LoadError: impossible d'activer multipart-post-2.4.0, déjà activé 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' [… ]

Je n’y connais rien en ruby, mais est-ce peut-être un conflit de paquets entre multipart-post-2.4.0 et multipart-post-2.4.1 ?

Merci !
Thommie

Il est et a provoqué la chute de deux de mes constructions. Au moins un des plugins de CDCK utilise une ancienne version.

C’est le système qui fonctionne comme prévu.

Lorsque nous gérons les dépendances de gemmes à l’aide de Gemfile et d’un Gemfile.lock, nous avons dependbot qui analyse les mises à jour, nous nous tenons à jour en utilisant nos processus internes.

En tant que concepteur de plugin, vous pouvez désormais dépendre des dépendances de gemmes que nous expédions dans le cœur.

Cela signifie que vous devriez supprimer multipart-post de votre plugin plugin.rb et simplement le requerir là où vous l’utilisez.

Une chose de moins dont les auteurs de plugins doivent se soucier.

Commentaire utile, merci.

@Thomas_Rother J’ai supprimé la dépendance du plugin, réessayez la compilation.

@merefield @sam :smiley: - succès !! Avec le commit 6be7a44 dans le plugin de Robert GitHub - merefield/discourse-workflow: A workflow system for Topics that implements a configurable multi-stage process, la compilation est réussie. Merci pour l’analyse et la correction !