Werkzeug: 0.15.0 provoque OSError : [Errno 8] Erreur de format Exec : dans Docker pour Windows

Créé le 21 mars 2019  ·  19Commentaires  ·  Source: pallets/werkzeug

La nouvelle version 0.15.0 ne s'exécute pas dans Docker pour Windows. Je n'ai pas essayé Docker sur d'autres plates-formes.

Exemple minimal avec 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')

Fichier Docker

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

exigences.txt

# Werkzeug==0.14.1
Flask

Exécutez docker build -t flask_test . puis docker run flask_test .
Erreur dans le conteneur :

λ 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

Décommentez la première ligne dans requirements.txt et elle s'exécutera correctement après la reconstruction.

Commentaire le plus utile

J'ai fait le même tutoriel et j'ai trouvé le même problème. Cela l'a réglé pour moi.

J'ai ajouté le shebang suivant en haut de mon script app.py

#!/usr/local/bin/python3

Ce qui a ensuite causé des problèmes d'autorisation. J'ai ensuite ajouté ce qui suit à mon Dockerfile avant le CMD

RUN chmod 644 app.py

Tous les 19 commentaires

Salut même problème ici. Testé sur

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

Cela est dû aux modifications de _get_args_for_reloading() dans _reloading.py.

Étant donné le code ci-dessus dans un fichier appelé app.py, avec cwd() étant /home/user/Projects/test/

_get_args_for_reloading() donne ceci :

Avec 0.14.1 :

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

Avec 0.15.0

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

Ajouter /home/user/.virtualenvs/test-ChRUEUMK/bin/python au chemin résout le problème.

@shinuza vérifie si app.py est exécutable, si oui - définissez chmod 644 app.py. Ou deuxième façon, ajoutez shebang en haut de app.py comme #!/usr/bin/env python

@shinuzahttps://github.com/pallets/werkzeug/blob/0.15.x/src/werkzeug/_reloader.py#L90 lignes 90-94 le "'/home/user/.virtualenvs/test-ChRUEUMK/bin /python'" a été supprimé si app.py exécutable.
et OSError : [Errno 8] Erreur de format Exec : '/usr/src/app/app.py s'est produite car app.py n'a pas de ligne shebang (https://stackoverflow.com/questions/27606653/oserror-errno- 8-exec-format-error)

@kamyanskiy Je viens de comprendre cela en lisant le code mais l'erreur devrait être aussi cryptique qu'elle l'est actuellement.

De plus, si j'exécute explicitement python app.py , le sous-processus ne doit faire aucune hypothèse et changer la façon dont j'exécute l'application. c'est-à-dire : travailler avec une machine virtuelle avec un dossier partagé rend tous les fichiers exécutables par défaut.

@shinuza Je ne pense pas que ce soit un bogue critique, en d'autres termes, c'est un peu plus strict maintenant qu'avant. Donc, je ne devrais pas avoir app.py exécutable sans shebang, cela n'a aucun sens. Et deuxièmement, je ne devrais pas exécuter un exécutable avec shebang comme "python app.py". Mais je suis d'accord, c'était probablement inattendu pour vous comme pour moi :) Pour contourner le problème, ajoutez simplement shebang à votre app.py, j'espère que cela vous aidera.

Si vous marquez un script comme exécutable, vous devez ajouter un commentaire d'interpréteur correspondant en haut. Vous pouvez utiliser un outil comme le hook check-executables-have-shebangs de pre-commit pour faire appliquer cela.

Si vous ne souhaitez pas qu'un script soit directement exécutable et que vous souhaitiez exiger python script.py la place, vous ne devez pas le marquer comme exécutable.

Comme je l'ai dit, je suis d'accord avec la logique principale ici. Je ne suis pas d'accord avec la façon dont l'erreur est traitée ainsi que le fait que le message d'erreur est inintelligible à moins que vous ne connaissiez les détails techniques ou que vous ne lisiez le code. Cela devrait au moins être documenté dans le changelog.

Nous n'avons aucun contrôle sur le message d'erreur, qui vient de Linux. Le fait que nous ayons modifié la gestion des fichiers exécutables est répertorié dans le journal des modifications :

Le rechargeur n'ajoutera pas l'exécutable Python à la ligne de commande si le fichier Python est marqué comme exécutable. Cela permet au rechargeur de fonctionner sur NixOS. #1242

Rendre le fichier non exécutable fonctionne. La ligne shebang ne fonctionne pas, pour moi. Je reçois des erreurs de fichier introuvable à la place. C'est la première chose que j'ai essayé.

Avec #!/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

Je pense aussi que faire un changement qui ne fonctionne que sur une distribution Linux mais casse le reste ne semble pas idéal. Rendre les fichiers non exécutables semble être la bonne solution, mais cela me semble toujours cassé.

@ penner42 essayez #!/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

vous n'avez probablement pas de lien symbolique sur python3

Même résultat. Le lien symbolique python3 est là, et il suffit d'exécuter /usr/bin/env python3 ou /usr/bin/env python partir d'un shell.

FWIW, Docker donne cet avertissement lors de la construction.
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.

Utilisez la commande 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

Le tutoriel sur https://docs.docker.com/compose/gettingstarted/ fonctionnait-il sur Windows 7 ?
Ce changement récent est-il la cause pour laquelle je vois une erreur similaire en essayant d'exécuter l'exemple :

$ 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

J'ai fait le même tutoriel et j'ai trouvé le même problème. Cela l'a réglé pour moi.

J'ai ajouté le shebang suivant en haut de mon script app.py

#!/usr/local/bin/python3

Ce qui a ensuite causé des problèmes d'autorisation. J'ai ensuite ajouté ce qui suit à mon Dockerfile avant le CMD

RUN chmod 644 app.py

N'importe qui peut mettre à jour le tutoriel (https://docs.docker.com/compose/gettingstarted/)
ajouter

RUN chmod 644 app.py

Modifications du didacticiel Docker Compose proposées dans https://github.com/docker/docker.github.io/pull/8609.

Corrigé dans l'outil 0.15.5.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

SimonSapin picture SimonSapin  ·  12Commentaires

lepture picture lepture  ·  6Commentaires

sorenh picture sorenh  ·  4Commentaires

taion picture taion  ·  7Commentaires

abathur picture abathur  ·  13Commentaires