[DOCKER] BUNDLE_APP_CONFIG qui est gênant lors du développement de Ruby avec DevContainer

TL;DR

json:.devcontainer/devcontainer.json


{
  // ...
  "remoteEnv": {
    "BUNDLE_APP_CONFIG": null
  },
  // ...
}

Dépannage de BUNDLE_APP_CONFIG

VSCode Remote - Dans la plupart des cas de développement Ruby avec des conteneurs, vous allez créer un DevContainer basé sur l 'image ruby officielle Docker [^ 1] Je suppose, mais cette image a un vilain problème.

C'est la variable d'environnement BUNDLE_APP_CONFIG. Il est défini sur / usr / local / bundle par défaut par l'instruction ʻENV` dans le Dockerfile.

BUNDLE_APP_CONFIG est une variable d'environnement qui spécifie où enregistrer les paramètres locaux de l'application de bundler (les paramètres créés lorsque vous faites bundle config set --local). Si cette variable d'environnement n'est pas définie, le bundler créera un paramètre sous .bundle / dans la racine de l'application.

Maintenant, passons au cas du développement de Ruby avec DevContainer de VSCode, afin de monter le gem installé sur le conteneur tout en le rendant persistant, je voudrais l'insérer dans le répertoire vendor, etc. dans l'espace de travail comme suit. [^ 2]

$ bundle config set --local path vendor/bundle

Ce paramètre doit généralement enregistrer le fichier de configuration avec le paramètre de chemin comme .bundle / config. En le définissant localement, un fichier de paramètres est créé dans l'espace de travail, et même si le conteneur est détruit, il n'est pas nécessaire de le reconfigurer. Cependant, comme mentionné ci-dessus, l'image ruby officielle de Docker a BUNDLE_APP_CONFIG défini, donc ce paramètre local est enregistré dans / usr / local / bundle / config.

Si vous vérifiez avec bundle config, cela ressemble à ce qui suit.

$ bundle config
Settings are listed in order of priority. The top value will be used.
path
Set for your local app (/usr/local/bundle/config): "vendor/bundle"

app_config
Set via BUNDLE_APP_CONFIG: "/usr/local/bundle"

silence_root_warning
Set via BUNDLE_SILENCE_ROOT_WARNING: true

Dans ce cas, les paramètres seront perdus lorsque le conteneur est détruit par Rebuild etc., alors exécutez bundle config ... à chaque fois, ou montez / usr / local / bundle depuis l'hôte. Vous aurez besoin de concevoir.

La solution intelligente est de faire quelque chose à propos de BUNDLE_APP_CONFIG lui-même.

À propos, BUNDLE_APP_CONFIG est défini dans l'image officielle dans le sens opposé, il semble être" pour empêcher .bundle / config du côté hôte d'affecter l'intérieur du conteneur" [^ 3 ].

__2020 / 09/30 Addendum __ Si vous travaillez uniquement à l'intérieur du conteneur (= vous n'avez pas besoin de partager .bundle / ou vendor / avec l'hôte), laissez BUNDLE_APP_CONFIG et laissez le volume créé séparément / usr / local / bundle Il semble préférable de le monter. Surtout dans Docker pour Mac, les E / S du disque au moment du montage de la liaison sont lentes, donc si vous définissez pour mettre un gem dans l'espace de travail, cela peut prendre du temps, tel que l'installation du bundle.

Contre-mesures

× Définissez un caractère vide dans BUNDLE_APP_CONFIG

C'est la méthode décrite dans la Documentation officielle.

The environment variables we set are canonically listed in the above-linked Dockerfiles, but some of them include GEM_HOME, BUNDLE_PATH, BUNDLE_BIN, BUNDLE_SILENCE_ROOT_WARNING, and BUNDLE_APP_CONFIG.

If these cause issues for your use case (running multiple Ruby applications in a single container, for example), setting them to the empty string should be sufficient for undoing their behavior.

L'essentiel est que cette méthode ne fonctionne pas. Puisque le bundler ne regarde que l'existence de BUNDLE_APP_CONFIG [^ 4], si un caractère vide est défini, un fichier config sera créé directement sous le répertoire courant.

Expérimentons. Définissez BUNDLE_APP_CONFIG sur un caractère vide dans le Dockerfile pour DevCotainer.

devcontainer/Dockerfile


FROM ruby:2.7

#Définir un caractère vide
ENV BUNDLE_APP_CONFIG=

#Ce qui suit est omis

Construisez DevContaier et entrez. Pour une raison quelconque, BUNDLE_APP_CONFIG disparaît sur le terminal et fonctionne correctement (pour des raisons inconnues, il peut s'agir d'un problème d'implémentation VSCode).

$ bundle config
Settings are listed in order of priority. The top value will be used.
silence_root_warning
Set via BUNDLE_SILENCE_ROOT_WARNING: true
$ bundle config set --local path vendor/bundle
$ bundle config
Settings are listed in order of priority. The top value will be used.
path
Set for your local app (/workspace/sample_app/.bundle/config): "vendor/bundle"

silence_root_warning
Set via BUNDLE_SILENCE_ROOT_WARNING: true

Le problème est lors du débogage. Imaginez un cas où le débogueur (rdebug-ide) est géré par un Gemfile et installé par bundle install. Cela devrait ressembler à launch.json:

json:.vscode/launch.json


{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug Local File",
      "type": "Ruby",
      "request": "launch",
      "program": "${workspaceFolder}/main.rb",
      "useBundler": true
    }
  ]
}

