Tengo un Dockerfile con un ENTRYPOINT que usa una variable ENV. No puedo estructurar el PUNTO DE ENTRADA para que el contenedor también pueda aceptar argumentos de línea de comando adicionales. Aquí está la parte relevante del Dockerfile:
ARG MODULE_NAME ENV MODULE_NAME=$MODULE_NAME ENTRYPOINT /usr/bin/python3 -m ${MODULE_NAME}Eso funciona bien si solo quiero iniciar el contenedor sin argumentos adicionales:
docker run my-imagePero necesito poder pasar argumentos de línea de comando adicionales (por ejemplo, un indicador "--debug") al proceso de python de esta manera:
docker run my-image --debugCon la forma de ENTRYPOINT anterior, el argumento "--debug" no se pasa al proceso de python. Probé tanto el formulario exec como el formulario de shell de ENTRYPOINT, pero no puedo hacer que funcione tanto con la variable ENV como con los argumentos de la línea de comandos. Algunas otras formas que probé:
Esto se ejecuta pero no acepta argumentos adicionales:
ENTRYPOINT ["/bin/bash", "-c", "/usr/bin/python3 -m ${MODULE_NAME}"]Esto da "/usr/bin/python3: ningún módulo llamado ${MODULE_NAME}":
ENTRYPOINT ["/usr/bin/python3", "-m ${MODULE_NAME}"]Esto da "/usr/bin/python3: ningún módulo llamado ${MODULE_NAME}":
ENTRYPOINT ["/usr/bin/python3", "-m", "${MODULE_NAME}"]Parece que no es posible crear un PUNTO DE ENTRADA que admita directamente tanto la expansión variable como los argumentos adicionales de la línea de comandos. Si bien la forma de shell de ENTRYPOINT expandirá las variables ENV en tiempo de ejecución, no acepta argumentos adicionales (adjuntos) del comando de docker run . Si bien la forma ejecutiva de ENTRYPOINT admite argumentos de línea de comando adicionales, no crea un entorno de shell de forma predeterminada, por lo que las variables ENV no se expanden.
Para evitar esto, se puede llamar a bash explícitamente en el formulario exec para ejecutar un script que luego expande las variables ENV y pasa los argumentos de la línea de comandos al proceso de python. Aquí hay un Dockerfile de ejemplo que hace esto:
FROM ubuntu:16.04 ARG MODULE_NAME=foo ENV MODULE_NAME=${MODULE_NAME} RUN apt-get update -y && apt-get install -y python3.5 # Create the module to be run RUN echo "import sys; print('Args are', sys.argv)" > /foo.py # Create a script to pass command line args to python RUN echo "/usr/bin/python3.5 -m $MODULE_NAME \$@" > /run_module.sh ENTRYPOINT ["/bin/bash", "/run_module.sh"]Salida de la imagen acoplable:
$ docker run my-image Args are ['/foo.py'] $ docker run my-image abc Args are ['/foo.py', 'a', 'b', 'c']Tenga en cuenta que la expansión variable se produce durante los comandos EJECUTAR (ya que están utilizando el formulario de shell), por lo que el contenido de run_script.py en la imagen es:
/usr/bin/python3.5 -m foo $@Si el último comando RUN se reemplaza con esto:
RUN echo "/usr/bin/python3.5 -m \$MODULE_NAME \$@" > /run_module.shentonces run_script.sh contendría
/usr/bin/python3.5 -m $MODULE_NAME $@Pero la salida del contenedor en ejecución sería la misma ya que la expansión variable ocurrirá en tiempo de ejecución. Un beneficio potencial de la segunda versión es que uno podría anular el módulo para que se ejecute en tiempo de ejecución sin reemplazar el ENTRYPOINT.
Pude resolver las variables ENV dentro de ENTRYPOINT. El error que estaba cometiendo era que los ARG que se usaron para completar ENV se escribieron antes de la declaración FROM y, por lo tanto, estaban fuera del alcance de la etapa acoplable actual. Una vez que los moví debajo de FROM, funciona muy bien.
Mi Dockerfile de trabajo:
ARG BASE_IMAGE FROM ${BASE_IMAGE} ARG NEO4J_USERNAME ARG NEO4J_URL ARG NEO4J_PASSWORD ENV NEO4J_USERNAME=$NEO4J_USERNAME \ NEO4J_URL=$NEO4J_URL \ NEO4J_PASSWORD=$NEO4J_PASSWORD COPY ./ / WORKDIR / ENTRYPOINT python3 -u myscript.py ${NEO4J_URL} ${NEO4J_USERNAME} ${NEO4J_PASSWORD}