Werkzeug: 0.15.0 provoca OSError: [Errno 8] Error de formato Exec: en Docker para Windows

Creado en 21 mar. 2019  ·  19Comentarios  ·  Fuente: pallets/werkzeug

El nuevo 0.15.0 no se ejecuta en Docker para Windows. No he probado Docker en otras plataformas.

Ejemplo mínimo con Flask.

app.py

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_world():
    return 'Hello, world!'

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')

Dockerfile

FROM python:3-onbuild
COPY . /usr/src/app
CMD ["python", "app.py"]

requisitos.txt

# Werkzeug==0.14.1
Flask

Ejecute docker build -t flask_test . y luego docker run flask_test .
Error en el contenedor:

λ docker run flask_test
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
 * Restarting with stat
Traceback (most recent call last):
  File "app.py", line 11, in <module>
    app.run(debug=True, host='0.0.0.0')
  File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 943, in run
    run_simple(host, port, self, **options)
  File "/usr/local/lib/python3.6/site-packages/werkzeug/serving.py", line 988, in run_simple
    run_with_reloader(inner, extra_files, reloader_interval, reloader_type)
  File "/usr/local/lib/python3.6/site-packages/werkzeug/_reloader.py", line 332, in run_with_reloader
    sys.exit(reloader.restart_with_reloader())
  File "/usr/local/lib/python3.6/site-packages/werkzeug/_reloader.py", line 176, in restart_with_reloader
    exit_code = subprocess.call(args, env=new_environ, close_fds=False)
  File "/usr/local/lib/python3.6/subprocess.py", line 267, in call
    with Popen(*popenargs, **kwargs) as p:
  File "/usr/local/lib/python3.6/subprocess.py", line 709, in __init__
    restore_signals, start_new_session)
  File "/usr/local/lib/python3.6/subprocess.py", line 1344, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
OSError: [Errno 8] Exec format error: '/usr/src/app/app.py

Descomente la primera línea en requirements.txt y se ejecutará correctamente después de la reconstrucción.

Comentario más útil

Hice el mismo tutorial y encontré el mismo problema. Esto me lo arregló.

Agregué el siguiente shebang en la parte superior de mi script app.py

#!/usr/local/bin/python3

Lo que luego causó problemas de permisos. Luego agregué lo siguiente a mi Dockerfile antes del CMD

RUN chmod 644 app.py

Todos 19 comentarios

Hola mismo problema aquí. Probado en

  • Centos 7.4 con python 3.6
  • Mac OSX 10.14.3 con Python 3.7

Esto es causado por los cambios en _get_args_for_reloading() en _reloading.py.

Dado el código anterior en un archivo llamado app.py, con cwd() siendo /home/user/Projects/test/

_get_args_for_reloading() produce lo siguiente:

Con 0.14.1 :

['/home/user/.virtualenvs/test-ChRUEUMK/bin/python', 'app.py']

Con 0.15.0

['/home/user/Projects/test/app.py']

Anteponer /home/user/.virtualenvs/test-ChRUEUMK/bin/python a la ruta soluciona el problema.

@shinuza comprueba si app.py es ejecutable, si es así, establece chmod 644 app.py. O de la segunda manera, agregue shebang en la parte superior de app.py como #!/usr/bin/env python

@shinuza allí https://github.com/pallets/werkzeug/blob/0.15.x/src/werkzeug/_reloader.py#L90 líneas 90-94 el "'/home/user/.virtualenvs/test-ChRUEUMK/bin /python'" se eliminó si app.py ejecutable.
y OSError: [Errno 8] Error de formato Exec: '/usr/src/app/app.py ocurrió porque app.py no tiene línea shebang (https://stackoverflow.com/questions/27606653/oserror-errno- 8-exec-formato-error)

@kamyanskiy Me acabo de dar cuenta de esto leyendo el código, pero el error debería ser tan críptico como lo es ahora.

Además, si ejecuto explícitamente python app.py , entonces el subproceso no debería hacer ninguna suposición y cambiar la forma en que ejecuto la aplicación. es decir: trabajar con una máquina virtual con una carpeta compartida hace que todos los archivos sean ejecutables de forma predeterminada.

@shinuza No creo que sea un error crítico, en otras palabras, ahora es un poco más estricto que antes. Entonces, no debería tener el ejecutable app.py sin shebang, no tiene sentido. Y segundo, no debería ejecutar un ejecutable con shebang como "python app.py". Pero estoy de acuerdo, probablemente eso fue inesperado para ti y para mí :) Para solucionarlo, solo agrega shebang a tu app.py, espero que esto ayude.

Si marca un script como ejecutable, debe agregar un comentario de intérprete correspondiente en la parte superior. Puede usar una herramienta como el gancho check-executables-have-shebangs de pre-commit para hacer cumplir eso.

Si no tiene la intención de que un script sea directamente ejecutable y desea requerir python script.py en su lugar, entonces no debe marcarlo como ejecutable.

Como dije, estoy de acuerdo con la lógica principal aquí. No estoy de acuerdo con la forma en que se trata el error, así como con el hecho de que el mensaje de error es ininteligible a menos que conozca los detalles técnicos o lea el código. Al menos debería estar documentado en el registro de cambios.

No tenemos control sobre el mensaje de error, que proviene de Linux. El hecho de que cambiamos la forma en que se manejan los archivos ejecutables se enumera en el registro de cambios:

