Docker flask app not working - port issues - python

I am trying to run a flask through docker.
My dockerfile:
FROM python:3
# set a directory for the app
WORKDIR /usr/src/app
# copy all the files to the container
COPY . .
# install dependencies
RUN pip install --no-cache-dir -r requirements.txt
# tell the port number the container should expose
EXPOSE 3000
# run the command
ENTRYPOINT ["python", "app.py"]
My app.py
import os
from flask import Flask, request, jsonify
from submission import SubmissionResult
app = Flask(__name__)
#app.route("/health")
def health_check():
return "healthy"
if __name__ == "__main__":
app.run(debug=True)
I ran docker run <my_image>.
When I hit "/health" on postman, I get an error saying:
Could not get any response
There was an error connecting to .
Why this might have happened:
The server couldn't send a response:
Ensure that the backend is working properly
Self-signed SSL certificates are being blocked:
Fix this by turning off 'SSL certificate verification' in Settings > General
Proxy configured incorrectly
Ensure that proxy is configured correctly in Settings > Proxy
Request timeout:
Change request timeout in Settings > General
It's weird because my flask app doesn't show any debugging logs, so presumably the request isn't hitting the server. Am I not exposing the port correctly?
How do I fix this?

You are not specifying the output port on the Python code. It maps to the default port, which is 5000. Use app.run(debug=True, port=3000) if you want to expose to port 3000. You also have to export the Docker port on host, do this calling -p 3000:3000 before <my_image>. It will tell Docker to map port 3000 of the image to port 3000 of host.

Related

Docker/Flask: Development server runs on localhost fine, but cannot access external URL

I'm brand new to Docker so I think there's something wrong in my setup.
Here's my app.py (reduced version):
import flask
from flask import request
from flask_cors import CORS, cross_origin
app = flask.Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
#app.route('/', methods=['GET'])
#cross_origin()
def index():
return('Home')
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
My Dockerfile:
FROM python:3
WORKDIR /app
ENV FLASK_APP=app.py
COPY ./requirements.txt .
RUN pip3 install -r requirements.txt
COPY . .
CMD ["python3", "app.py"]
I'm building the image with docker build -t flaskapi . and running with
docker run --rm -it -p 80:5000 flaskapi which gives the following output:
* Serving Flask app "app" (lazy loading)
* Environment: development
* Debug mode: on
* Running on all addresses.
WARNING: This is a development server. Do not use it in a production deployment.
* Running on http://172.17.0.2:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
Visiting localhost in the browser, everything works fine but when trying to vist http://172.17.0.2:5000/ or testing with Postman, I eventually get a timeout error. I feel like it's just a small mistake I've made somewhere but I can't quite see it. What can I do to fix this?
By default, Docker runs in a separate subnet that is not accessible by the outside world. To be able to access the service running inside the container, you will have to map one of your host's ports to the internal docker subnet.
In your run command, you map TCP 80 to TCP 5000 inside the docker network (the -p 80:5000 part). That's why your service is accessible when visiting http://localhost (80 is implied). In essence, any request to your port 80 will end up being served by the service running at http://172.17.0.2:5000/.
The 172.* ip is in Docker's subnet range. To communicate via that, with your current settings, you would have to be in another container that shares the same network as this one.

Connecting to flask docker container on windows browser

I have docker running on my Windows 10 OS and I have a minimal flask app
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run(host ='0.0.0.0', port = 5001, debug = True)
And I am dockerizing it using the following file
FROM python:alpine3.7
COPY . /opt
WORKDIR /opt
RUN pip install -r requirements.txt
EXPOSE 5001
ENTRYPOINT [ "python" ]
CMD ["app.py", "run", "--host", "0.0.0.0"]
From what I am seeing on other posts and on Flask tutorials having a 0.0.0.0 should allow me to connect from the windows firefox browser when I type 0.0.0.0:5001 but it is not connecting, I keep getting a 'unable to connect' message. I remember using the 0.0.0.0:port to connect in localhost on a linux ubuntu machine but for whatever reason its not letting me connect on Windows. Is there a special setting to connect on windows ?
Inside the Docker container, the private port is 5001. This private port then needs to be mapped to a public port when running the container. For example, to set the public port to 8000, you could run:
$ docker run --publish 8000:5001 --name <docker-container> <docker-container>:<version-tag>
The Flask app would then be accessible at URL: http://127.0.0.1:8000
Dockerfile
In addition, since in app.py you are setting the host and port, there is no need to specify these values in the Dockerfile CMD. But the public port (in this example 8000) needs to be exposed.
It also looks like the COPY command is placing everything under an /opt directory, so that needs to be included in the app path when launching the Flask app within Docker.
FROM python:alpine3.7
COPY . /opt
WORKDIR /opt
RUN pip install -r requirements.txt
EXPOSE 8000
CMD ["python", "/opt/app.py"]
Docker-Flask Example
For a complete Flask-Docker example, including using Gunicorn, see:
Docker Python Flask Example using the Gunicorn WSGI HTTP Server

