Understanding Docker Context: Flask could not locate app.py, when run via docker-compose

  docker, docker-compose, dockerfile, flask, python

I’d like to have docker-compose start an "api" service that is a flask app. 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:

foo/backend/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:

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 -f docker-compose.dev.yml up --build

My issue is around various errors wherein the app.py file isn’t found by flask. 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. The RUN ls command indicates that there is an app.py present:

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:

Example 1

foo/.dev.env

FLASK_APP=app.py

foo/docker-compose.dev.yml

version: '3.8'

services:
 api:
  build:
   context: ./backend/
  ports:
  - 5000:5000
  env_file:
  - .dev.env
  volumes:
  - ./:/app

Example 2

(consider files reverted to state prior to example 1)

foo/backend/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. Here’s the frontend portion of my docker-compose:

foo/docker-compose.dev.yml

version: '3.8'

services:
 frontend:
   build:
     context: ./frontend/
   ports:
   - 8080:8080

And my frontend Dockerfile:

foo/frontend/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? 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?

Source: Docker Questions

LEAVE A COMMENT