into - docker run entrypoint bash
Cómo pasar argumentos a Shell Script a través de Docker Run (7)
Soy nuevo en el mundo de los acopladores. Tengo que invocar un script de shell que toma argumentos de línea de comando a través de un contenedor acoplable. Ej: Mi script de shell se ve así:
#!bin/bash
echo $1
Dockerfile se ve así:
FROM ubuntu:14.04
COPY ./file.sh /
CMD /bin/bash file.sh
No estoy seguro de cómo pasar los argumentos mientras ejecuto el contenedor
Con Docker, la forma correcta de pasar este tipo de información es a través de variables de entorno.
Entonces, con el mismo Dockerfile, cambie el script a
#!/bin/bash
echo $FOO
Después de compilar, use el siguiente comando docker:
docker run -e FOO="hello world!" test
Hay algunas cosas que interactúan aquí:
-
docker run your_image arg1 arg2
reemplazará el valor deCMD
conarg1 arg2
. Eso es un reemplazo completo de la CMD, sin agregarle más valores. Es por eso que a menudo ve quedocker run some_image /bin/bash
para ejecutar un shell bash en el contenedor. -
Cuando tiene definidos un ENTRYPOINT y un valor CMD, Docker inicia el contenedor concatenando los dos y ejecutando ese comando concatenado. Entonces, si define su punto de entrada como
file.sh
, ahora puede ejecutar el contenedor con args adicionales que se pasarán como args afile.sh
-
Los puntos de entrada y los comandos en Docker tienen dos sintaxis, una sintaxis de cadena que lanzará un shell y una sintaxis json que ejecutará un exec. El shell es útil para manejar cosas como la redirección de E / S, encadenando múltiples comandos juntos (con cosas como
&&
), sustitución de variables, etc. Sin embargo, ese shell se interpone en el manejo de la señal (si alguna vez ha visto un retraso de 10 segundos para detener un contenedor, esta suele ser la causa) y con la concatenación de un punto de entrada y comando juntos. Si define su punto de entrada como una cadena, se ejecutará/bin/sh -c "file.sh"
, lo cual está bien. Pero si también tiene un comando definido como una cadena, verá algo como/bin/sh -c "file.sh" /bin/sh -c "arg1 arg2"
como el comando que se inicia dentro de su contenedor, no así bueno. Consulte la tabla aquí para obtener más información sobre cómo interactúan estas dos opciones. -
La opción shell
-c
solo toma un único argumento. Todo después de eso se pasaría como$1
,$2
, etc., a ese argumento único, pero no a un script de shell incrustado a menos que haya pasado explícitamente los argumentos. Es decir,/bin/sh -c "file.sh $1 $2" "arg1" "arg2"
funcionaría, pero/bin/sh -c "file.sh" "arg1" "arg2"
no funcionaría ya que se llamaríafile.sh
sin args.
En conjunto, el diseño común es:
FROM ubuntu:14.04
COPY ./file.sh /
RUN chmod 755 /file.sh
# Note the json syntax on this next line is strict, double quotes, and any syntax
# error will result in a shell being used to run the line.
ENTRYPOINT ["file.sh"]
Y luego ejecutas eso con:
docker run your_image arg1 arg2
Hay bastante más detalles sobre esto en:
Lo que tengo es un archivo de script que realmente ejecuta cosas. Este archivo de script podría ser relativamente complicado. Llamémoslo "run_container". Este script toma argumentos de la línea de comando:
run_container p1 p2 p3
Un simple run_container podría ser:
#!/bin/bash
echo "argc = ${#*}"
echo "argv = ${*}"
Lo que quiero hacer es, después de "acoplar" esto, me gustaría poder iniciar este contenedor con los parámetros en la línea de comando del acoplador como este:
docker run image_name p1 p2 p3
y que el script run_container se ejecute con p1 p2 p3 como parámetros.
Esta es mi solución:
Dockerfile:
FROM docker.io/ubuntu
ADD run_container /
ENTRYPOINT ["/bin/bash", "-c", "/run_container /"$@/"", "--"]
Otra opción...
Para que esto funcione
docker run -d --rm $IMG_NAME "bash:command1&&command2&&command3"
en dockerfile
ENTRYPOINT ["/entrypoint.sh"]
en entrypoint.sh
#!/bin/sh
entrypoint_params=$1
printf "==>[entrypoint.sh] %s/n" "entry_point_param is $entrypoint_params"
PARAM1=$(echo $entrypoint_params | cut -d'':'' -f1) # output is 1 must be ''bash'' it will be tested
PARAM2=$(echo $entrypoint_params | cut -d'':'' -f2) # the real command separated by &&
printf "==>[entrypoint.sh] %s/n" "PARAM1=$PARAM1"
printf "==>[entrypoint.sh] %s/n" "PARAM2=$PARAM2"
if [ "$PARAM1" = "bash" ];
then
printf "==>[entrypoint.sh] %s/n" "about to running $PARAM2 command"
echo $PARAM2 | tr ''&&'' ''/n'' | while read cmd; do
$cmd
done
fi
Si quieres ejecutarlo @build time:
CMD /bin/bash /file.sh arg1
si quieres ejecutarlo @ tiempo de ejecución:
ENTRYPOINT ["/bin/bash"]
CMD ["/file.sh", "arg1"]
Luego en el host shell
docker build -t test .
docker run -i -t test
Use el mismo
file.sh
#!bin/bash
echo $1
Cree la imagen utilizando el Dockerfile existente:
docker build -t test .
Ejecute la imagen con argumentos
abc
o
xyz
u otra cosa.
docker run -ti test /file.sh abc
docker run -ti test /file.sh xyz
con este script en
file.sh
#!/bin/bash
echo Your container args are: "$@"
y este
Dockerfile
FROM ubuntu:14.04
COPY ./file.sh /
ENTRYPOINT ["/file.sh"]
CMD []
deberias ser capaz de:
% docker build -t test .
% docker run test hello world
Your container args are: hello world