Mi Discourse está caído. ¿Problema de certificado?

Hola @WesPenre :slight_smile:

El error debería estar más arriba de lo que incluye tu captura de pantalla. ¿Podrías pegar tu log completo aquí para que la gente pueda ver cuál podría ser el problema?

¿Alguien puede decirme cómo crear un registro de errores si no puedo iniciar sesión en Discourse? ¿Puedo encontrarlo en WinSCP? Si es así, ¿cuál es el directorio y el nombre del registro?

¿Es esto? Este es el archivo del lanzador:

#!/usr/bin/env bash

usage () {
  echo "Uso: launcher COMANDO CONFIG [--skip-prereqs] [--docker-args CADENA]"
  echo "Comandos:"
  echo "    start:       Iniciar/inicializar un contenedor"
  echo "    stop:        Detener un contenedor en ejecución"
  echo "    restart:     Reiniciar un contenedor"
  echo "    destroy:     Detener y eliminar un contenedor"
  echo "    enter:       Abrir una shell para ejecutar comandos dentro del contenedor"
  echo "    logs:        Ver los registros de Docker de un contenedor"
  echo "    bootstrap:   Inicializar un contenedor para la configuración basada en una plantilla"
  echo "    run:         Ejecutar el comando dado con la configuración en el contexto de la última imagen inicializada"
  echo "    rebuild:     Reconstruir un contenedor (destruir el antiguo, inicializar, iniciar el nuevo)"
  echo "    cleanup:     Eliminar todos los contenedores que han estado detenidos por > 24 horas"
  echo "    start-cmd:   Generar el comando de docker usado para iniciar el contenedor"
  echo
  echo "Opciones:"
  echo "    --skip-prereqs             No verificar los requisitos previos del lanzador"
  echo "    --docker-args              Argumentos adicionales para pasar al ejecutar docker"
  echo "    --skip-mac-address         No asignar una dirección MAC"
  echo "    --run-image                Sobrescribir la imagen usada para ejecutar el contenedor"
  exit 1
}

# para una posible reejecución posterior
SAVED_ARGV=("$@")

comando=$1
config=$2

# user_args_argv se asigna una sola vez cuando se analiza el vector de argumentos.
user_args_argv=""
# user_args es mutable: su valor puede cambiar cuando se analizan las plantillas.
# Superconjunto de user_args_argv.
user_args=""

user_run_image=""

if [[ $comando == "run" ]]; then
  run_command=$3
fi

while [ ${#} -gt 0 ]; do
  case "${1}" in
  --debug)
    DEBUG="1"
    ;;
  --skip-prereqs)
    SKIP_PREREQS="1"
    ;;
  --skip-mac-address)
    SKIP_MAC_ADDRESS="1"
    ;;
  --docker-args)
    user_args_argv="$2"
    user_args="$user_args_argv"
    shift
    ;;
  --run-image)
    user_run_image="$2"
    shift
    ;;
  esac

  shift 1
done

if [ -z "$comando" -o -z "$config" -a "$comando" != "cleanup" ]; then
  usage
fi

# Docker no le gustan los caracteres mayúsculas, espacios o caracteres especiales, atrápalos ahora antes de construir todo y luego descubrirlo
re='[[:upper:]/ !@#$%^&*()+~`=]'
if [[ $config =~ $re ]];
  then
    echo
    echo "ERROR: El nombre de la configuración '$config' no debe contener caracteres mayúsculas, espacios o caracteres especiales. Corrija el nombre de la configuración y vuelva a ejecutar $0."
    echo
    exit 1
fi

cd "$(dirname "$0")"

pups_version='v1.0.3'
docker_min_version='17.03.1'
docker_rec_version='17.06.2'
git_min_version='1.8.0'
git_rec_version='1.8.0'
kernel_min_version='4.4.0'

config_file=containers/"$config".yml
cidbootstrap=cids/"$config"_bootstrap.cid
local_discourse=local_discourse
image="discourse/base:2.0.20230217-0055"
image_stable="discourse/base:2.0.20230116-0051"
docker_path=`which docker.io 2> /dev/null || which docker`
git_path=`which git`

