So, I've got this flask app that works fine when I run it via the terminal, but for some reason, if I start up a docker container, it instantly exits with 'exit code zero'.
Here is the folder structure:
https://imgur.com/a/BOGCt6S
docker-compose.yml:
version: '3.2'
services:
flask-app:
build: ./Flask_App
volumes:
- ./Flask_App/static:/Flask_App/static
- ./Flask_App/db:/Flask_App/db
ports:
- '5001:5001'
# restart: unless-stopped
Dockerfile:
FROM python:3
# Setup env
COPY requirements.txt ./
RUN pip install -r requirements.txt
# Setup App
RUN mkdir -p /Flask_App
COPY . /Flask_App
WORKDIR /Flask_App
EXPOSE 5001
ENTRYPOINT [ 'python3' ]
CMD [ 'app.py' ]
and the app.py file: (I know its just imports, but it works fine when I run it via the terminal on the host, so it probably is working ok)
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask_bootstrap import Bootstrap
from forms import *
app = Flask(__name__)
app.config.from_pyfile('config.py')
Bootstrap(app)
db = SQLAlchemy(app)
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
from views import *
if __name__ == '__main__':
app.run(host=app.config['HOST'], port=app.config['PORT'], debug=app.config['DEBUG'])
and just in case, here is a part of the 'config.py' file:
DEBUG = False
HOST = '0.0.0.0'
PORT = 5001
As said by David Maze in a comment, the single quotes(') I used in ENTRYPOINT and CMD should be changed to double quotes ("), since they are supposed to be JSON arrays.
Related
I am trying to build and run a flask application using docker on GCP.
My file structure is as follows:
> /project
> static (contains some images)
> templates (contains html files)
> tmp_data (contains some data that is created during usage of the app)
> __init__.py
> auth.py (app has a login feature, this script helps authorize them)
> main.py
> Dockerfile
> some other function scripts
My Dockerfile is as follows:
FROM python:3.9-slim
RUN pip3 install Flask gunicorn scipy seaborn matplotlib pandas numpy flask_excel flask_login flask_sqlalchemy
COPY . /project
WORKDIR project
ENV FLASK_APP=main.python
# run flask in dev mode
ENV FLASK_ENV=development
EXPOSE 5001:5000
CMD ["flask", "run", "--host", "0.0.0.0"]
My main.py file is as follows:
from flask import Blueprint, render_template, redirect, url_for
from flask_login import login_required, current_user
from . import db
import flask_excel as excel
import json
# user written imports (not sure why it wants relative imports now?)
from .generate_data import get_truncated_normal, create_data
from .create_graphs import plot_graph, hist_plot, bar_plot, pie_plot, data_comments
from .generate_html_file import generate_html
main = Blueprint('main', __name__)
#main.route('/')
def index():
return render_template('index.html')
... some functions and flask views ...
When I build my app (successfully) using the command
~/some_upper_folder/project (my_sandbox)$ docker build -t project .
and then run it with the command
~/some_upper_folder/project (my_sandbox)$ docker run project
I get the error:
* Serving Flask app 'main.python' (lazy loading)
* Environment: development
* Debug mode: on
Usage: flask run [OPTIONS]
Try 'flask run --help' for help.
Error: Could not import 'project.main.python'.
I am not sure why this is occurring, I'm guessing this is due to the fact that I'm referencing an incorrect directory?
NOTE: The app is working correctly, I can run it using a venv created in another folder not seen here
I am trying to migrate my python changes to my docker project, however when I try to run the command python manage.py db migrate I get the error unknown database 'main', however when I look inside of my docker-compose.yml file I see that main is indeed defined inside of the MYSQL_DATABASE variable inside of the container db. I have tried some solutions found on StackOverflow as well as Github like getting the restart: always out of my docker-compose.yml script and making a Windows PowerShell script that will run to restart my docker container as found here: MYSQL Docker container gives "unknown database" error, and trying to change my DATA_SAVE_PATH variable and other such variables in my docker-compose.yml: https://github.com/laradock/laradock/issues/1017 and I have also tried to change the MYSQL_DATABASE variable to a different name but that doesn't work either.
Here is the full error that I am receiving when I run my code:
sqlalchemy.exc.OperationalError: (MySQLdb._exceptions.OperationalError) (1049, "Unknown database 'main'")
(Background on this error at: http://sqlalche.me/e/13/e3q8)
Here is my docker-compose.yml script:
version: '3.9'
services:
backend:
build:
context: .
dockerfile: Dockerfile
ports:
- 8001:5000
volumes:
- .:/app
depends_on:
- db
db:
image: mysql:5.7.22
restart: always
environment:
MYSQL_DATABASE: main
MYSQL_USER: root
MYSQL_PASSWORD: root
MYSQL_ROOT_PASSWORD: root
volumes:
- .dbdata:/var/lib/mysql
ports:
- 33067:3306
Here is my Dockerfile:
FROM python:3.9
ENV PYTHONUNBUFFERED 1
WORKDIR /app
COPY requirements.txt /app/requirements.txt
RUN pip install -r requirements.txt
COPY . /app
CMD python main.py
Here is my main.py file:
from flask_cors import CORS
from sqlalchemy import UniqueConstraint
from vegaaimain.vegamain import main
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = 'mysql://root:root#db/main'
CORS(app)
db = SQLAlchemy(app)
class VegaScriptRun(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=False)
title = db.Column(db.String(200))
description = db.Column(db.String(400))
image = db.Column(db.String(200))
main()
class VegaScriptUser(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer)
title = db.Column(db.String(200))
description = db.Column(db.String(400))
image = db.Column(db.String(200))
UniqueConstraint('user_id', 'title', 'description', 'image', name='user_experiment_unique')
#app.route('/')
def index():
return 'Hello'
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
And finally my manage.py file, and requirements.txt file:
from main import app, db
from flask_migrate import Migrate, MigrateCommand
from flask_script import Manager
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
if __name__ == '__main__':
manager.run()
requirements.txt
Flask==1.1.2
Flask-SQLAlchemy==2.4.4
SQLAlchemy==1.3.20
Flask-Migrate==3.0.0
Flask-Script==2.0.6
Flask-Cors==3.0.9
requests==2.25.0
mysqlclient==2.0.1
pika==1.1.0
wolframalpha==5.0.0
What exactly am I missing or doing wrong here, thank you!
I solved this problem by looking in my .dbdata folder and found my service, I then changed the MYSQL_DATABASE variable and the app configuration to the same variable as MYSQL_DATABASE which was vegatest instead of main.
So I ran the same command python manager.py db migrate and I got a successful migration.
I have a flask application that runs perfectly in localhost even with docker.
But as soon as I deploy it, it doesn't work anymore.
I have a 404 errorcin the back, and the browser answers with:
Not Found The requested URL was not found on the server. If you
entered the URL manually please check your spelling and try again.
When I curl localhost:5010/helloworld from my server, I get an empty answer.. I don't know why, but it seems that the flask server doesn't restart:
WARNING:root:no config found for parameter None default mode debug loaded
WARNING:flask_cors.core:Unknown option passed to Flask-CORS: headers
WARNING:flask_cors.core:Unknown option passed to Flask-CORS: headers
* Serving Flask app "application" (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: on
INFO:werkzeug: * Running on https://0.0.0.0:5000/ (Press CTRL+C to quit)
INFO:werkzeug: * Restarting with stat
WARNING:root:no config found for parameter None default mode debug loaded
WARNING:flask_cors.core:Unknown option passed to Flask-CORS: headers
WARNING:flask_cors.core:Unknown option passed to Flask-CORS: headers
WARNING:werkzeug: * Debugger is active!
INFO:werkzeug: * Debugger PIN: 899-121-971
run.py:
from application import create_app, db
import sys
from OpenSSL import SSL
context = SSL.Context(SSL.PROTOCOL_TLSv1_2)
context.use_privatekey_file('./ssl/server.key')
context.use_certificate_file('./ssl/server.crt')
# we set the app default value is debug
appStartingMode= None
if(len (sys.argv) >1):
appStartingMode= sys.argv[1]
app = create_app(appStartingMode)
if __name__ == "__main__":
app.debug = True
app.use_reloader = True
app.run(host=app.config['FLASK_HOST'], port=app.config['FLASK_PORT'],ssl_context = context)
The Dockerfile:
FROM python:3.9.1
EXPOSE 5000
# Install pip requirements
COPY requirements.txt .
RUN python -m pip install -r requirements.txt
WORKDIR /app
COPY . /app
# Switching to a non-root user, please refer to https://aka.ms/vscode-docker-python-user-rights
RUN useradd appuser && chown -R appuser /app
USER appuser
# During debugging, this entry point will be overridden. For more information, please refer to https://aka.ms/vscode-docker-python-debug
CMD [ "python", "./run.py" ]
An extract of the docker-compose.yml:
bel-backend:
container_name: bel-backend
env_file: database-variables.env
build:
context: /home/ubuntu/sob/sob-2020-back-end
ports:
- 5010:5000
depends_on :
- mysql-server
And the route I try to access:
#app.route('/helloworld', methods=['GET'])
def helloWorld():
print("ok")
return 'Hello World !'
By typing: https://ipofthemachine:5010/helloworld
even if the https crosses out because I have to renew my certificate.
Any ideas?
[EDIT]
Better if I share the config.py:
from os import environ, path
from dotenv import load_dotenv
basedir = path.abspath(path.dirname(__file__))
load_dotenv(path.join(basedir, '.env'))
class Config:
"""Base config."""
SECRET_KEY = environ.get('SECRET_KEY')
'''
SESSION_COOKIE_NAME = environ.get('SESSION_COOKIE_NAME')
STATIC_FOLDER = 'static'
TEMPLATES_FOLDER = 'templates'
'''
class DebugConfig(Config):
# General Flask Config
FLASK_ENV = 'development'
DEBUG = False
#TESTING = True
FLASK_APP = 'run.py'
FLASK_PORT=5000
FLASK_HOST='0.0.0.0'
# Database
SQLALCHEMY_DATABASE_URI = environ.get('SQLALCHEMY_DATABASE_URI')
SQLALCHEMY_ECHO = False
SQLALCHEMY_TRACK_MODIFICATIONS = False
Add to the bottom of your routes script
if __name__ == '__main__':
app.run(host='0.0.0.0')
#Dunski I answer because the main post is gonna be long if I edit it..
So I did what you said: I hard-coded the app.run. Now, I have:
appStartingMode= None
if(len (sys.argv) >1):
appStartingMode= sys.argv[1]
app = create_app(appStartingMode)
The Dockerfile:
FROM python:3.9.1
EXPOSE 5000
# Install pip requirements
COPY requirements.txt .
RUN python -m pip install -r requirements.txt
WORKDIR /app
COPY . /app
# Switching to a non-root user, please refer to https://aka.ms/vscode-docker-python-user-rights
RUN useradd appuser && chown -R appuser /app
USER appuser
# During debugging, this entry point will be overridden. For more information, please refer to https://aka.ms/vscode-docker-python-debug
CMD ["flask", "run", "-host", "0.0.0.0", "-port", "5000"]
And the .env file I read in the docker-compose:
user=root
password=*****
host=mysql
port=3306
database=bel_2020_db
SECRET_KEY=secret
FLASK_APP=run.py
FLASK_ENV=development
FLASK_DEBUG=0
SQLALCHEMY_DATABASE_URI=mysql://${user}:${password}#${host}:${port}/${database
}?charset=utf8mb4&binary&binary_prefix=true
SQLALCHEMY_ECHO=0
SQLALCHEMY_TRACK_MODIFICATIONS=0
Now, I tried to curl the docker with his ip adress from the server itself... Didn't work!!!!! Everything works on localhost... I'm starting to lose hope.
The server DO receive the request, but returns a 404...
This question already has answers here:
Deploying a minimal flask app in docker - server connection issues
(8 answers)
Closed 2 years ago.
I have simple flask app which uses SQLLite database.
Here is my app.py code
from flask import Flask
from flask_restful import Api
from flask_jwt import JWT
from datetime import timedelta
from db import db
from security import authenticate, identity
from resources.user import UserRegister
from resources.product import Product, ProductList
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.secret_key = '#hsgvTyb#3gd###123'
api = Api(app)
#app.before_first_request
def create_tables():
db.create_all()
jwt = JWT(app, authenticate, identity) # /auth
app.config['JWT_EXPIRATION_DELTA'] = timedelta(seconds=1800)
api.add_resource(Product, '/product/<string:name>')
api.add_resource(ProductList, '/products')
api.add_resource(UserRegister, '/register')
if __name__ == '__main__':
db.init_app(app)
app.run(port=5000, debug=False)
DockerFile as below:
FROM python:3
ADD app/ /app
WORKDIR /app
RUN apt-get update
RUN pip install -r requirements.txt
CMD python app.py
docker-compose.yml as below:
version: "2"
services:
app:
container_name: test-146957-app
build:
context: ../
dockerfile: deployments/app/Dockerfile
ports:
- "5000:5000"
Now when I execute docker-compose up command it is showing container is running but I hit any endpoints from postman, it does not return any response.
You have to add host=0.0.0.0 as Flask run parameter. See the documentation for details: https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.run
When trying to build the image, i'm getting the error below. I am also adding the related project files.
Dockerfile
docker-compose.yml
init.py
manage.py
Error:
Building users-service
Step 1/7 : FROM python:3.6.1
ERROR: Service 'users-service' failed to build: Get https://registry-1.docker.io/v2/: dial tcp 52.206.156.207:443: getsockopt: connection refused
Here is my Dockerfile
FROM python:3.6.1
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
ADD ./requirements.txt /usr/src/app/requirements.txt
RUN pip install -r requirements.txt
ADD . /usr/src/app
CMD python manage.py runserver -h 0.0.0.0
Here is the docker-compose.yml
version: '2.1'
services:
users-service:
container_name: users-service
build: .
volumes:
- '.:/usr/src/app'
ports:
- 5001:5000 # expose ports - HOST:CONTAINER
init.py
from flask import Flask, jsonify
# instantiate the app
app = Flask(__name__)
# set config
app.config.from_object('project.config.DevelopmentConfig')
#app.route('/ping', methods=['GET'])
def ping_pong():
return jsonify({'status': 'success',
'message': "pong"})
manage.py
from flask_script import Manager
from project import app
# configure your app
manager = Manager(app)
if __name__ == '__main__':
manager.run()