2016-02-29 3 views
8

Ich möchte eine Textzeile in eine Textdatei INSIDE einen laufenden Docker Container schreiben. Hier ist, was ich bisher versucht:Docker exec - Schreibe Text in Datei im Container

docker exec -d app_$i eval echo "server.url=$server_url" >> /home/app/.app/app.config 

Antwort:

/home/user/.app/app.config: No such file or directory 

Zweiter Versuch:

cfg_add="echo 'server.url=$server_url' >> /home/user/.app/app.config" 
docker exec -i app_$i eval $cfg_add 

Antwort:

exec: "eval": executable file not found in $PATH 

Irgendwelche Ideen?

+0

Warum '-d' für docker exec? – user2915097

+2

'eval' ist nicht im Container vorhanden. Der Kernel wird vom Host und dem Container gemeinsam genutzt. Die Programme sind nicht. Wenn Sie 'nc' auf Ihrem Host installiert haben, kann der Container sie nicht ausführen, solange er nicht darin installiert wurde. – Auzias

+0

@Auzias: Das Problem ist nicht, dass 'eval' nicht _present_ im Container ist (es ist wahrscheinlich, als _Shell builtin_ der Shell des Containers), aber es ist _not ein externes Dienstprogramm_, so' docker exec' kann nicht aufgerufen werden es. – mklement0

Antwort

22

eval ist ein Shell gebautet, während docker exec erfordert ein externes Dienstprogramm aufgerufen werden, so dass unter Verwendung von eval ist nicht eine Option.

Stattdessen aufrufen, um eine Schale ausführbare im Behälter (bash) explizit, und sie den Befehl übergeben als Zeichenfolge über seine -c Option auszuführen:

docker exec "app_$i" bash -c "echo 'server.url=$server_url' >> /home/app/.app/app.config" 

Durch die Verwendung eines Doppel -0,Zeichenfolge, die an bash -c übergeben wird, stellen Sie sicher, dass die Shell zuerst die Zeichenfolgeninterpolation ausführt, während die bash Instanz des Containers das erweiterte Ergebnis alsanzeigtLiteral, als Teil der eingebetteten einfach zitierten Zeichenfolge.


Was Ihre Symptome:

  • /home/user/.app/app.config: No such file or directory berichtet wurde, weil die Umleitung Sie im Behälter tatsächlich passiert ist in Ihrem Host-Shell passieren soll - und weil Richt. /home/user/.app offenbar existiert nicht in Dateisystem Ihres Hosts, konnte der Befehl grundsätzlich, vor Shell Ihren Hosts selbst den Befehl (bash wird abgebrochen, Befehlsausführung, wenn eine Umleitung der Ausgabe nicht durchgeführt werden kann) auszuführen versucht.

    • So, auch wenn Sie Ihre erste Befehl enthielt auch eval, hat seine Verwendung nicht als Problem, bis der zweite Befehl Oberfläche, die tatsächlich tat ausgeführt werden sollen.
  • exec: "eval": executable file not found in $PATH passiert ist, weil, wie gesagt, eval kein externes Dienstprogramm ist, sondern eine Schale gebautet und docker exec können nur externe Dienstprogramme ausführen.

+0

Große Antwort. Ich habe unten eine Antwort geschrieben, ohne zu merken, dass er vom Host deklarierte Variablen und ähnliches verwenden wollte. Ihre Antwort ist viel besser und erklärte die Dinge sehr gut. Vielen Dank. – CtheGood

+0

@CtheGood: Danke; Abgesehen von der Verwendung von Hostvariablen wird Ihr Befehl nicht funktionieren, weil Sie die Argumente _separately_ an 'docker exec' übergeben müssen; In Ihrem Fall wird die Zeichenfolge _entire_ mit einem Anführungszeichen als _Befehlsname_ interpretiert und führt zu folgendem Fehler: 'exec:" echo \ "Hallo Welt \"> test.txt ": Die ausführbare Datei wurde nicht in $ PATH gefunden – mklement0

+0

Hier ist ein Beispiel hier können Sie Dateien mit Anführungszeichen in ihnen schreiben. Zum Beispiel wollen Sie 'obj ['key'] = 'value' in eine Datei namens'/etc/config.py' schreiben. 'docker exec" app_ $ i "bash -c 'echo" obj [' "'key'" '] =' "'value'" '">/etc/config.py'' – Gourneau

4

Zusätzlich:

Wenn Sie Text von außerhalb des Behälters schreiben müssen, funktioniert das auch:

(docker exec -i container sh -c "cat > c.sql") < c.sql 

Dies wird Rohr Eingabe in den Behälter. Das funktioniert natürlich auch für reinen Text (keine Datei). Es ist wichtig, den Parameter -t nicht zu verwenden.

Siehe https://github.com/docker/docker/pull/9537

UPDATE (falls Sie müssen nur Dateien kopieren, nicht Teile von Dateien):

Docker v17.03 hat docker cp, die Kopien zwischen dem lokalen fs und der Behälter: https://docs.docker.com/engine/reference/commandline/cp/#usage