Lorsque j'exécute le débogage, j'obtiens une erreur dans DEBUG CONSOLE indiquant que la gemme requise ne peut pas être trouvée comme indiqué ci-dessous.

bundler: failed to load command: rdebug-ide (/usr/local/bundle/bin/rdebug-ide)
Bundler::GemNotFound: Could not find concurrent-ruby-1.1.7 in any of the sources
  /usr/local/lib/ruby/2.7.0/bundler/spec_set.rb:86:in `block in materialize'
  /usr/local/lib/ruby/2.7.0/bundler/spec_set.rb:80:in `map!'
  /usr/local/lib/ruby/2.7.0/bundler/spec_set.rb:80:in `materialize'
  /usr/local/lib/ruby/2.7.0/bundler/definition.rb:170:in `specs'
  /usr/local/lib/ruby/2.7.0/bundler/definition.rb:237:in `specs_for'
  /usr/local/lib/ruby/2.7.0/bundler/definition.rb:226:in `requested_specs'
  /usr/local/lib/ruby/2.7.0/bundler/runtime.rb:101:in `block in definition_method'
  /usr/local/lib/ruby/2.7.0/bundler/runtime.rb:20:in `setup'
  /usr/local/lib/ruby/2.7.0/bundler.rb:149:in `setup'
  /usr/local/lib/ruby/2.7.0/bundler/setup.rb:20:in `block in <top (required)>'
  /usr/local/lib/ruby/2.7.0/bundler/ui/shell.rb:136:in `with_level'
  /usr/local/lib/ruby/2.7.0/bundler/ui/shell.rb:88:in `silence'
  /usr/local/lib/ruby/2.7.0/bundler/setup.rb:20:in `<top (required)>'

Ceci est dû au fait que le sous-processus de débogage a BUNDLE_APP_CONFIG =" " en vigueur, donc .bundle / config n'est pas référencé et le paramètre path n'est pas lu.

△ Définissez le chemin de .bundle sur BUNDLE_APP_CONFIG (Dockerfile)

Par exemple, comme indiqué ci-dessous, vous pouvez spécifier le chemin absolu de .bundle pour les paramètres locaux dans Dockerfile.

devcontainer/Dockerfile


ENV BUNDLE_APP_CONFIG=/workspace/.bundle

Cette méthode fonctionne plutôt bien, mais elle ne fonctionne pas pour les cas où vous avez plusieurs projets dans votre monorepo (plusieurs Gemfiles).

△ Le chemin de .bundle est défini dans BUNDLE_APP_CONFIG (paramètre VSCode)

Par exemple, le problème que le débogage ci-dessus ne fonctionne pas peut être résolu comme suit.

json:.vscode/launch.json


{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug Local File",
      "type": "Ruby",
      "request": "launch",
      "program": "${workspaceFolder}/main.rb",
      "useBundler": true,
      "env": {
        "BUNDLE_APP_CONFIG": "${workspaceFolder}/.bundle"
      }
    }
  ]
}

Avec cette méthode, vous pouvez également gérer les cas mono-repo en définissant Espace de travail multi-racine. Cependant, ce paramètre seul n'est valide que pour le sous-processus de débogage, vous devez donc écrire des paramètres similaires dans les paramètres du terminal de settings.json et tasks.json si nécessaire. De plus, pour une raison quelconque, il devient difficile de partager des paramètres tels que launch.json avec des personnes qui définissent et utilisent BUNDLE_APP_CONFIG.

〇 Supprimez BUNDLE_APP_CONFIG dans les paramètres de devcontainer.json

Vous pouvez annuler la définition des variables d'environnement au lieu de les vider ou de les écraser en ajoutant les paramètres suivants à devcontainer.json.

json:.devcontainer/devcontainer.json


{
  // ...
  "remoteEnv": {
    "BUNDLE_APP_CONFIG": null
  },
  // ...
}

Cette méthode supprime BUNDLE_APP_CONFIG dans le processus VSCode et tous ses sous-processus dans le conteneur. Personnellement, cette méthode semble avoir le moins d'effets secondaires, je la recommande donc.

[^ 1]: mcr.microsoft.com / vscode / devcontainers / ruby est également basé sur cette image [^ 2]: En passant, l'option --path de bundle install est obsolète ... J'ai appris récemment

Recommended Posts

BUNDLE_APP_CONFIG qui est gênant lors du développement de Ruby avec DevContainer
Étudier à CodeWar (ruby) ④ cas ~ quand
Comportement lorsque le caractère générique (**) est spécifié dans ruby