Esecuzione di uno script all'interno di un contenitore docker utilizzando lo script della shell


88

Sto cercando di creare uno script di shell per impostare un contenitore docker. Il mio file di script ha il seguente aspetto:

#!bin/bash

docker run -t -i -p 5902:5902 --name "mycontainer" --privileged myImage:new /bin/bash

L'esecuzione di questo file di script eseguirà il contenitore in una bash appena richiamata.

Ora ho bisogno di eseguire un file di script (test.sh) che è già all'interno del contenitore dallo script di shell sopra indicato. (Ad esempio: cd /path/to/test.sh && ./test.sh) Come si fa?


1
Perché non usare WORKDIRe CMD?
Dharmit

1
Probabilmente non vorrai usare --privileged qui. Vedi: stackoverflow.com/questions/36425230/…
CMP

Risposte:


123

È possibile eseguire un comando in un contenitore in esecuzione utilizzando docker exec [OPTIONS] CONTAINER COMMAND [ARG...]:

docker exec mycontainer /path/to/test.sh

E per eseguire da una sessione bash:

docker exec -it mycontainer /bin/bash

Da lì puoi eseguire il tuo script.


6
cosa succede se devo prima entrare in / bin / bash e poi eseguire il comando all'interno di quella bash?
zappy

49
È inoltre possibile eseguire uno script locale direttamente dall'host. docker exec -i mycontainer bash < mylocal.sh Questo legge lo script dell'host locale e lo esegue all'interno del contenitore. Puoi farlo con altre cose (come i file .tgz convogliati in tar) - è solo usando '-i' per eseguire il pipe nell'input std del processo contenitore.
Marvin

@ Marvin qual è l'equivalente in PowerShell? il carattere "<" non viene riconosciuto.
Nicekiwi,

1
Non sono un guru di PowerShell (per fortuna) ma ho vagato per SO e ho trovato stackoverflow.com/a/11788475/500902 . Quindi, forse Get-Content mylocal.sh | docker exec -i mycontainer bash. Non so se funziona però.
Marvin,

99

Supponendo che il tuo container Docker sia attivo e funzionante, puoi eseguire comandi come:

docker exec mycontainer /bin/sh -c "cmd1;cmd2;...;cmdn"

2
Mi piace questa risposta; non è necessario accedere al contenitore docker per eseguire un comando o una serie di comandi. Grazie!
Hatem Jaber

Sai come fare un ulteriore passo avanti e passare l'intero comando ( /bin/sh -c "cmd1; cmd2; ...; cmdn") come valore di una variabile di shell? Chiedo perché 'docker run' sembra aspettarsi un singolo comando e singoli argomenti non quotati piuttosto che una stringa tra virgolette.
davidA

@meowsqueak: questa risposta ti dice come eseguire più comandi all'interno di un contenitore già creato e in esecuzione senza accedere a quel contenitore, il che è utile nell'automazione. Tuttavia, se si desidera eseguire più comandi al momento della creazione del contenitore (PS: il comando di esecuzione docker crea e avvia il contenitore), è possibile farlo seguendo le risposte in questo stesso thread stackoverflow.com/a/41363989/777617
Cyclops

Al posto di cmd1, ho bisogno di passare un intero ciclo for, ma si aspetta ;dopo l' istruzione loop e l' istruzione do . Come posso eseguire l'intero ciclo for come un unico comando, ad esempio cmd1? È possibile?
Nicholas K

19

Stavo cercando una risposta per questa stessa domanda e ho trovato ENTRYPOINT nella soluzione Dockerfile per me.

Dockerfile

...
ENTRYPOINT /my-script.sh ; /my-script2.sh ; /bin/bash

Ora gli script vengono eseguiti quando avvio il contenitore e ottengo il prompt bash dopo che gli script sono stati eseguiti.


6

Puoi anche montare una directory locale nell'immagine docker e generare lo script nel tuo file .bashrc. Non dimenticare che lo script deve essere composto da funzioni a meno che tu non voglia che venga eseguito su ogni nuova shell. (Questo è obsoleto, vedere l'avviso di aggiornamento.)

Sto usando questa soluzione per poter aggiornare lo script al di fuori dell'istanza docker. In questo modo non devo rieseguire l'immagine in caso di modifiche, apro solo una nuova shell. (Mi sono sbarazzato della riapertura di una shell - vedi l'avviso di aggiornamento)

Ecco come associare la directory corrente:

docker run -it -v $PWD:/scripts $my_docker_build /bin/bash

Ora la tua directory corrente è associata alla /scriptstua istanza docker.

(Non aggiornato) Per salvare le .bashrcmodifiche, eseguire il commit dell'immagine di lavoro con questo comando:

docker commit $container_id $my_docker_build

Aggiornare

Per risolvere il problema di aprire una nuova shell per ogni modifica ora faccio quanto segue:

Nello stesso dockerfile aggiungo RUN echo "/scripts/bashrc" > /root/.bashrc". All'interno zshrcesporto la directory degli script nel percorso. La directory degli script ora contiene più file invece di uno. Ora posso chiamare direttamente tutti gli script senza dover aprire una sub shell ad ogni modifica.

BTW puoi anche definire il file della cronologia al di fuori del tuo contenitore. In questo modo non è più necessario eseguire il commit su una modifica bash.


Troppo tardi..! @javier mostra già una soluzione semplice !! Sento che è ancora meglio.
zappy

2
@zappy la soluzione di javier non ha risolto questo problema in modo conveniente per me, ma la mia soluzione l'ha fatto, ho pensato che sarebbe stato interessante per coloro che avevano un problema simile in cui non vogliono riavviare le immagini docker per aggiornare un visualizzare le funzioni di cui hanno bisogno. Ad esempio, se utilizzi più immagini Docker contemporaneamente per avviare un cluster di sviluppo, non vorrai riavviarle tutte le volte.
Devpool

3

Nel caso in cui non desideri (o hai) un contenitore in esecuzione, puoi chiamare il tuo script direttamente con il runcomando.

Rimuovi gli -i -targomenti iterativi tty e usa questo:

    $ docker run ubuntu:bionic /bin/bash /path/to/script.sh

Questo (non testerà) funzionerà anche per altri script:

    $ docker run ubuntu:bionic /usr/bin/python /path/to/script.py


0

Se vuoi eseguire lo stesso comando su più istanze puoi farlo:

for i in c1 dm1 dm2 ds1 ds2 gtm_m gtm_sl; do docker exec -it $i /bin/bash -c "service sshd start"; done
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.