[DOCKER] BUNDLE_APP_CONFIG, was bei der Entwicklung von Ruby mit DevContainer problematisch ist

TL;DR

json:.devcontainer/devcontainer.json


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

Problematisch BUNDLE_APP_CONFIG

VSCode Remote - In den meisten Fällen der Ruby-Entwicklung mit Containern erstellen Sie einen DevContainer basierend auf dem offiziellen Ruby-Image von Docker [^ 1]. Ich nehme an, aber dieses Bild hat ein böses Problem.

Das ist die Umgebungsvariable BUNDLE_APP_CONFIG. Es wird standardmäßig durch die Anweisung "ENV" in der Docker-Datei auf "/ usr / local / bundle" gesetzt.

BUNDLE_APP_CONFIG ist eine Umgebungsvariable, die angibt, wo die anwendungslokalen Einstellungen des Bundlers gespeichert werden sollen (die Einstellungen, die beim Bündelkonfigurationssatz --local erstellt wurden). Wenn diese Umgebungsvariable nicht festgelegt ist, erstellt der Bundler eine Einstellung unter ".bundle /" im Anwendungsstamm.

Kommen wir nun zum Fall der Ruby-Entwicklung mit DevContainer von VSCode. Um das installierte Juwel auf dem Container zu mounten und es dauerhaft zu machen, möchte ich es wie folgt in das Verzeichnis "vendor" usw. im Arbeitsbereich einfügen. [^ 2]

$ bundle config set --local path vendor/bundle

Diese Einstellung sollte normalerweise die Konfigurationsdatei mit der Pfadeinstellung ".bundle / config" speichern. Durch lokales Einstellen wird eine Einstellungsdatei im Arbeitsbereich erstellt, und selbst wenn der Container zerstört wird, muss er nicht neu konfiguriert werden. Wie oben erwähnt, ist für das offizielle Ruby-Image von Docker "BUNDLE_APP_CONFIG" festgelegt, sodass diese lokale Einstellung in "/ usr / local / bundle / config" gespeichert wird.

Wenn Sie mit "Bundle-Konfiguration" prüfen, sieht es wie folgt aus.

$ 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

In diesem Fall gehen die Einstellungen verloren, wenn der Container durch Rebuild usw. zerstört wird. Führen Sie daher jedes Mal bundle config ... aus oder mounten Sie / usr / local / bundle vom Host. Sie müssen sich etwas ausdenken.

Die clevere Lösung besteht darin, etwas gegen BUNDLE_APP_CONFIG selbst zu unternehmen.

Übrigens ist "BUNDLE_APP_CONFIG" im offiziellen Bild in umgekehrter Weise gesetzt. Es scheint zu sein, "zu verhindern, dass" .bundle / config "auf der Host-Seite das Innere des Containers beeinflusst" [^ 3 ].

__2020 / 09/30 Nachtrag __ Wenn Sie nur innerhalb des Containers arbeiten (= Sie müssen ".bundle /" oder "vendor /" nicht mit dem Host teilen), lassen Sie "BUNDLE_APP_CONFIG" und lassen Sie das separat erstellte Volume "/ usr / local / bundle" Es scheint besser, es zu montieren. Insbesondere in Docker für Mac ist die Festplatten-E / A zum Zeitpunkt des Bind-Mount langsam. Wenn Sie also Gem im Arbeitsbereich festlegen, kann dies einige Zeit dauern, z. B. "Bundle-Installation".

Gegenmaßnahmen

× Setzen Sie ein Leerzeichen in BUNDLE_APP_CONFIG

Dies ist die in den offiziellen Dokumenten beschriebene Methode.

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.

Das Fazit ist, dass diese Methode nicht funktioniert. Da der Bundler nur die Existenz von BUNDLE_APP_CONFIG [^ 4] untersucht, wird bei einem Leerzeichen eine config-Datei direkt unter dem aktuellen Verzeichnis erstellt.

