I have an iamge which is a flask app.
I am trying to run it, like so:
import docker
import requests
client = docker.from_env()
if __name__ == "__main__":
client.containers.run(IMAGE_NAME, detach=True, ports={"1000/tcp": "1000"})
res = requests.get("http://localhost:1000/health")
print(res.status_code)
The flask app:
#app.route("/health")
def health_check():
return "healthy"
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True, port=int(os.environ.get("PORT", 5000)))
However I get an error:
requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
Presumably the connection dies out after run ends?
How do I make it so that the app keeps running in the background?
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 5000
# run the command
CMD ["python", "app.py"]
Running the container using the following should solve the issue
client.containers.run(IMAGE_NAME, detach=True, ports={"5000/tcp": "5000"}) which binds port 5000 of the container to port 5000 of the host machine.
Ports 0 to 1024 are strictly reserved for OS applications, it's always adviced to use ports greater than 1024 for the host machine. However, to use ports less than 1024 you'll need to have sudo access which is not advisable.
Add a few sleeps in conjunction with #Saiprasad's answer solved this issue:
if __name__ == "__main__":
container = client.containers.run(IMAGE_NAME, detach=True, ports={"5000/tcp": "5000"})
import time
time.sleep(1)
res = requests.get("http://localhost:5000/health")
print(res.status_code)
print(res.text)
container.kill()
time.sleep(1)
Related
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
so I do have the next code, which is a Flask app, and it runs on a Raspberry inside a docker container with NginX and Uwsgi.
I need to be able to connect to local ssh and also to get the correct MAC address of the Raspberry.
import socket
import time
import pwd
import os
from ssh2.session import Session
from flask import Flask
from flask import request
app = Flask(__name__)
usernameSSH = pwd.getpwuid(os.getuid()).pw_name
passwordSSH = "password"
host = 'localhost' # the specified host for the SSH
#app.route("/")
def hello():
return gma() #get mac address of the device
#app.route("/ssh") #This is the connection to ssh
def welcome():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, 22))
session = Session()
session.handshake(sock)
session.userauth_password(usernameSSH, passwordSSH)
channel = session.open_session()
channel.shell()
channel.write("ifconfig\n")
time.sleep(2)
size, data = channel.read()
channel.close()
return data.decode("utf-8")
if __name__ == "__main__":
app.run(threaded=True)
So. If I run my docker image like this:
docker run -p 3134:80 dockapp
I'm able to connect with the external IP and port. But the mac address that I get on external IP:port/ it's wrong, it's the mac address of the container. Also, I get auth error when trying to connect to ssh.
If I run my image like this:
sudo docker run -p 3134:80 --network=host dockapp
I'm able to reach the API only by typing the local address of the RaspBerry but I do get the correct MAC Addres but still I'm not able to connect to local SSH and I get an authError. The program is running fine without docker. Any solutions ?
Also, adding host="0.0.0.0" to the Flask App hasn't helped at all
DockerFile:
FROM cseelye/rpi-nginx-uwsgi-flask
MAINTAINER Carl Seelye <cseelye#gmail.com>
RUN apt-get update && apt-get -y install cmake libssl-dev
COPY exampleapp /app
RUN pip install -U -r /app/requirements.txt
my python app runs fine as a local docker container, but when trying to deploy on heroku, i get this error:
Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
if __name__ == '__main__':
from os import environ
app.run(host='0.0.0.0', port=environ.get('PORT', 5000))
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 pip3 install --no-cache-dir -r requirements.txt
# heroku doesn't need this
# EXPOSE 5000
# run the command
CMD ["python3", "app.py"]
i thought it might have to do with the app being a bit too big for dyno=1 and that i'd have to pay to increase the dynos? but I'm not sure..
thanks in advance!!
The application cannot bind to the Heroku port, nothing to do with the Dyno. Try to cast to int the port before assigning it
port = int(os.environ.get("PORT", 5000))
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 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.