How to start Dockerized Python Flask app with https instead of http?

I have a REST api server developed with Python & Flask framework and deployed in the main server with Docker. When I build & start the docker container by sudo docker-compose build & sudo docker-compose up, the docker container starts at http://0.0.0.0:5000/ or localhost and using port 5000.
This works fine in non-ssl environment or browser or domain. But recently my main website (suppose www.example.com) started using ssl certificates. To communicate with main site I have to serve my apis in https instead of http.
Now I am trying to use this code to start server in https mode, but getting some errors.
My code :
import ssl
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
ctx.load_cert_chain('certificate.pem', 'privateKey.pem')
.
.
if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0',ssl_context=ctx)
Here is my error:
What will be the proper procedure to start Docker supported Python Flask app in https mode?
After 2 days of tiresome work I found the proper solution. My domain got 2 files when implemented ssl or https. One is mydomain_com.crt file, another is private.key
I found these 2 files in my server's main directory. As I am using Apache, then I found these files in /etc/var/www/html folder.
I copied 2 files as follows:
copied the license from mydomain_com.crt file and paste in a text file then renamed it certificate.pem
copied the license from private.key and paste in a text file then renamed it privateKey.pem
Then I used my domain's default ssl certificate into my Flask app like this:
import ssl
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
ctx.load_cert_chain('certificate.pem', 'privateKey.pem')
.
.
.
if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0', ssl_context=ctx)
And exposed the 2 ports in my Dockerfile like this :
FROM python:3
WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD [ "python", "app.py" ]
EXPOSE 80
EXPOSE 443
After restart, my Dockerized Flask app now working with my domain's default ssl certificate and serving the APIs correctly.
Example : https://example.com:5000/getUsers

Exposing Flask App within Docker to Internet

I have a Python Flask App running inside a Docker container in the default port 500. This is on a Ubuntu server.
I am able to access the Flask App through local host as follows:
URL = "http://127.0.0.1:5000/get_image"
Would like to know how to expose this server to outside world. I would like to use the server IP to expose the service so that others can access it as well.
Can some one guide on how to expose this docket to internet? Thank you
You should first put "0.0.0.0" as host for flask. Next you need to expose your docker port.
Flask file:
from flask import Flask
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class HelloWorld(Resource):
def get(self):
return {'hello': 'world'}
api.add_resource(HelloWorld, '/get_image')
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
Dockerfile
FROM python:3.7
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
ENTRYPOINT ["python"]
CMD ["app.py"]
Build the docker image
docker build -t docker_flask:latest .
Run the image
docker run -d -p 5000:5000 docker_flask:latest
After checking everything is running fine in local, push the image to docker registry using docker push command. Then deploy the image on kubernetes or VM

Containerized flask app does not load if port is Changed

I have created a simple flask app that is running on a this is the skeleton o the flask app, which by default runs at port 5000:
# Create the application instance
app = connexion.App(__name__, specification_dir="./")
# read the swagger.yml file to configure the endpoints
app.add_api("swagger.yml")
# Create a URL route in our application for "/"
#app.route("/")
def home():
"""
This function just responds to the browser URL
localhost:5000/
:return: the rendered template "home.html"
"""
return render_template("home.html")
if __name__ == "__main__":
app.run(debug=True)
In the Dockerfile I'm exposing the same port:
RUN python3 -m pip install -r requirements.txt
COPY . /app
EXPOSE 5000
Then I run the container as:
sudo docker run -d -p 5000:5000 my_app:latest
and once the container is up, I'm able to acces to app at:
http://localhost:5000
Now, I'm trying to change to port 5100, for that I'm changing:
a) In the Dockerfile:
COPY . /app
EXPOSE 5100
...
b) When I run the container:
sudo docker run -d -p 5100:5100 my_app:latest
But when I try to visit: http://localhost:5100/
The app is not running there
When I do Docker ps this is shown:
EDIT:
I tried changing the flask app:
app.run(host='0.0.0.0', port=5100)
Still not working, this is the screenshot from docker ps:
Not sure if the error is because still says 5000: at the begining:
5000/tcp, 0.0.0.0:5100->5100/tcp romantic_fermi
This is what I get from docker logs...
* Serving Flask app "server" (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)
You could technically change the default port assigned to the Flask object, but it's simpler to just change the docker mapping.
When you run a command like this:
$ docker run -d -p 5100:5100 my_app:latest
You are saying that you want to forward a port from inside the container (on the right) to your host machine (on the left).
# Left side is your host machine
# Right side is inside of the container
5100:5100
So you could update your run to map to 5000 inside of the container:
$ docker run -d -p 5100:5000 my_app:latest
Then you'll be able to access via http://localhost:5100
PS: If you haven't used docker-compose before, I would highly recommend setting it up after you've worked through this issue. It'll make your life easier in general.
On your .py script ou need to set 5100 port with:
app.run(debug=True,host='0.0.0.0', port=5100)
Everything else you did is correct!
If still your python are listening on port 5000, probably it's the old version.

Categories

Resources