El recargador no antepondrá el ejecutable de Python a la línea de comando si el archivo de Python está marcado como ejecutable. Esto permite que el recargador funcione en NixOS. #1242

Hacer que el archivo no sea ejecutable funciona. La línea shebang no lo hace, para mí. Obtengo errores de archivo no encontrado, en su lugar. Eso fue lo primero que probé.

Con #!/usr/bin/env python3 :

λ docker run flask_test
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
 * Restarting with stat
: No such file or directory

También creo que hacer un cambio que funcione solo en una distribución de Linux pero rompa el resto no parece ideal. Hacer que los archivos no sean ejecutables parece la solución adecuada, pero todavía me parece que no funciona.

@penner42 prueba #!/usr/bin/env python

root<strong i="7">@4541ebd677e0</strong>:/usr/src/app# ls -la /usr/local/bin/python3
lrwxrwxrwx 1 root staff 9 Mar  4 23:40 /usr/local/bin/python3 -> python3.6
root<strong i="8">@4541ebd677e0</strong>:/usr/src/app# ls -la /usr/local/bin/python 
lrwxrwxrwx 1 root staff 7 Mar  4 23:40 /usr/local/bin/python -> python3

probablemente no tengas un enlace simbólico en python3

Mismo resultado. El enlace simbólico de python3 está ahí, y simplemente ejecutar /usr/bin/env python3 o /usr/bin/env python desde un shell funciona.

FWIW, Docker da esta advertencia al construir.
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.

Utilice el comando flask run .

FROM python:3.7-alpine
WORKDIR /app
ENV FLASK_ENV development
ENV FLASK_APP example
EXPOSE 5000
RUN ["pip", "install", "flask"]
CMD ["flask", "run", "-h", "0.0.0.0"]
docker run --rm -p 5000:5000 -v $(pwd):/app flask/example:latest

¿El tutorial en https://docs.docker.com/compose/gettingstarted/ solía funcionar en Windows 7?
¿Este cambio reciente es la causa por la que veo un error similar al intentar ejecutar el ejemplo?

$ docker-compose up
Creating composetest_web_1   ... done
Creating composetest_redis_1 ... done
Attaching to composetest_web_1, composetest_redis_1
redis_1  | 1:C 27 Mar 2019 17:29:12.746 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1  | 1:C 27 Mar 2019 17:29:12.746 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1  | 1:C 27 Mar 2019 17:29:12.747 # Warning: no config file specified, using the default config. In order to specify a config file use redis-ser
ver /path/to/redis.conf
redis_1  | 1:M 27 Mar 2019 17:29:12.757 * Running mode=standalone, port=6379.
redis_1  | 1:M 27 Mar 2019 17:29:12.757 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to th
e lower value of 128.
redis_1  | 1:M 27 Mar 2019 17:29:12.758 # Server initialized
redis_1  | 1:M 27 Mar 2019 17:29:12.758 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issu
e add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
web_1    |  * Serving Flask app "app" (lazy loading)
web_1    |  * Environment: production
web_1    |    WARNING: Do not use the development server in a production environment.
web_1    |    Use a production WSGI server instead.
web_1    |  * Debug mode: on
web_1    |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
web_1    |  * Restarting with stat
web_1    | Traceback (most recent call last):
web_1    |   File "app.py", line 32, in <module>
web_1    |     app.run(host="0.0.0.0", debug=True)
web_1    |   File "/usr/local/lib/python3.4/site-packages/flask/app.py", line 943, in run
web_1    |     run_simple(host, port, self, **options)
web_1    |   File "/usr/local/lib/python3.4/site-packages/werkzeug/serving.py", line 988, in run_simple
web_1    |     run_with_reloader(inner, extra_files, reloader_interval, reloader_type)
web_1    |   File "/usr/local/lib/python3.4/site-packages/werkzeug/_reloader.py", line 332, in run_with_reloader
web_1    |     sys.exit(reloader.restart_with_reloader())
web_1    |   File "/usr/local/lib/python3.4/site-packages/werkzeug/_reloader.py", line 176, in restart_with_reloader
web_1    |     exit_code = subprocess.call(args, env=new_environ, close_fds=False)
web_1    |   File "/usr/local/lib/python3.4/subprocess.py", line 534, in call
web_1    |     with Popen(*popenargs, **kwargs) as p:
web_1    |   File "/usr/local/lib/python3.4/subprocess.py", line 856, in __init__
web_1    |     restore_signals, start_new_session)
web_1    |   File "/usr/local/lib/python3.4/subprocess.py", line 1464, in _execute_child
web_1    |     raise child_exception_type(errno_num, err_msg)
web_1    | OSError: [Errno 8] Exec format error
composetest_web_1 exited with code 1

Hice el mismo tutorial y encontré el mismo problema. Esto me lo arregló.

Agregué el siguiente shebang en la parte superior de mi script app.py

#!/usr/local/bin/python3

Lo que luego causó problemas de permisos. Luego agregué lo siguiente a mi Dockerfile antes del CMD

RUN chmod 644 app.py

Cualquiera puede actualizar el tutorial (https://docs.docker.com/compose/gettingstarted/)
agregar

RUN chmod 644 app.py

Se proponen cambios en el tutorial de Docker Compose en https://github.com/docker/docker.github.io/pull/8609.

Solucionado en la herramienta 0.15.5.

¿Fue útil esta página
0 / 5 - 0 calificaciones