I am running a python flask app on an amazon ec2 linux instace.
MY python app looks like:
application.py
#!flask/bin/python
from flask import Flask
application = Flask(__name__)
#application.route('/', methods=['GET', 'POST'])
def index():
return '{"Output":"Hello World"}'
if __name__ == '__main__':
application.run(host='0.0.0.0', port=80, debug=False)
my supervisor config looks like:
supervisor.conf
[program:flaskapplication]
command = /home/ec2-user/myapp/venv/bin/python /home/ec2-user/myapp/application.py
stdout_logfile = /var/log/watcher-stdout.log
stdout_logfile_maxbytes = 10MB
stdout_logfile_backups = 5
stderr_logfile = /var/log/watcher-stderr.log
stderr_logfile_maxbytes = 10MB
stderr_logfile_backups = 5
When I do the following command:
supervisorctl -c supervisor.conf
I get the following response:
00:00:00 /home/ec2-user/myapp/venv/bin/python2.7 /home/ec2-user/myapp/venv/bin/supervisord -c supervisor.conf
But when I hit the Amazon instance link, nothing is displayed. I get a server not responding page. What am I doing wrong?
I think you probably need an end-point:
>>> #application.route('/say_hi', methods=['POST'])
I realized that port 80 by default is not configured to be an incoming port in the EC2 security group. Once I added port 80 to be a verified incoming group, I was able to run the application.
Related
I'm trying to deploy my Flask app by Docker container. When I run the app on the local machine, the log file writes and updates normally. After I deployed it in Docker, the app runs normally but the log file doesn't seem to appear.
This is my Flask code:
Python version: 3.7, Flask version: 1.1.2
from elasticapm.contrib.flask import ElasticAPM
from elasticapm.handlers.logging import LoggingHandler
from flask import Flask, jsonify, request
import logging
from logging.handlers import TimedRotatingFileHandler
formatter = logging.Formatter("[%(asctime)s - %(levelname)s] %(message)s")
handler = TimedRotatingFileHandler('./log/apm-test.log',when='midnight',interval=1,encoding='utf8')
handler.suffix = '%Y_%m_%d'
handler.setFormatter(formatter)
logger = logging.getLogger()
logger.setLevel(logging.INFO)
logger.addHandler(handler)
server_domain = '0.0.0.0'
app = Flask(__name__)
app.config['ELASTIC_APM'] = {
# Set required service name. Allowed characters:
# a-z, A-Z, 0-9, -, _, and space
'SERVICE_NAME': 'Master Node',
# Use if APM Server requires a token
'SECRET_TOKEN': '',
# Set custom APM Server URL (default: http://localhost:8200)
'ELASTIC_APM_SERVER_URL': 'http://elastic-agent:8200',
'ENVIRONMENT':'production'
}
apm = ElasticAPM(app)
#app.route('/',methods=['post'])
def index():
app.logger.info("info log -- POST / 200")
return 'Hello!'
#app.route('/route1',methods=['get'])
def passdata():
a = {'test01':1,'test02':2}
app.logger.info("info log -- GET /route1 200")
return jsonify(a)
#app.route('/route2',methods=['get'])
def postdata():
b = {'test003':3,'test004':4}
app.logger.info('info: "get /route2 HTTP1.1" --200')
return jsonify(b)
if __name__ == '__main__':
apm_handler = LoggingHandler(client=apm.client)
apm_handler.setLevel(logging.INFO)
app.logger.addHandler(apm_handler)
app.run(host=server_domain,port=5000)
This is my Dockerfile and command:
Docker-desktop(Windows) version: 4.13
Dockerfile
FROM python:3.7-slim
COPY ./apm-test.py /usr/share/apm-test.py
RUN pip install elastic-apm flask blinker
ENV ELASTIC_APM_SERVER_URL='http://elastic-agent:8200'
EXPOSE 5000
CMD ["python", "./apm-test.py"]
Docker command
docker run -d --name apm-client00 apm-client00
I tried to mount the log folder and the exact log file in my local machine into the same relative container path as the py file writes the log in local machine, but it is still the same.
I have been using the following python 3 script in a CDSW session which run just fine as long as the session is not killed.
I am able to click on the top-right grid and select my app
hello.py
from flask import Flask
import os
app = Flask(__name__)
#app.route('/')
def index():
return 'Web App with Python Flask!'
app.run(host=os.getenv("CDSW_IP_ADDRESS"), port=int(os.getenv('CDSW_PUBLIC_PORT')))
I would like this app to run 24/7, so instead of using a Session or scheduling a job that never ends, I would like to create a CDSW Application so that it doesn't stop.
This is the settings on my application:
Logs:
from flask import Flask
import os
app = Flask(__name__)
#app.route('/')
def index():
return 'Web App with Python Flask!'
app.run(host=os.getenv("CDSW_IP_ADDRESS"), port=int(os.getenv('CDSW_PUBLIC_PORT')))
* Serving Flask app "__main__" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
OSError: [Errno 98] Address already in use
I tried to change the port from CDSW_PUBLIC_PORT to CDSW_APP_PORT but it ends up the same.
As it mentions here maybe you need to change this line of code
app.run(host=os.getenv("CDSW_IP_ADDRESS"), port=int(os.getenv('CDSW_PUBLIC_PORT')))
to this
app.run(host="127.0.0.1", port=int(os.environ['CDSW_APP_PORT']))
Hope it works!
I'm new to python, so this might be a dumb question, but I have the following issue:
I'm trying to deploy a Flask-SocketIO app to heroku, my app.py looks like this:
app = Flask(__name__)
socketio = SocketIO(app)
opt: Dict[Any, Any] = {}
.
.
#socketio.on('connect')
def joined():
test = json.dumps(opt)
emit('test', test)
.
.
if __name__ == '__main__':
opt = setup_args()
socketio.run(app)
My procfile looks like this:
web: gunicorn -k flask_sockets.worker app:app
If i run heroku local my server starts as expected, and I can establish a socket conection with my client, but my variable opt seems not to be filled. From what i've read in the docs, this is because the procfile does the socketio.run(app) for me, and my __main__ part is not getting executed.
I need to somehow trigger a method that initializes some variables in my app.py.
How can I achieve this?
Thanks
Is there a reason why you don't simply move opt = setup_args() out of the if statment, and move it, say, somewhere at the top of the file?
I have a sample Flask-RestPlus application as myapp.py:
from flask import Flask
from flask_restplus import Resource, API
API = Api(version='1.0', title='my_routes')
MY_NAMESPACE = API.namespace('v1.0/routes', description='v1.0 routes')
def initialize():
app = Flask(__name__)
API.init_app(app)
API.add_namespace(MY_NAMESPACE)
return app
#MY_NAMESPACE.route('/hello')
class HelloWorld(Resource):
def get(self):
return {'hello': 'world'}
if __name__ == '__main__':
MY_ROUTE = initialize()
MY_ROUTE.run(host='0.0.0.0', port=8080)
This works fine if I am running python myapp.py. Since I want to run to run this code on production, I want to use Gunicorn. I have gunicorn installed on my UNIX machine. Sample code from https://gunicorn.org/ works perfectly fine. How do I run code in my case? I tried:
gunicorn -w 4 myapp:initialize
gunicorn -w 4 "myapp:initialize()"
gunicorn -w 4 myapp:main
But none of them worked. Do I have to make some changes in code?
In your myapp.py, turn your part:
if __name__ == '__main__':
MY_ROUTE = initialize()
MY_ROUTE.run(host='0.0.0.0', port=8080)
into:
app = initialize() # app has to be accessible outside if
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
and then run
gunicorn --bind 0.0.0.0:8080 --workers 4 myapp:app --log-level debug
if you want to run in production mode, specify --log-level info.
The code below works on localhost. I get the message '50' which is the number of rows I have. But it doesn't work when I push it to heroku. I get the "Application error message" and the heroku logs just say app crashed.
And yes, the heroku app has the mongolab add-on connected.
What am I doing incorrectly?
import os
from flask import Flask
from flask.ext.pymongo import PyMongo
app = Flask(__name__)
app.debug = True
app.config['MONGO_URI'] = os.environ['MONGOLAB_URI']
mongo = PyMongo(app, config_prefix='MONGO')
#app.route("/")
def hello():
num = mongo.db.test.count()
return '%s' % num
if __name__ == "__main__":
app.run()
On heroku (unless you've changed it) mongolab stores its URI at MONGOLAB_URI (per these docs).
The crash is probably PyMongo saying it can't connect to NULL, but you can check that with heroku logs on the cli.
Check that you PyMongo version is compatible with Mongo 3.0. MongoLab has switched to it recently: http://blog.mongolab.com/2015/07/mongodb-version-3-0-now-ga-on-mongolab/