From 02d27c386810e136e11e418ed7e69d4e36101e08 Mon Sep 17 00:00:00 2001 From: Daniel Cortes Date: Thu, 14 Mar 2019 00:40:42 -0300 Subject: [PATCH] Mejorado el deploy por docker Ahora se usan archivos .env para la configuracion en vez del archivo en la instancia Tambien se paso a usar docker-compose para tambien crear la base de datos Se tienen volumenes separados para la carpeta de uploads y para la base de datos Cambie los comandos para que sea solo uno poble la base de datos con todo lo que implica Se paso a mysql tambien --- .gitignore | 3 +- Dockerfile | 12 ++++---- db.env.example | 2 ++ docker-compose.yml | 22 +++++++++++++++ files/__init__.py | 15 ++++------ files/commands.py | 69 +++++++++++++++------------------------------- files/files.py | 2 +- files/models.py | 14 +++++----- requirements.txt | 7 +++-- web.env.example | 12 ++++++++ 10 files changed, 84 insertions(+), 74 deletions(-) create mode 100644 db.env.example create mode 100644 docker-compose.yml create mode 100644 web.env.example diff --git a/.gitignore b/.gitignore index b1c2d86..8d0050b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ - # Created by https://www.gitignore.io/api/flask # Edit at https://www.gitignore.io/?templates=flask @@ -127,3 +126,5 @@ dmypy.json # End of https://www.gitignore.io/api/flask uploads/ +db.env +web.env diff --git a/Dockerfile b/Dockerfile index 898beb9..bc98c29 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,13 @@ FROM python:alpine RUN mkdir /app -COPY . /app +COPY requirements.txt gunicorn.conf run.py /app/ +COPY files/ /app/files +ENV FLASK_APP=files WORKDIR /app - +RUN apk add mariadb-connector-c-dev gcc musl-dev RUN pip install --no-cache-dir -r requirements.txt +RUN apk del gcc musl-dev +EXPOSE 8080 -EXPOSE 5000 - -ENV GUNICORN_WORKERS 2 -ENV GUNICORN_BIND 0.0.0.0:8080 CMD ["gunicorn", "--config", "gunicorn.conf", "run:app"] diff --git a/db.env.example b/db.env.example new file mode 100644 index 0000000..ff92198 --- /dev/null +++ b/db.env.example @@ -0,0 +1,2 @@ +MYSQL_ROOT_PASSWORD=secret +MYSQL_DATABASE=db diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..6a97588 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3' +services: + web: + build: . + ports: + - "8080:8080" + volumes: + - uploads:/app/uploads + depends_on: + - db + env_file: + - web.env + db: + image: mariadb + volumes: + - dbdata:/var/lib/mysql + env_file: + - db.env +volumes: + dbdata: + uploads: + diff --git a/files/__init__.py b/files/__init__.py index c98ed50..a98b04d 100644 --- a/files/__init__.py +++ b/files/__init__.py @@ -6,18 +6,15 @@ from werkzeug.wsgi import SharedDataMiddleware def create_app(): app = Flask(__name__, instance_relative_config=True) - app.config.from_mapping( - SQLALCHEMY_DATABASE_URI="sqlite:///{}".format( - os.path.join(app.instance_path, 'files.sqlite')), - SQLALCHEMY_TRACK_MODIFICATIONS=False, - USERNAME='dev', - PASSWORD='secret', - SECRET_KEY='1337', - UPLOAD_FOLDER='uploads' + SQLALCHEMY_DATABASE_URI=os.environ.get("SQLALCHEMY_DATABASE_URI"), + SQLALCHEMY_TRACK_MODIFICATIONS=os.environ.get("SQLALCHEMY_TRACK_MODIFICATIONS"), + USERNAME=os.environ.get("USERNAME"), + PASSWORD=os.environ.get("PASSWORD"), + SECRET_KEY=os.environ.get("SECRET_KEY"), + UPLOAD_FOLDER=os.environ.get("UPLOAD_FOLDER") ) - app.config.from_pyfile('config.py') app.wsgi_app = SharedDataMiddleware( app.wsgi_app, {'/uploads': app.config['UPLOAD_FOLDER']}) diff --git a/files/commands.py b/files/commands.py index 34a5ad6..426f256 100644 --- a/files/commands.py +++ b/files/commands.py @@ -8,30 +8,33 @@ from werkzeug.security import generate_password_hash from files.models import db, User, Category, File, FileType - def init_db(): - db.drop_all() db.create_all() - def generate_admin(): username = current_app.config['USERNAME'] - password = current_app.config['PASSWORD'] - user = User(username, generate_password_hash(password)) - db.session.add(user) - db.session.commit() + if User.query.filter_by(username=username).first() is None: + password = current_app.config['PASSWORD'] + + user = User(username, generate_password_hash(password)) + db.session.add(user) + db.session.commit() def add_defaults(): - default_category = Category('Default') - default_file_type = FileType('Default') - code_file_type = FileType('Code') - image_file_type = FileType('Image') - db.session.add(default_category) - db.session.add(default_file_type) - db.session.add(code_file_type) - db.session.add(image_file_type) + if Category.query.filter_by(name='Default').first() is None: + default_category = Category('Default') + db.session.add(default_category) + if FileType.query.filter_by(name='Default').first() is None: + default_file_type = FileType('Default') + db.session.add(default_file_type) + if FileType.query.filter_by(name='Code').first() is None: + code_file_type = FileType('Code') + db.session.add(code_file_type) + if FileType.query.filter_by(name='Image').first() is None: + image_file_type = FileType('Image') + db.session.add(image_file_type) db.session.commit() @@ -60,42 +63,14 @@ def add_files(): @with_appcontext def init_db_command(): """ - Creates the db file + Creates and initializes the db with data + If the db was previously created it just keep it and its data """ init_db() - - -@click.command("add-defaults") -@with_appcontext -def add_defaults_command(): - """ - Initializes the database with default data - """ - add_defaults() - click.echo("Defaults added") - - -@click.command('generate-admin') -@with_appcontext -def generate_admin_command(): - """Creates the admin of the system""" generate_admin() - click.echo('The admin was created') - - -@click.command('add-files') -@with_appcontext -def add_files_command(): - """ - Generates the rows in the database for the files currently uploaded - They all will have default privacy, so, public - """ - added_size = add_files() - click.echo(f'added {added_size} files') + add_defaults() + add_files() def init_app(app): app.cli.add_command(init_db_command) - app.cli.add_command(add_defaults_command) - app.cli.add_command(generate_admin_command) - app.cli.add_command(add_files_command) diff --git a/files/files.py b/files/files.py index 2e22184..1e60cfd 100644 --- a/files/files.py +++ b/files/files.py @@ -140,7 +140,7 @@ def preview_file(file_id): if file.type.name == 'Code': try: content = open(_get_path_in_upload(file.filename), 'r').read() - except IOError: + except UnicodeDecodeError: flash('Error: file is binary, can\'t be displayed') content = 'Error' diff --git a/files/models.py b/files/models.py index a06c94a..3fd642d 100644 --- a/files/models.py +++ b/files/models.py @@ -8,8 +8,8 @@ db = SQLAlchemy() class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) - username = db.Column(db.String, unique=True, nullable=False) - password = db.Column(db.String, nullable=False) + username = db.Column(db.String(255), unique=True, nullable=False) + password = db.Column(db.String(255), nullable=False) def __init__(self, username=None, password=None): self.username = username @@ -22,8 +22,8 @@ class User(db.Model): class Message(db.Model): __tablename__ = 'messages' id = db.Column(db.Integer, primary_key=True) - name = db.Column(db.String, nullable=False) - email = db.Column(db.String, nullable=False) + name = db.Column(db.String(255), nullable=False) + email = db.Column(db.String(255), nullable=False) message = db.Column(db.Text, nullable=False) sended = db.Column(db.DateTime, default=datetime.utcnow()) @@ -39,7 +39,7 @@ class Message(db.Model): class File(db.Model): __tablename__ = 'files' id = db.Column(db.Integer, primary_key=True) - filename = db.Column(db.String, nullable=False) + filename = db.Column(db.String(255), nullable=False) private = db.Column(db.Integer, nullable=False) category_id = db.Column( db.Integer, @@ -68,7 +68,7 @@ class File(db.Model): class Category(db.Model): __tablename__ = 'categories' id = db.Column(db.Integer, primary_key=True) - name = db.Column(db.String, nullable=False) + name = db.Column(db.String(255), nullable=False) files = db.relationship('File', backref='category', lazy=True) def __init__(self, name=None): @@ -81,7 +81,7 @@ class Category(db.Model): class FileType(db.Model): __tablename__ = 'file_types' id = db.Column(db.Integer, primary_key=True) - name = db.Column(db.String, nullable=False) + name = db.Column(db.String(255), nullable=False) files = db.relationship('File', backref='type', lazy=True) def __init__(self, name=None): diff --git a/requirements.txt b/requirements.txt index 020cdc1..ecc1093 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ -Flask==1.0.2 -Flask-SQLAlchemy==2.3.2 -gunicorn==19.9.0 +Flask +Flask-SQLAlchemy +mysqlclient +gunicorn diff --git a/web.env.example b/web.env.example new file mode 100644 index 0000000..2231790 --- /dev/null +++ b/web.env.example @@ -0,0 +1,12 @@ +SQLALCHEMY_DATABASE_URI=mysql://root:secret@localhost:3306/db +SQLALCHEMY_TRACK_MODIFICATIONS=False + +USERNAME=admin +PASSWORD=secret + +SECRET_KEY=1337 + +UPLOAD_FOLDER=uploads + +GUNICORN_WORKERS=2 +GUNICORN_BIND=0.0.0.0:8080