if [ "${SUPERVISED}" = "true" ]; then
  restart_policy="--restart=no"
  attach_on_start="-a"
  attach_on_run="-a stdout -a stderr"
else
  attach_on_run="-d"
fi

if [ -n "$DOCKER_HOST" ]; then
  docker_ip=`sed -e 's/^tcp:\/\/\(.*\):.*$/\1/' <<< "$DOCKER_HOST"`
elif [ -x "$(which ip 2>/dev/null)" ]; then
  docker_ip=`ip addr show docker0 | \
                  grep 'inet ' | \
                  awk '{ split($2,a,"/"); print a[1] }';`
else
  docker_ip=`ifconfig | \
                  grep -B1 "inet addr" | \
                  awk '{ if ( $1 == "inet" ) { print $2 } else if ( $2 == "Link" ) { printf "%s:" ,$1 } }' | \
                  grep docker0 | \
                  awk -F: '{ print $3 }';`
fi

# De https://stackoverflow.com/a/44660519/702738
compare_version() {
    if [[ $1 == $2 ]]; then
        return 1
    fi
    local IFS=.
    local i a=(${1%%[^0-9.]*}) b=(${2%%[^0-9.]*})
    local arem=${1#${1%%[^0-9.]*}} brem=${2#${2%%[^0-9.]*}}
    for ((i=0; i<${#a[@]} || i<${#b[@]}; i++)); do
        if ((10#${a[i]:-0} < 10#${b[i]:-0})); then
            return 1
        elif ((10#${a[i]:-0} > 10#${b[i]:-0})); then
            return 0
        fi
    done
    if [ "$arem" '<' "$brem" ]; then
        return 1
    elif [ "$arem" '>' "$brem" ]; then
        return 0
    fi
    return 1
}

fatal () {
  echo -e "\n$1\n"
  exit "${2:-1}"
}

install_docker() {
  echo "Docker no está instalado, necesitarás instalar Docker para poder ejecutar el lanzador"
  echo "Consulta https://docs.docker.com/installation/"
  exit 1
}

pull_image() {
  # Agregar un solo reintento para evitar errores TLS de dockerhub
  $docker_path pull $image || $docker_path pull $image
}

check_prereqs() {

  if [ -z $docker_path ]; then
    install_docker
  fi

  # 1. ¿El demonio de docker está en ejecución?
  # enviamos stderr a /dev/null porque no nos importan las advertencias,
  # generalmente se queja del swap, lo cual no importa
  test=`$docker_path info 2> /dev/null`
  if [[ $? -ne 0 ]] ; then
    echo "No se puede conectar al demonio de docker: verifique que esté en ejecución y que tenga acceso"
    exit 1
  fi

  # 2. ¿Se está ejecutando un controlador de almacenamiento aprobado?
  if ! $docker_path info 2> /dev/null | egrep -q 'Storage Driver: (btrfs|aufs|zfs|overlay2)$'; then
    echo "Su instalación de Docker no está utilizando un controlador de almacenamiento compatible. Si procedemos, es posible que tenga una instalación rota."
    echo "overlay2 es el controlador de almacenamiento recomendado, aunque zfs y aufs también pueden funcionar."
    echo "Se sabe que otros controladores de almacenamiento son problemáticos."
    echo "Puede indicar qué sistema de archivos está utilizando ejecutando \"docker info\" y buscando la línea 'Storage Driver'."
    echo
    echo "Si desea continuar de todos modos utilizando su controlador de almacenamiento no compatible existente,"
    echo "lea el código fuente del lanzador y averigüe cómo omitir esta verificación."
    exit 1
  fi

  # 3. ¿Se está ejecutando la versión recomendada de docker?
  test=($($docker_path --version))  # Obtener la cadena de versión de docker
  test=${test[2]//,/}  # Obtener solo la versión y eliminar la coma si existe

  # Al menos la versión mínima de docker
  if compare_version "${docker_min_version}" "${test}"; then
    echo "ERROR: La versión de Docker ${test} no es compatible, actualice a al menos ${docker_min_version}, o a la recomendada ${docker_rec_version}"
    exit 1
  fi

  # Recomendar una versión más reciente de docker
  if compare_version "${docker_rec_version}" "${test}"; then
    echo "ADVERTENCIA: La versión de Docker ${test} está obsoleta, se recomienda actualizar a ${docker_rec_version} o superior."
  fi

  arm=false
  case $(uname -m) in
    armv7l)
      echo "ERROR: arm de 32 bits no es compatible. Verifique si su hardware admite arm64, que es compatible en capacidad experimental."
      exit 1
      ;;
    aarch64 | arm64)
      echo "ADVERTENCIA: El soporte para aarch64 es experimental en este momento. Por favor, informe cualquier problema en https://meta.discourse.org/tag/arm"
      image="discourse/base:aarch64"
      arm=true
      ;;
    x86_64)
      echo "Arquitectura x86_64 detectada."
      ;;
    *)
      echo "ERROR: arquitectura desconocida detectada."
      exit 1
      ;;
  esac


  # 4. la imagen de docker de discourse está descargada
  test=`$docker_path images | awk '{print $1 ":" $2 }' | grep "$image"`

  # El soporte experimental de arm está en una etiqueta fija, siempre descargar
  if [ -z "$test" ] || [ $arm = true ]; then
    echo
    echo "ADVERTENCIA: Estamos a punto de comenzar a descargar la imagen base de Discourse"
    echo "Este proceso puede tardar desde unos minutos hasta una hora, dependiendo de la velocidad de su red"
    echo
    echo "Por favor, tenga paciencia"
    echo

    pull_image
  fi

  # usar una imagen más antigua para estable
  version=$(cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
      "require 'yaml'; puts YAML.load(STDIN.readlines.join)['params']['version']")
  if [ "$version" = "stable" ]; then
    image=$image_stable
    pull_image
  fi

  # 5. ¿se está ejecutando la versión recomendada de git?
  test=($($git_path --version))  # Obtener la cadena de versión de git
  test=${test[2]//,/}  # Obtener solo la versión y eliminar la coma si existe

  # Al menos la versión mínima
  if compare_version "${git_min_version}" "${test}"; then
    echo "ERROR: La versión de Git ${test} no es compatible, actualice a al menos ${git_min_version}, o a la recomendada ${git_rec_version}"
    exit 1
  fi

  # Recomendar la mejor versión
  if compare_version "${git_rec_version}" "${test}"; then
    echo "ADVERTENCIA: La versión de Git ${test} está obsoleta, se recomienda actualizar a ${git_rec_version} o superior."
  fi

  # Verificar la versión mínima del kernel debido a https://bugs.ruby-lang.org/issues/13885
  test=($(uname -r))

  # Al menos la versión mínima
  if compare_version "${kernel_min_version}" "${test}"; then
    echo "ERROR: La versión del kernel ${test} no es compatible, actualice a al menos ${kernel_min_version}"
    exit 1
  fi

  # 6. ¿puede adjuntar stderr / out / tty?
  test=`$docker_path run $user_args -i --rm -a stdout -a stderr $image echo working`
  if [[ "$test" =~ "working" ]] ; then : ; else
    echo "Su instalación de Docker no está funcionando correctamente"
    echo
    echo "Ver: https://meta.discourse.org/t/docker-error-on-bootstrap/13657/18?u=sam"
    exit 1
  fi

  # 7. suficiente espacio para el inicio en la carpeta de docker
  folder=`$docker_path info --format '{{.DockerRootDir}}'`
  safe_folder=${folder:-/var/lib/docker}
  if [[ -d $safe_folder && $(stat -f --format="%a*%S" $safe_folder)/1024**3 -lt 5 ]] ; then
    echo "Tiene menos de 5 GB de espacio libre en el disco donde se encuentra $safe_folder. Necesitará más espacio para continuar"
    df -h $safe_folder
    echo
    if tty >/dev/null; then
      read -p "¿Le gustaría intentar recuperar espacio limpiando las imágenes y contenedores de docker en el sistema? (y/N)" -n 1 -r
      echo
      if [[ $REPLY =~ ^[Yy]$ ]]
      then
        $docker_path container prune --force --filter until=24h >/dev/null
        $docker_path image prune --all --force --filter until=24h >/dev/null
        echo "Si la limpieza fue exitosa, puede intentarlo de nuevo ahora"
      fi
    fi
    exit 1
  fi

  # 8. el archivo de definición del contenedor es accesible y no es inseguro (legible por todos)
  if [[ ! -e "$config_file" || ! -r "$config_file" ]]; then
    echo "ERROR: $config_file no existe o no es legible."
    echo
    echo "Configuraciones disponibles ( `cd containers && ls -dm *.yml | tr -s '\n' ' ' | awk '{ gsub(/\.yml/, ""); print }'`)"
    exit 1
  elif [[ "$(find $config_file -perm -004)" ]]; then
    echo "ADVERTENCIA: el archivo $config_file es legible por todos. Puede asegurar este archivo ejecutando: chmod o-rwx $config_file"
  fi
}


if [ -z "$SKIP_PREREQS" ] && [ "$comando" != "cleanup" ]; then
  check_prereqs
fi

set_volumes() {
  volumes=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
        "require 'yaml'; puts YAML.load(STDIN.readlines.join)['volumes'].map{|v| '-v ' << v['volume']['host'] << ':' << v['volume']['guest'] << ' '}.join"`
}

set_links() {
    links=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
        "require 'yaml'; puts YAML.load(STDIN.readlines.join)['links'].map{|l| '--link ' << l['link']['name'] << ':' << l['link']['alias'] << ' '}.join"`
}

find_templates() {
    local templates=`cat $1 | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
      "require 'yaml'; puts YAML.load(STDIN.readlines.join)['templates']"`

    local arrTemplates=${templates// / }

    if [ ! -z "$templates" ]; then
      echo $templates
    else
      echo ""
    fi
}

set_template_info() {
    templates=$(find_templates $config_file)

    arrTemplates=(${templates// / })
    config_data=$(cat $config_file)

    input="hack: true"

    for template in "${arrTemplates[@]}"
    do
      [ ! -z $template ] && {
        input="$input _FILE_SEPERATOR_ $(cat $template)"
      }
    done

    # siempre queremos nuestro archivo de configuración al final para que tenga prioridad
    input="$input _FILE_SEPERATOR_ $config_data"

    read -r -d '' env_ruby << 'RUBY'
    require 'yaml'

    input=STDIN.readlines.join
    # por defecto a UTF-8 por el bien de la base de datos
    env = {'LANG' => 'en_US.UTF-8'}
    input.split('_FILE_SEPERATOR_').each do |yml|
       yml.strip!
       begin
         env.merge!(YAML.load(yml)['env'] || {})
       rescue Psych::SyntaxError => e
        puts e
        puts "*ERROR."
       rescue => e
        puts yml
        p e
       end
    end
    env.each{|k,v| puts "*ERROR." if v.is_a?(Hash)}
    puts env.map{|k,v| "-e\n#{k}=#{v}" }.join("\n")
RUBY

    tmp_input_file=$(mktemp)

    echo "$input" > "$tmp_input_file"
    raw=`exec cat "$tmp_input_file" | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e "$env_ruby"`

    rm -f "$tmp_input_file"

    env=()
    ok=1
    while read i; do
      if [ "$i" == "*ERROR." ]; then
        ok=0
      elif [ -n "$i" ]; then
        env[${#env[@]}]="${i//\{\{config\}\}/${config}}"
      fi
    done <<< "$raw"

    if [ "$ok" -ne 1 ]; then
      echo "${env[@]}"
      echo "Error de sintaxis YAML. Por favor, verifique sus archivos de configuración containers/*.yml."
      exit 1
    fi

    # etiquetas
    read -r -d '' labels_ruby << 'RUBY'
    require 'yaml'

    input=STDIN.readlines.join
    labels = {}
    input.split('_FILE_SEPERATOR_').each do |yml|
       yml.strip!
       begin
         labels.merge!(YAML.load(yml)['labels'] || {})
       rescue Psych::SyntaxError => e
        puts e
        puts "*ERROR."
       rescue => e
        puts yml
        p e
       end
    end
    puts labels.map{|k,v| "-l\n#{k}=#{v}" }.join("\n")
RUBY

    tmp_input_file=$(mktemp)

    echo "$input" > "$tmp_input_file"
    raw=`exec cat "$tmp_input_file" | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e "$labels_ruby"`

    rm -f "$tmp_input_file"

    labels=()
    ok=1
    while read i; do
      if [ "$i" == "*ERROR." ]; then
        ok=0
      elif [ -n "$i" ]; then
        labels[${#labels[@]}]=$(echo $i | sed s/{{config}}/${config}/g)
      fi
    done <<< "$raw"

    if [ "$ok" -ne 1 ]; then
      echo "${labels[@]}"
      echo "Error de sintaxis YAML. Por favor, verifique sus archivos de configuración containers/*.yml."
      exit 1
    fi

    # exponer
    read -r -d '' ports_ruby << 'RUBY'
    require 'yaml'

    input=STDIN.readlines.join
    ports = []
    input.split('_FILE_SEPERATOR_').each do |yml|
       yml.strip!
       begin
         ports += (YAML.load(yml)['expose'] || [])
       rescue Psych::SyntaxError => e
        puts e
        puts "*ERROR."
       rescue => e
        puts yml
        p e
       end
    end
    puts ports.map { |p| p.to_s.include?(':') ? "-p\n#{p}" : "--expose\n#{p}" }.join("\n")
RUBY

    tmp_input_file=$(mktemp)

    echo "$input" > "$tmp_input_file"
    raw=`exec cat "$tmp_input_file" | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e "$ports_ruby"`

    rm -f "$tmp_input_file"

    ports=()
    ok=1
    while read i; do
      if [ "$i" == "*ERROR." ]; then
        ok=0
      elif [ -n "$i" ]; then
        ports[${#ports[@]}]=$i
      fi
    done <<< "$raw"

    if [ "$ok" -ne 1 ]; then
      echo "${ports[@]}"
      echo "Error de sintaxis YAML. Por favor, verifique sus archivos de configuración containers/*.yml."
      exit 1
    fi

   merge_user_args
}

if [ -z $docker_path ]; then
  install_docker
fi

[ "$comando" == "cleanup" ] && {
  $docker_path container prune --filter until=1h
  $docker_path image prune --all --filter until=1h

  if [ -d /var/discourse/shared/standalone/postgres_data_old ]; then
    echo
    echo "Se detectó un clúster de datos de copia de seguridad antiguo de PostgreSQL que ocupa $(du -hs /var/discourse/shared/standalone/postgres_data_old | awk '{print $1}') detectado"
    read -p "¿Le gustaría eliminarlo? (y/N): " -n 1 -r && echo

    if [[ $REPLY =~ ^[Yy]$ ]]; then
      echo "eliminando el antiguo clúster de datos de PostgreSQL en /var/discourse/shared/standalone/postgres_data_old..."
      rm -rf /var/discourse/shared/standalone/postgres_data_old*
    else
      exit 1
    fi
  fi

  exit 0
}

docker_version=($($docker_path --version))
docker_version=${test[2]//,/}
restart_policy=${restart_policy:---restart=always}

set_existing_container(){
  existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
}

run_stop() {

  set_existing_container

  if [ ! -z $existing ]
     then
       (
        set -x
        $docker_path stop -t 30 $config
       )
     else
       echo "$config no estaba iniciada !"
       echo "./discourse-doctor puede ayudar a diagnosticar el problema."
       exit 1
  fi
}

set_run_image() {
  run_image=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
    "require 'yaml'; puts YAML.load(STDIN.readlines.join)['run_image']"`

  if [ -n "$user_run_image" ]; then
    run_image=$user_run_image
  elif [ -z "$run_image" ]; then
    run_image="$local_discourse/$config"
  fi
}

set_boot_command() {
  boot_command=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
    "require 'yaml'; puts YAML.load(STDIN.readlines.join)['boot_command']"`

  if [ -z "$boot_command" ]; then

    no_boot_command=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
      "require 'yaml'; puts YAML.load(STDIN.readlines.join)['no_boot_command']"`

    if [ -z "$no_boot_command" ]; then
      boot_command="/sbin/boot"
    fi
  fi
}

merge_user_args() {
  local docker_args

  docker_args=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
          "require 'yaml'; puts YAML.load(STDIN.readlines.join)['docker_args']"`

  if [[ -n "$docker_args" ]]; then
    user_args="$user_args_argv $docker_args"
  fi
}

run_start() {

   if [ -z "$START_CMD_ONLY" ]
   then
     existing=`$docker_path ps | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
     echo $existing
     if [ ! -z $existing ]
     then
       echo "Nada que hacer, ¡su contenedor ya ha sido iniciado!"
       exit 0
     fi

     existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
     if [ ! -z $existing ]
     then
       echo "iniciando contenedor existente"
       (
         set -x
         $docker_path start $config
       )
       exit 0
     fi
   fi

   set_template_info
   set_volumes
   set_links
   set_run_image
   set_boot_command

   # obtener nombre de host y configuración desde la configuración del contenedor
   for envar in "${env[@]}"
   do
     if [[ $envar == DOCKER_USE_HOSTNAME* ]] || [[ $envar == DISCOURSE_HOSTNAME* ]]
     then
       # usar como variable de entorno
       eval $envar
     fi
   done

   (
     hostname=`hostname -s`
     # sobrescribir nombre de host
     if [ "$DOCKER_USE_HOSTNAME" = "true" ]
     then
       hostname=$DISCOURSE_HOSTNAME
     else
       hostname=$hostname-$config
     fi

     # tenemos que normalizar para que solo tengamos cadenas permitidas, esto es más completo pero veamos cómo lo hace bash primero
     # hostname=`$docker_path run $user_args --rm $image ruby -e 'print ARGV[0].gsub(/[^a-zA-Z-]/, "-")' $hostname`
     # docker agregó más reglas de nombre de host
     hostname=${hostname//_/-}


     if [ -z "$SKIP_MAC_ADDRESS" ] ; then
      mac_address="--mac-address $($docker_path run $user_args -i --rm -a stdout -a stderr $image /bin/sh -c "echo $hostname | md5sum | sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/'")"
     fi

     if [ ! -z "$START_CMD_ONLY" ] ; then
       docker_path="true"
     fi

     set -x

     $docker_path run --shm-size=512m $links $attach_on_run $restart_policy "${env[@]}" "${labels[@]}" -h "$hostname" \
        -e DOCKER_HOST_IP="$docker_ip" --name $config -t "${ports[@]}" $volumes $mac_address $user_args \
        $run_image $boot_command

   )
   exit 0

}

run_run() {
  set_template_info
  set_volumes
  set_links
  set_run_image

  unset ERR
  (exec $docker_path run --rm --shm-size=512m $user_args $links "${env[@]}" -e DOCKER_HOST_IP="$docker_ip" -i -a stdin -a stdout -a stderr $volumes $run_image \
    /bin/bash -c "$run_command") || ERR=$?

  if [[ $ERR > 0 ]]; then
    exit 1
  fi
}

run_bootstrap() {
  set_template_info

  base_image=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
    "require 'yaml'; puts YAML.load(STDIN.readlines.join)['base_image']"`

  update_pups=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
    "require 'yaml'; puts YAML.load(STDIN.readlines.join)['update_pups']"`

  if [[ ! X"" = X"$base_image" ]]; then
    image=$base_image
  fi

  # la base_image puede no ser siempre discourse/base,
  # asegurémonos de que siempre construimos desde la última
  pull_image

  set_volumes
  set_links

  if $docker_path run $user_args --rm -i $image gem which pups; then
    pups_command="/usr/local/bin/pups --stdin"
  else
    # Fallback al método git pull aquí si `pups` no fue instalado por gem en la imagen base
    pups_command="cd /pups &&"
    if [[ ! "false" =  $update_pups ]]; then
      pups_command="$pups_command git pull && git checkout $pups_version &&"
    fi
    pups_command="$pups_command /pups/bin/pups --stdin"
  fi

  echo $pups_command

  declare -i BOOTSTRAP_EXITCODE
  rm -f $cidbootstrap

  echo "$input" | $docker_path run --shm-size=512m $user_args $links "${env[@]}" -e DOCKER_HOST_IP="$docker_ip" --cidfile "$cidbootstrap" -i -a stdin -a stdout -a stderr $volumes $image \
    /bin/bash -c "$pups_command"
  BOOTSTRAP_EXITCODE=$?

  CONTAINER_ID=$(cat "$cidbootstrap")
  rm -f "$cidbootstrap"

  # código de salida mágico que indica un reintento
  if [[ $BOOTSTRAP_EXITCODE -eq 77 ]]; then
    $docker_path rm "$CONTAINER_ID"
    exit 77
  elif [[ $BOOTSTRAP_EXITCODE -gt 0 ]]; then
    echo "la inicialización falló con el código de salida $BOOTSTRAP_EXITCODE"
    echo "** FALLO EN LA INICIALIZACIÓN ** por favor, desplácese hacia arriba y busque mensajes de error anteriores, puede haber más de uno."
    echo "./discourse-doctor puede ayudar a diagnosticar el problema."

    if [[ -n "$DEBUG" ]]; then
      if $docker_path commit "$CONTAINER_ID" $local_discourse/$config-debug; then
        echo "** DEBUG ** Manteniendo imagen para diagnóstico $local_discourse/$config-debug"
      else
        echo "** DEBUG ** Falló al confirmar el contenedor $CONTAINER_ID para diagnóstico"
      fi
    fi

    $docker_path rm "$CONTAINER_ID"
    exit 1
  fi

  sleep 5

  $docker_path commit \
    -c "LABEL org.opencontainers.image.created=\"$(TZ=UTC date -Iseconds)\"" \
    "$CONTAINER_ID" \
    $local_discourse/$config || fatal "FALLÓ AL CONFIRMAR $CONTAINER_ID"
  $docker_path rm "$CONTAINER_ID"
}

case "$comando" in
  bootstrap)
      run_bootstrap
      echo "Inicializado con éxito, para iniciar use ./launcher start $config"
      exit 0
      ;;

  run)
      run_run
      exit 0
      ;;

  enter)
      exec $docker_path exec -it $config /bin/bash --login
      ;;

  stop)
      run_stop
      exit 0
      ;;

  logs)

      $docker_path logs $config
      exit 0
      ;;

  restart)
      run_stop
      run_start
      exit 0
      ;;

  start-cmd)
    START_CMD_ONLY="1"
    run_start
    exit 0;
    ;;

  start)
      run_start
      exit 0
      ;;

  rebuild)
      if [ "$(git symbolic-ref --short HEAD)" == "master" ]; then
        git branch -m master main
        git fetch origin
        git branch -u origin/main main
        git remote set-head origin -a
      fi

      if [ "$(git symbolic-ref --short HEAD)" == "main" ]; then
        echo "Asegurando que el lanzador esté actualizado"

        git remote update

        LOCAL=$(git rev-parse HEAD)
        REMOTE=$(git rev-parse @{u})
        BASE=$(git merge-base HEAD @{u})

        if [ $LOCAL = $REMOTE ]; then
          echo "El lanzador está actualizado"

        elif [ $LOCAL = $BASE ]; then
          echo "Actualizando el lanzador..."
          git pull || (echo 'falló al actualizar' && exit 1)

          echo "Lanzador actualizado, reiniciando..."
          exec "$0" "${SAVED_ARGV[@]}"

        elif [ $REMOTE = $BASE ]; then
          echo "Su versión del lanzador está por delante de origin"

        else
          echo "El lanzador ha divergido de la fuente, esto solo se espera en modo Dev"
        fi

      fi

      set_existing_container

      if [ ! -z $existing ]
        then
          echo "Deteniendo contenedor antiguo"
          (
            set -x
            $docker_path stop -t 60 $config
          )
      fi

      run_bootstrap

      if [ ! -z $existing ]
        then
          echo "Eliminando contenedor antiguo"
          (
            set -x
            $docker_path rm $config
          )
      fi

      run_start
      exit 0
      ;;


  destroy)
      (set -x; $docker_path stop -t 10 $config && $docker_path rm $config) || (echo "$config no fue encontrado" && exit 0)
      exit 0
      ;;
esac

usage

Para finalizar, una pequeña ayuda de PM reveló que era un problema de maxmind y comentarlo permitió que el bootstrap se completara con éxito. :+1: