Ejecutar un script dentro de un contenedor docker usando un script de shell

85

Estoy tratando de crear un script de shell para configurar un contenedor docker. Mi archivo de script se ve así:

#!bin/bash

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

La ejecución de este archivo de secuencia de comandos ejecutará el contenedor en un bash recién invocado.

Ahora necesito ejecutar un archivo de script (test.sh) que ya está dentro del contenedor del script de shell dado anteriormente (por ejemplo: cd /path/to/test.sh && ./test.sh) ¿Cómo hacer eso?

alegre
fuente
1
¿Por qué no usar WORKDIRy CMD?
Dharmit
1
Probablemente no quieras usar --privileged here. Ver: stackoverflow.com/questions/36425230/…
CMP

Respuestas:

121

Puede ejecutar un comando en un contenedor en ejecución usando docker exec [OPTIONS] CONTAINER COMMAND [ARG...]:

docker exec mycontainer /path/to/test.sh

Y para ejecutar desde una sesión bash:

docker exec -it mycontainer /bin/bash

Desde allí puede ejecutar su script.

Javier Cortejoso
fuente
6
¿Qué pasa si necesito ingresar en / bin / bash primero y luego ejecutar el comando dentro de ese bash?
zappy
44
También puede ejecutar un script local desde el host directamente. docker exec -i mycontainer bash < mylocal.sh Esto lee el script del host local y lo ejecuta dentro del contenedor. Puede hacer esto con otras cosas (como archivos .tgz canalizados en tar); solo usa el '-i' para canalizar la entrada estándar del proceso del contenedor.
Marvin
@Marvin ¿cuál es el equivalente en PowerShell? no se reconoce el carácter "<".
Nicekiwi
1
No soy un gurú de powershell (afortunadamente) pero deambulé por SO y encontré stackoverflow.com/a/11788475/500902 . Entonces, tal vez Get-Content mylocal.sh | docker exec -i mycontainer bash. Aunque no sé si eso funciona.
Marvin
97

Suponiendo que su contenedor Docker esté en funcionamiento, puede ejecutar comandos como:

docker exec mycontainer /bin/sh -c "cmd1;cmd2;...;cmdn"
Cíclope
fuente
2
Me gusta esta respuesta; no tiene que iniciar sesión en el contenedor de la ventana acoplable para ejecutar un comando o un conjunto de comandos. ¡Gracias!
Hatem Jaber
¿Sabe cómo llevar esto un paso más allá y pasar todo el comando ( /bin/sh -c "cmd1; cmd2; ...; cmdn") como el valor de una variable de shell? Lo pregunto porque 'docker run' parece esperar un solo comando y argumentos individuales sin comillas en lugar de una cadena entre comillas.
davidA
@meowsqueak: esta respuesta le dice cómo ejecutar múltiples comandos dentro de un contenedor ya creado y en ejecución sin iniciar sesión en ese contenedor, lo cual es útil en la automatización. Sin embargo, si desea ejecutar varios comandos en el momento de la creación del contenedor (PS: el comando docker run crea e inicia el contenedor), puede lograrlo siguiendo las respuestas en este mismo hilo stackoverflow.com/a/41363989/777617
Cyclops
En lugar de cmd1, necesito pasar un bucle for completo, pero se espera ;después de la declaración de bucle y la declaración do . ¿Cómo puedo ejecutar todo el bucle for como un solo comando, es decir cmd1? ¿Es posible?
Nicholas K
18

Estaba buscando una respuesta para esta misma pregunta y encontré ENTRYPOINT en la solución Dockerfile para mí.

Dockerfile

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

Ahora los scripts se ejecutan cuando inicio el contenedor y obtengo el indicador de bash después de que se han ejecutado los scripts.

tojo
fuente
6

También puede montar un directorio local en su imagen de docker y obtener el script en su .bashrc . No olvide que el script debe constar de funciones a menos que desee que se ejecute en cada shell nuevo. (Esto está desactualizado, consulte el aviso de actualización).

Estoy usando esta solución para poder actualizar el script fuera de la instancia de Docker. De esta manera no tengo que volver a ejecutar la imagen si ocurren cambios, simplemente abro un nuevo shell. (Eliminó la reapertura de un shell, consulte el aviso de actualización)

Así es como enlaza su directorio actual:

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

Ahora su directorio actual está vinculado a /scripts su instancia de Docker.

(Desactualizado) Para guardar sus .bashrccambios, confirme su imagen de trabajo con este comando:

docker commit $container_id $my_docker_build

Actualizar

Para resolver el problema de abrir un nuevo shell para cada cambio, ahora hago lo siguiente:

En el propio dockerfile agrego RUN echo "/scripts/bashrc" > /root/.bashrc". Dentrozshrc exporto el directorio de scripts a la ruta. El directorio de scripts ahora contiene varios archivos en lugar de uno. Ahora puedo llamar directamente a todos los scripts sin tener que abrir un sub shell en cada cambio.

Por cierto, también puede definir el archivo de historial fuera de su contenedor. De esta manera, ya no es necesario comprometerse con un cambio de bash.

Devpool
fuente
Demasiado tarde..! @javier ya muestra una solución sencilla !! Siento que uno es aún mejor.
zappy
2
@zappy, la solución de javier no resolvió este problema convenientemente para mí, pero mi solución lo hizo, pensé que sería interesante para aquellos que tenían un problema similar en el que no quieren reiniciar las imágenes de la ventana acoplable para actualizar una ver las funciones que necesitan. Por ejemplo, si usa varias imágenes de Docker a la vez para activar un clúster de desarrollo, no desea reiniciarlas todo el tiempo.
Devpool
3

En caso de que no desee (o tenga) un contenedor en ejecución, puede llamar a su script directamente con el runcomando.

Elimine los -i -targumentos tty iterativos y use esto:

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

Esto (no probado) también funcionará para otros scripts:

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

Si desea ejecutar el mismo comando en varias instancias, puede hacer esto:

for i in c1 dm1 dm2 ds1 ds2 gtm_m gtm_sl; do docker exec -it $i /bin/bash -c "service sshd start"; done
DMin
fuente