I am trying to play with a dockerized flask container using docker-compose. The flask app is a hello world app that works correctly when I test it on my host.
The docker-compose file looks like this:
version: '3'
services:
web:
image: ubuntu
build:
context: ./
dockerfile: Dockerfile
ports:
- "6000:5000"
My dockerfile looks like this:
FROM ubuntu
RUN apt-get update
RUN apt-get install -y python3 python3-pip
RUN pip3 install Flask
COPY app.py .
EXPOSE 5000
CMD ["python3", "app.py"]
The hello world app looks like this:
from flask import Flask, request
app = Flask(__name__)
#app.route("/")
def index():
return "Hello, World!"
if __name__ == "__main__":
app.run(debug=True)
When I bring up the containers using docker-compose up -d, there is no error. When I curl to localhost:6000, I get this :
curl -X PUT localhost:6000
curl: (52) Empty reply from server
It seems like the app is responding but not how it responds when I run it on a my host and just returns an empty string instead of "hello world" when I curl to it. What am I doing wrong?
There are several issues here:
You need to make your flask app accessible externally: app.run(host="0.0.0.0", debug=True).
You are sending a PUT request from curl but your app only allows GET (this is the default, you can add allowed methods to your route like this: #app.route("/", methods=["GET", "PUT"]).
This one is not actually a bug but rather a recommendation: don't use port 6000 if you need your app to be accessible via web browsers. At least some of them will display an ERR_UNSAFE_PORT error and will block the request. It will work via curl though.
Related
I'm trying to create a simple web application container within Ubuntu-WSL2 with the help of the Docker. So I've built my container creating my-simple-webapp folder and within that folder, I've created Dockerfile and app.py files;
Dockerfile
FROM ubuntu:16.04
RUN apt-get update && apt-get install -y python python-pip
RUN pip install flask
COPY app.py /opt/
ENTRYPOINT FLASK_APP=/opt/app.py flask run --host=0.0.0.0 --port=8080
app.py
import os
from flask import Flask
app = Flask(__name__)
#app.route("/")
def main():
return "Welcome!"
#app.route('/how are you')
def hello():
return 'I am good, how about you?'
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080)
When I run the command docker build ./my-simple-webapp it works without error. However when I use my browser to connect my container typing 172.17.0.2:8080, o.o.o.o:8080 or localhost:8080 connection times out.
Resource : https://github.com/mmumshad/simple-webapp-flask
If all you run is docker build... then you still need to start your container with docker run....
You can open the docker dashboard (in your Windows tray) to see if your container is actually running.
To actually run your app you need to start a container. First, build the image:
docker build -t simple-webapp-flask .
Then start a container using the image, with 8080:8080 mapping from container to your host:
docker run -p 8080:8080 simple-webapp-flask
If you want to deploy your flask application, you need to choose from the following options:
https://flask.palletsprojects.com/en/1.1.x/deploying/
The way you are trying to do it, can be used only for development purposes.
I am running Flask application in Python using docker-compose. I am able to run the Flask app using 5000 port. I am trying to run it on 6000 besides another Flask app running on 5000. But I am unable run it on 6000 port. Any help would be appreciated.
docker-compose.yml
version: '3.8'
services:
web:
build: ./web
ports:
- "6000:5000"
app.py
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
Dockerfile:
FROM python:3
COPY . /app
WORKDIR /app
RUN pip install -U pip
RUN pip install -r requirements.txt
ENTRYPOINT ["python"]
CMD ["app.py"]
requirements.txt
Flask==1.1.1
Port 6000 is listening. I am able to get a connection succeeded by executing nc command with host and port.
I am unable to run the app on port 6000.
I got the following when I hit http://#{HOST_IP}:6000 in browser
This site can’t be reached
The web page at http://#{HOST_IP}:6000/ might be temporarily down or it may have moved permanently to a new web address.
6000 is unsafe port that is why browser not allowing to access the application.
how-to-fix-err-unsafe-port-error-on-chrome-when-browsing-to-unsafe-ports
But you should not allow this port, just try to publish another port.
version: '3.8'
services:
web:
build: ./web
ports:
- "5001:5000"
For downvoter
Here is Github Repo to verify this
git clone https://github.com/Adiii717/dockerize-flask-app.git
cd dockerize-flask-app/
# this will not work in the browser
PORT=6000 docker-compose up
You haven't defined any routes. The app server has no idea what routes are available nor does it know what you want to return, so you need to specify that.
Here's a more complete version of app.py
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
Please refer to the Flask tutorial for a minimal app.
I am building and running this docker container. It is running a simple flask server. But when I run, it exited right after.
This is my Dockerfile
FROM python:3
WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8080
# CMD ["python3", "-m", "http.server", "8080"]
CMD ["python3", "./py_server.py"]
and this is py_server.py
from flask import Flask
app = Flask(__name__)
PORT = 8080
#app.route('/')
def hello_world():
return "Hello World"
if __name__ == '__main__':
app.run(PORT)
this is how I build and run the container respectively.
build:
docker build -t banuka/python-venv .
run:
docker run -dit -p 8080:8080 --name server1 banuka/python-venv:latest
Can someone tell me what I do wrong?
There are several issues:
You want the -it parameter, not -dit:
docker run -it -p 8080:8080 --name server1 banuka/python-venv:latest
You are passing PORT as a variable to the app.run() function, so that it is interpreted as the first host parameter, rather than what you want, which is for it to be the port parameter. What you want is this: app.run(port=8080)
As #Alexandre pointed out, if you're accessing the host remotely, then you need to explicitly bind it to host='0.0.0.0', so we need app.run(host='0.0.0.0',port=8080)
You have a bug in your Flask Code. You're trying to configure Flask Server PORT in a wrong way. This will throw the error you're experiencing:
AttributeError: 'int' object has no attribute 'startswith'
You should configure your Flask Server Port with the following way
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return "Hello World"
if __name__ == '__main__':
app.run(host='0.0.0.0',port=8080)
The documentation: https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.run
EDIT: Added host='0.0.0.0' so you can access your Flask Server remotely.
you are maybe running procces that finishes and then exit ?
if you run you py script and it finishes so your container will be closed to ...
try using while(true) //and then your code
I have two docker containers running Flask, just a simple backend/frontend example bit I was running through to learn docker and flask.
My frontend is:
from flask import Flask, jsonify
import requests
import simplejson
import json
app = Flask(__name__)
#app.route('/')
def hello():
uri = "http://127.0.0.1:5000/tasks"
try:
uResponse = requests.get(uri)
except requests.ConnectionError:
return "Connection Error"
Jresponse = uResponse.text
data = json.loads(Jresponse)
fullString = ""
title = data['tasks'][0]['title']
description = data['tasks'][0]['description']
fullString += title
fullString += "<br/>"
fullString += description
return fullString
if __name__ == '__main__':
app.run(debug=True,host="0.0.0.0", port=2000)
This works fine when I run it locally, and it also works when I run it in my docker. I'm able to go to the frontend at localhost:2000 and I see valid data.
My backend code is:
from flask import Flask,request, jsonify, make_response
from flask import abort
import csv
import json
import flask
app = Flask(__name__)
tasks = [
{
'id': 1,
'title': u'example title 1',
'description': u'example description 1',
'done': False
},
{
'id': 2,
'title': u'example title 2',
'description': u'example description 2',
'done': False
}
]
#app.route('/tasks', methods=['GET'])
def get_tasks():
return jsonify({'tasks': tasks})
if __name__ == '__main__':
app.run(debug=True,host="0.0.0.0", port=5000)
If I run both of these without docker, and I go to the frontend at localhost:2000 I get what I expect, the 0th entry of tasks description and title.
When I run these in docker, everything seems to work, but I get the Connection Error from the frontend. So, the requests.get(uri) seems to not be working once dockerized.
Here's my docker files
For Backend
FROM ubuntu:latest
MAINTAINER me
RUN apt-get update -y
RUN apt-get install -y python3-pip python3-dev build-essential
COPY . /app
WORKDIR /app
RUN pip3 install -r requirements.txt
ENTRYPOINT ["python3"]
CMD ["backend.py"]
For Frontend
FROM ubuntu:latest
MAINTAINER me
RUN apt-get update -y
RUN apt-get install -y python3-pip python3-dev build-essential
COPY . /app
WORKDIR /app
ENV FLASK_APP=/app/frontend.py
ENV FLASK_ENV=development
RUN pip3 install -r requirements.txt
ENTRYPOINT ["python3"]
CMD ["frontend.py"]
So, it appears they both work individually, but can't communicate. Why is that? As if it isn't obvious, I'm new to docker.
EDIT1
Command for frontend:
sudo docker run -d -p 2000:2000 frontend
Command for backend:
sudo docker run -d -p 5000:5000 backend
EDIT2
I moved this to docker compose, and have the same issue it appears.
docker-compose.yml
version: '3'
services:
backend:
build:
context: backend/
dockerfile: compose/lib/backend/Dockerfile
ports:
- "5000:5000"
frontend:
build:
context: lib/frontend/
dockerfile: compose/lib/frontend/Dockerfile
ports:
- "2000:2000"
No changes to Docker files. According to the docs here it is correct that I don't need specific networking, and there is a default network created. However, this still works fine under just flask, but I can't get them to attach using docker or docker-compose.
Can you share the docker run command you're using?
Are you exposing the ports with the -p flag?
docker run -p 5000:5000 ...
[Update]: Depending on your docker install and config, you may not be able to use that IP. Docker considers the 127.0.0.1 IP to mean "this container," not "this machine."
A bridged network may address this, but I'd recommend using docker-compose instead (details below).
If, for the purposes of this experiment, you are planning on running these two containers at the same time on the same machine always, you might want to look into docker-compose, which lets you run multiple containers from the same master command, and gives you nice bonus features like creating a virtual network for the two to connect to each other on, without external networks being able to access them. e.g. your data server can be visible only to your other flask container, but that one can be publicly exposed on your host machine's network interface.
In the case of docker-compose, you can use the following (untested) docker-compose.yml as a start:
version: 3
services:
backend:
build: path/to/dockerfile
ports:
- 5000:5000
frontend:
build: path/to/dockerfile
ports:
- 2000:2000
I am newbie to Docker and Python.I have created a simple python application using Flask .I would like to run it in a Docker container.The docker container shows it is running.However when I access the url ,I get localhost didn’t send any data.
docker container ls shows my container running on localhost and port no 8081
app.py
from flask import Flask, redirect, url_for, request
app = Flask(__name__)
#app.route("/hello", methods=["GET","POST"])
def hello():
return "Hello World!"
if __name__ == '__main__':
app.run(debug=True, port=8081,host='0.0.0.0')
Dockerfile
FROM python:2.7
ADD app.py /
RUN pip install flask
EXPOSE 8081
CMD ["flask", "run", "--host=0.0.0.0"]
CMD ["python", "app.py", "--host=0.0.0.0"]
When I run the same app.py in my local environment.I get the desired data on the localhost url. Could someone guide me in the right direction?
Image is tagged dockerimage:latest and I run it with:
docker run -it -p 8081:8081 dockerimage
And checking for the container with docker container ls shows:
0.0.0.0:8081->8081/tcp
Everything seems fine in your Dockerfile and the Flask script, but I will suggest two thing.
Update base image to python:3.7 as 2.7 will reach its end of life.
Remove CMD ["flask", "run", "--host=0.0.0.0"] this as there is only one CMD per dockerfile.
FROM python:3.7.4-alpine3.10
RUN pip install flask
ADD app.py /
EXPOSE 8081
CMD ["python", "app.py", "--host=0.0.0.0"]
Now run the container
docker run -it --name my_app --rm -p 8081:8081 dockerimage
Open the browser and hit
http://localhost:8081/hello
or
docker exec -it my_app ash -c "apk add --no-cache curl && curl localhost:8081/hello"
One of the above should work.
If you the second command work then something wrong with host configuration.