【问题标题】:Flask CLI throws "[Errno 2] No such file" when deploying with docker使用 docker 部署时,Flask CLI 抛出“[Errno 2] No such file”
【发布时间】:2019-08-15 14:33:39
【问题描述】:

我正在关注 testdriven.io 上的微服务课程。在本课程中,我需要使用 Docker 部署一个 Flask 应用程序。为了运行我使用 Flask-cli 的应用程序,它在启动时给了我一个错误:

No such file or directory: '/usr/src/app/manage.py': '/usr/src/app/manage.py'

为了部署容器,我使用 Docker-compose。我在我的 Windows 10 机器上运行该命令,并使用标准 Python 映像 (python:3.7.2-alpine)。我已经尝试更改文件的权限,但没有帮助。

这就是我的撰写文件的样子:

version: '3.7'

services:

  users:
    build:
      context: ./services/users
      dockerfile: Dockerfile-dev
    volumes:
      - './services/users:/usr/src/app'
    ports:
      - 6001:6000
    environment:
      - FLASK_APP=project/__init__.py
      - FLASK_ENV=development
      - COMPOSE_CONVERT_WINDOWS_PATHS=1

我的 docker 文件:

# base image
FROM python:3.7.2-alpine

# set working directory
WORKDIR /usr/src/app

# add and install requirements
COPY ./requirements.txt /usr/src/app/requirements.txt
RUN pip install -r requirements.txt

# add app
COPY . /usr/src/app

# i tried to give it the right rights.. but it didn't help
RUN chmod +x /usr/src/app/manage.py

# run server
CMD python manage.py run -h 0.0.0.0

还有我的manage.py 文件,它将启动应用程序:

#!/usr/bin/python3
# services/users/manage.py

from flask.cli import FlaskGroup

from project import app

cli = FlaskGroup(app)

if __name__ == '__main__':
    cli()

所以我希望这会启动应用程序并使其在端口 6001 上可用,但它却给了我以下错误:

Successfully tagged testdriven-app_users:latest
Recreating testdriven-app_users_1 ... done
Attaching to testdriven-app_users_1
users_1  |  * Serving Flask app "project/__init__.py" (lazy loading)
users_1  |  * Environment: development
users_1  |  * Debug mode: on
users_1  |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
users_1  |  * Restarting with stat
users_1  | Traceback (most recent call last):
users_1  |   File "manage.py", line 11, in <module>
users_1  |     cli()
users_1  |   File "/usr/local/lib/python3.7/site-packages/click/core.py", line 764, in __call__
users_1  |     return self.main(*args, **kwargs)
users_1  |   File "/usr/local/lib/python3.7/site-packages/flask/cli.py", line 557, in main
users_1  |     return super(FlaskGroup, self).main(*args, **kwargs)
users_1  |   File "/usr/local/lib/python3.7/site-packages/click/core.py", line 717, in main
users_1  |     rv = self.invoke(ctx)
users_1  |   File "/usr/local/lib/python3.7/site-packages/click/core.py", line 1137, in invoke
users_1  |     return _process_result(sub_ctx.command.invoke(sub_ctx))
users_1  |   File "/usr/local/lib/python3.7/site-packages/click/core.py", line 956, in invoke
users_1  |     return ctx.invoke(self.callback, **ctx.params)
users_1  |   File "/usr/local/lib/python3.7/site-packages/click/core.py", line 555, in invoke
users_1  |     return callback(*args, **kwargs)
users_1  |   File "/usr/local/lib/python3.7/site-packages/click/decorators.py", line 64, in new_func
users_1  |     return ctx.invoke(f, obj, *args, **kwargs)
users_1  |   File "/usr/local/lib/python3.7/site-packages/click/core.py", line 555, in invoke
users_1  |     return callback(*args, **kwargs)
users_1  |   File "/usr/local/lib/python3.7/site-packages/flask/cli.py", line 771, in run_command
users_1  |     threaded=with_threads, ssl_context=cert)
users_1  |   File "/usr/local/lib/python3.7/site-packages/werkzeug/serving.py", line 988, in run_simple
users_1  |     run_with_reloader(inner, extra_files, reloader_interval, reloader_type)
users_1  |   File "/usr/local/lib/python3.7/site-packages/werkzeug/_reloader.py", line 332, in run_with_reloader
users_1  |     sys.exit(reloader.restart_with_reloader())
users_1  |   File "/usr/local/lib/python3.7/site-packages/werkzeug/_reloader.py", line 176, in restart_with_reloader
users_1  |     exit_code = subprocess.call(args, env=new_environ, close_fds=False)
users_1  |   File "/usr/local/lib/python3.7/subprocess.py", line 323, in call
users_1  |     with Popen(*popenargs, **kwargs) as p:
users_1  |   File "/usr/local/lib/python3.7/subprocess.py", line 775, in __init__
users_1  |     restore_signals, start_new_session)
users_1  |   File "/usr/local/lib/python3.7/subprocess.py", line 1522, in _execute_child
users_1  |     raise child_exception_type(errno_num, err_msg, err_filename)
users_1  | FileNotFoundError: [Errno 2] No such file or directory: '/usr/src/app/manage.py': '/usr/src/app/manage.py'
testdriven-app_users_1 exited with code 1

【问题讨论】:

    标签: python docker flask


    【解决方案1】:

    当你执行一个脚本时,内核会寻找 shebang (#!) 中指定的解释器。提取解释器的位置,然后启动解释器(例如python3),执行脚本本身。如果未找到解释器二进制文件,则执行失败并出现 No such file or directory (ENOENT) 错误(根据 man 2 execve):

    ERRORS
    <...>
        ENOENT The file filename or a script or ELF interpreter does not exist,
               or a shared library needed for the file or interpreter cannot be found.
    

    您在 shebang 中指定了 #!/usr/bin/python3,但在您使用的基础映像 (python:3.7.2-alpine) 中,python3 二进制文件位于不同的位置:

    $ docker run -it python:3.7.2-alpine sh
    / # which python3
    /usr/local/bin/python3
    

    因此,即使您的应用程序在您的主机上本地运行(如果是 Windows,它甚至可能不关心 shebang),当您将其移动到 Docker 容器中时,它也会停止运行。

    为了避免这种情况,脚本中的 shebangs 通常不是指解释器本身 (#!/usr/bin/python3),而是指 /usr/bin/env 二进制文件,它会找到并执行解释器:

    #!/usr/bin/env python3
    

    当您通过env 运行python3 时,后者通过PATH 执行搜索,因此它允许您的shebang 不依赖于python3 二进制文件的特定位置。

    最后,您的脚本的正确版本如下:

    #!/usr/bin/env python3
    # services/users/manage.py
    
    from flask.cli import FlaskGroup
    
    from project import app
    
    cli = FlaskGroup(app)
    
    if __name__ == '__main__':
        cli()
    

    【讨论】:

    • 感谢您的回答!现在可以了。我还必须将文件的换行从 CRLF 更改为 LF。
    【解决方案2】:

    将 werkzeug==0.14.1 添加到 requirements.txt 可以修复相同的错误出现在 windows 上。 它似乎是一个 werkzeug 错误。

    【讨论】:

    • 这也修复了我的问题。谢谢..我有版本 0.15.xx 我刚刚更新了版本并解决了问题。
    猜你喜欢
    • 2019-10-15
    • 2022-12-24
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-25
    • 1970-01-01
    相关资源
    最近更新 更多