[英]Understanding Docker Context: Flask could not locate app.py, when run via docker-compose
I'd like to have docker-compose start an "api" service that is a flask app.我想让 docker-compose 启动一个“api”服务,它是一个烧瓶应用程序。 My folder structure is as such:我的文件夹结构是这样的:
foo/backend/
Dockerfile
app.py
requirements.text
foo/
docker-compose.dev.yml
There's also a frontend folder which I'll discuss later when demonstrating why I think my current strategy should work.还有一个前端文件夹,稍后我将在演示为什么我认为我当前的策略应该有效时讨论它。
My backend Dockerfile looks like the following:我的后端 Dockerfile 如下所示:
foo/backend/Dockerfile foo/后端/Dockerfile
# syntax=docker/dockerfile:1
FROM python:3.8-slim-buster
WORKDIR /app
COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt
COPY . .
RUN ls
CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"]
My docker compose file looks like the following:我的 docker compose 文件如下所示:
foo/docker-compose.dev.yml foo/docker-compose.dev.yml
version: '3.8'
services:
api:
build:
context: ./backend/
ports:
- 5000:5000
volumes:
- ./:/app
(I removed the other services for clarity, I'll refer back to them later) (为了清楚起见,我删除了其他服务,稍后我会参考它们)
I run docker-compose with the following command:我使用以下命令运行 docker-compose:
docker-compose -f docker-compose.dev.yml up --build
My issue is around various errors wherein the app.py file isn't found by flask.我的问题是关于各种错误,其中烧瓶找不到 app.py 文件。 For example:例如:
api_1 | Error: Could not locate a Flask application. You did not provide the "FLASK_APP" environment variable, and a "wsgi.py" or "app.py" module was not found in the current directory.
I added the RUN ls
command to my Dockerfile because I don't know how to debug a Docker image that won't run (is that the right vocabulary?) and the backend image won't run because it fails with the above error.我将RUN ls
命令添加到我的 Dockerfile 中,因为我不知道如何调试无法运行的 Docker 映像(这是正确的词汇吗?)并且后端映像将无法运行,因为它因上述错误而失败。 The RUN ls
command indicates that there is an app.py
present: RUN ls
命令表明存在app.py
:
Step 6/7 : RUN ls
---> Running in f5f09e4805cc
Dockerfile
__pycache__
app.py
database.conf
requirements.txt
I've tried setting an environment variable two ways: with a file, and then at the direction of a stackoverflow answer directly as an ENV
property in the Dockerfile:我尝试通过两种方式设置环境变量:使用文件,然后在stackoverflow 答案的方向上直接作为 Dockerfile 中的ENV
属性:
Example 1示例 1
foo/.dev.env foo/.dev.env
FLASK_APP=app.py
foo/docker-compose.dev.yml foo/docker-compose.dev.yml
version: '3.8'
services:
api:
build:
context: ./backend/
ports:
- 5000:5000
env_file:
- .dev.env
volumes:
- ./:/app
Example 2示例 2
(consider files reverted to state prior to example 1) (考虑文件恢复到示例 1 之前的状态)
foo/backend/Dockerfile foo/后端/Dockerfile
# syntax=docker/dockerfile:1
FROM python:3.8-slim-buster
WORKDIR /app
COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt
COPY . .
RUN ls
ENV FLASK_APP=app.py
CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"]
Bot examples result in:机器人示例导致:
api_1 | Error: Could not import 'app'.
I suspect this issue has something to do with contexts that commands are being run in, but I don't understand why it doesn't work for backend
, when it does for frontend
.我怀疑这个问题与运行命令的上下文有关,但我不明白为什么它不适用于backend
,而它适用于frontend
。 Here's the frontend
portion of my docker-compose:这是我的 docker-compose 的frontend
部分:
foo/docker-compose.dev.yml foo/docker-compose.dev.yml
version: '3.8'
services:
frontend:
build:
context: ./frontend/
ports:
- 8080:8080
And my frontend Dockerfile:还有我的前端 Dockerfile:
foo/frontend/Dockerfile foo/前端/Dockerfile
# syntax=docker/dockerfile:1
FROM node:16
WORKDIR /app
COPY package*.json ./
RUN yarn
COPY . .
CMD [ "yarn", "run", "serve" ]
The frontend correctly runs and remains spun up.前端正确运行并保持旋转。
How can I determine the context in which a Dockerfile command is run?如何确定运行 Dockerfile 命令的上下文? Why isn't my python CMD
able to find the app.py
file that, to me, seems to be visible in the proper location to it?为什么我的 python CMD
无法找到app.py
文件,在我看来,它似乎在正确的位置可见?
You have a volumes:
block that's overwriting the /app
directory in the container with entirely different content.您有一个volumes:
块,它用完全不同的内容覆盖容器中的/app
目录。 If you delete that block, you'll run the code that's built into the image.如果您删除该块,您将运行内置于图像中的代码。
Some Docker tutorials will tell you to bind-mount host content into your image.一些 Docker 教程会告诉您将主机内容绑定到您的映像中。 The idea is that this simulates a live-development environment, so if you change your application code you don't have to restart the application.这个想法是模拟实时开发环境,因此如果您更改应用程序代码,则不必重新启动应用程序。 In your case, the directory you're mounting into the container is different from what you built the image, so you're getting inconsistent behavior.在您的情况下,您安装到容器中的目录与您构建图像的目录不同,因此您会得到不一致的行为。 In most cases you should be able to use an actual local development environment to build your application, and then run it in Docker (without a volumes:
bind-mount; running the actual code in the image) for integration testing and deployment.在大多数情况下,您应该能够使用实际的本地开发环境来构建您的应用程序,然后在 Docker 中运行它(没有volumes:
bind-mount;运行镜像中的实际代码)以进行集成测试和部署。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.