1

I have a basic REST API implemented in Flask. I want to try using Docker to containerize it. I'm completely new to Docker, but based on what I was able to figure out on various forums, this is what I have set up.

Dockerfile

FROM python:3.8-alpine

WORKDIR /myapplication

COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt

COPY . .
ENV FLASK_APP="app.py"

CMD ["python3", "-m" , "flask", "run"]

requirements.txt

Flask==2.0.2

I then go to the Terminal, and run $ docker build -t myapp:latest .

The build is successful, and I can see my app listed in the Docker Desktop app

I then run

$ docker run --rm -it -p 8080:8080 myapp:latest

 * Serving Flask app 'app.py' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

Docker Desktop shows myapp is in use.

So far, so good. But this is where I start running into issues.

I am also using Postman for API route testing. If I were to run the application outside of Docker, and I go to 127.0.0.1:5000/data or any of my other routes, I get a response just fine. But with the Docker build running, I am no longer able to access this route, or any other route.

I have tried endless combinations: 127.0.0.1:5000, 127.0.0.1:8080, localhost, localhost:5000, localhost:8080, to no avail.

The only one that gives me ANY response is 127.0.0.1:5000. The response I do get is a 403 Forbidden, with Postman saying "The request was a legal request, but the server is refusing to respond to it."

For what its worth, I am running this on a new M1 Pro MacBook. I know the new Macs are touchy with permissioning, so I wouldn't be surprised if permissions were the issue.

I really don't know what to do or where to go from here, every source I've tried has given me a slight variation on what I have already attempted, and I'm no closer to getting this to work. Please help, thanks.

danielschnoll
  • 3,045
  • 5
  • 23
  • 34

3 Answers3

6

your docker application is running on port 5000 inside the container, but in your docker run command you are binding port 8080 with port 8080 inside the container which should be 5000 instead. As there is nothing running on port 8080 inside the container hence you are getting the 403 error

the command should be

docker run --rm -it -p 8080:5000 myapp:latest

from host machine you can access the app on port 8080, i.e:

127.0.0.1:8080/data # access from host machine

127.0.0.1:5000/data # access from inside container

I just noticed, you didn't expose the app on internet/external use, in the last line of your Dockerfile add arg "--host=0.0.0.0"

CMD ["python3", "-m" , "flask", "run", "--host=0.0.0.0"]

after docker build and publishing the port you should be able to access the app.

Tasnuva Leeya
  • 2,515
  • 1
  • 13
  • 21
  • This did not solve it. I tried exposing `EXPOSE 5000` as well like the other comment suggested, and neither worked. – danielschnoll Mar 08 '22 at 05:07
  • `EXPOSE 5000` will expose the app to `5000` inside the container, to access from your host machine you need to publish the port i,e you should forward the traffic from correct port which is `5000` in your case with local port . please read this post: https://stackoverflow.com/questions/22111060/what-is-the-difference-between-expose-and-publish-in-docker – Tasnuva Leeya Mar 08 '22 at 05:11
  • I tried `EXPOSE 8080`, `docker run --rm -it -p 8080:8080 myapp:latest` as well as `EXPOSE 5000` `docker run --rm -it -p 8080:5000 myapp:latest`. Neither work when going to 127.0.0.1:5000/data – danielschnoll Mar 08 '22 at 05:12
  • from host machine you can access the app using `8080` not `5000`. try: 127.0.0.1:8080/data after running the container – Tasnuva Leeya Mar 08 '22 at 05:16
  • Visiting `127.0.0.1:8080/data` in Postman with `EXPOSE 8080`, `docker run --rm -it -p 8080:5000 myapp:latest` gives `Error: socket hang up` now – danielschnoll Mar 08 '22 at 05:18
  • I have edited the post, please check again. you should expose the app externally, localhost is not a exposing the app for external use. – Tasnuva Leeya Mar 08 '22 at 05:24
  • This ended up working: `CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"]`, `$ docker run --rm -it -p 8080:5000 myapp:latest`, accessing endpoints at `127.0.0.1:8080/data` – danielschnoll Mar 08 '22 at 05:28
0

This ended up working, thank you @Tasnuva

Dockerfile, append CMD with --host

CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"]

In the CLI, $ docker run --rm -it -p 8080:5000 myapp:latest

Accessing endpoints in Postman at 127.0.0.1:8080

danielschnoll
  • 3,045
  • 5
  • 23
  • 34
-1

In dockerfile you need to expose your port

...
ENV FLASK_APP="app.py"
EXPOSE 5000
CMD ["python3", "-m" , "flask", "run"]
Ashin Shakya
  • 690
  • 6
  • 9
  • Still not working, I have `EXPOSE 5000` in my Dockerfile now, and I deleted the old build. I rebuilt the image with `docker build -t myapp:latest .`, and ran with `docker run --rm -it -p 8080:8080 myapp:latest`. The server starts as usual, and when I go to Postman 127.0.0.1:5000/data, I get the same 403 Forbidden – danielschnoll Mar 08 '22 at 05:05
  • It should not work, the root problem is in docker run command, OP is binding the host port with port `8080` of container but his application is running on port `5000`, either he should expose the app to 8080 inside container or bind the host port with correct port which is 5000 – Tasnuva Leeya Mar 08 '22 at 05:08