Lass uns experimentieren. Setzen Sie BUNDLE_APP_CONFIG auf ein leeres Zeichen in der Docker-Datei für DevCotainer.

devcontainer/Dockerfile


FROM ruby:2.7

#Legen Sie ein leeres Zeichen fest
ENV BUNDLE_APP_CONFIG=

#Folgendes wird weggelassen

Baue DevContaier und gehe hinein. Aus irgendeinem Grund verschwindet "BUNDLE_APP_CONFIG" auf dem Terminal und funktioniert einwandfrei (aus unbekannten Gründen kann es sich um ein VSCode-Implementierungsproblem handeln).

$ 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

Das Problem ist beim Debuggen. Stellen Sie sich einen Fall vor, in dem der Debugger (rdebug-ide) von einer Gemfile verwaltet und von bundle install installiert wird. Es sollte aussehen wie 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
    }
  ]
}

Wenn ich das Debug ausführe, wird in DEBUG CONSOLE eine Fehlermeldung angezeigt, dass der erforderliche Edelstein nicht wie unten gezeigt gefunden werden kann.

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)>'

Dies liegt daran, dass für den Debugging-Unterprozess "BUNDLE_APP_CONFIG =" "aktiviert ist, sodass auf" .bundle / config "nicht verwiesen wird und die Einstellung" path "nicht gelesen wird.

△ Setzen Sie den Pfad von .bundle auf BUNDLE_APP_CONFIG (Dockerfile)

Wie unten gezeigt, können Sie beispielsweise den absoluten Pfad von ".bundle" für lokale Einstellungen in Dockerfile angeben.

devcontainer/Dockerfile


ENV BUNDLE_APP_CONFIG=/workspace/.bundle

Diese Methode funktioniert ziemlich gut, aber nicht in Fällen, in denen Sie mehrere Projekte in Ihrem Monorepo haben (mehrere Gemfiles).

△ Der Pfad von .bundle wird in BUNDLE_APP_CONFIG (VSCode-Einstellung) festgelegt.

Beispielsweise kann das Problem, dass das obige Debugging nicht funktioniert, wie folgt gelöst werden.

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"
      }
    }
  ]
}

Mit dieser Methode können Sie auch Mono-Repo-Fälle behandeln, indem Sie [Multi-Root-Arbeitsbereich] festlegen (https://code.visualstudio.com/docs/editor/multi-root-workspaces). Diese Einstellung allein gilt jedoch nur für den Debugging-Unterprozess. Daher müssen Sie bei Bedarf ähnliche Einstellungen in die Terminaleinstellungen von settings.json und task.json schreiben. Aus irgendeinem Grund wird es auch schwierig, Einstellungen wie "launch.json" für Personen freizugeben, die "BUNDLE_APP_CONFIG" festlegen und verwenden.

〇 Löschen Sie BUNDLE_APP_CONFIG in den Einstellungen von devcontainer.json

Sie können Umgebungsvariablen deaktivieren, anstatt sie zu leeren oder zu überschreiben, indem Sie die folgenden Einstellungen zu "devcontainer.json" hinzufügen.

json:.devcontainer/devcontainer.json


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

Diese Methode entfernt "BUNDLE_APP_CONFIG" im VSCode-Prozess und alle seine Unterprozesse im Container. Persönlich scheint diese Methode die wenigsten Nebenwirkungen zu haben, daher empfehle ich sie.

[^ 1]: mcr.microsoft.com / vscode / devcontainers / ruby basiert ebenfalls auf diesem Bild [^ 2]: Abgesehen davon ist die Option "--path" der "Bundle-Installation" veraltet ... Ich habe kürzlich erfahren

Recommended Posts

BUNDLE_APP_CONFIG, was bei der Entwicklung von Ruby mit DevContainer problematisch ist
Studieren bei CodeWar (Ruby) ④ case ~ when
Verhalten, wenn Platzhalter (**) in Ruby angegeben ist