Sign inSign up

romanmc72/flask

By romanmc72

•Updated about 6 years ago

Image
0

393

romanmc72/flask repository overview

⁠Description

This image is created to run python's flask web framework on docker. The actual flask application is not built in here but is expected to be mounted at runtime. This docker image runs expecting a PostgreSQL backend, and some sort of mail server as variables but if your flask application does not use postgres, or uses some other database technology then you will have to write your own entrypoint script. The default entrypoint script waits for the database to be available before launching flask. If your flask application requires other env variable values then you can set them on your own. If you use MySQL or some other database then that'll be up to you to figure out how to make it work.

⁠Using this

Currently I use this in conjunction with the postgres:12.0-alpine image. See that repo and its documentation for how to get started on that technology. Here is an example compose file using my image here:

version: "3.7"

services:

  flask:
    image: romanmc72/flask:latest
    ports:
      - 5000:5000
    # Just using this because of the compose definition below. In reality you probably
    # do not want flask running as the root user on your database
    env:
      - DATABASE_URI: "postgresql+psycopg2://username:password@db:5432/db"
    # mounting the local instance of flask to this running container
    volumes:
      - ../../flask_app:/usr/src/app
    depends_on: 
      - db

  db:
    image: postgres:12.0-alpine
    restart: always
    ports:
      - 5432:5432
    env:
      - POSTGRES_USER: "username"
      - POSTGRES_PASSWORD: "password"
      - POSTGRES_DB: "db" 

⁠Disclaimer

This is entirely a personal project so I make zero guarantees of any kind that this will work nor will I offer support on this. If you like it great, if not build your own ;)

⁠Dockerfile

This is the actual Dockerfile

FROM python:3.8.0-alpine
# For this to run, you will need to override some env variables and do a volume mount to the flask application.
# volumes:
#     - /location/on/disk/where/flask_app:/usr/src/app
# And this program does expect your application to be called `flask_app.py`

# In order to use postgres, you need the psycopg2 from pip,
# but in order to install that you need all of this junk
RUN apk update && \
    apk add --virtual build-deps gcc python-dev musl-dev && \
    apk add postgresql-dev

# Nobody likes you when you run under root
RUN adduser --disabled-password flask_user flask_user 
USER flask_user

# Set the working directory
WORKDIR /usr/src/app

# All the libraries for flask to run
COPY requirements.txt /tmp/requirements.txt
RUN pip install --user --upgrade pip && \
    pip install --user -r /tmp/requirements.txt

# Nobody wants to see your .pyc files
ENV PYTHONDONTWRITEBYTECODE 1

# Unbuffer the stdout and stderr streams
ENV PYTHONUNBUFFERED 1

# This is required for the pip installed requirements to find
# the `flask` executable when the entrypoint is run
ENV PATH=/home/flask_user/.local/bin:$PATH

# Required for flask to run
ENV FLASK_APP=/usr/src/app/flask_app.py

# Override these otherwise it will not work
ENV DATABASE_URI: "postgresql+psycopg2://username:password@server_name:port/db"
ENV MAIL_SERVER: mail.server.name
ENV MAIL_PORT: 123
ENV MAIL_USE_TLS: 1
ENV MAIL_USERNAME: username
ENV MAIL_PASSWORD: password

COPY wait_for_postgres.py /home/flask_user/wait_for_postgres.py
COPY entrypoint.sh /home/flask_user/entrypoint.sh

ENTRYPOINT [ "/home/flask_user/entrypoint.sh" ]

Here is the entrypoint script

#!/usr/bin/env sh

set -euo pipefail

# The depends_on clause in the docker-compose file is only until
# the container starts and has nothing to do with thie timing of
# the underlying applications that the container uses. So the
# PostgreSQL container may be on but it cannot accept connections yet.
python3 /home/flask_user/wait_for_postgres.py

flask db init || flask db migrate || echo 'init and migrate both failed, proceeding anyway'
flask db upgrade || echo 'database already up to date'

# Running this so that the ports can bind from localhost:5000 to the container's 0.0.0.0
# otherwise the lines in the main application do not work where it specifies the host as 0.0.0.0
# And nothing is visible.
python3 $FLASK_APP

Here is the wait for postgres script

#!/usr/bin/env python3
"""
PostgreSQL must be ready to receive connections before flask can start issuing commands to it.
This application loops until that is that case then exits.

Borrowed from stack overflow, but I lost the link to it.
Thank you to all of the brave pioneers on that site who light the way for others.
"""
import os
import time

from sqlalchemy import exc
from sqlalchemy import create_engine


NGN = os.getenv('DATABASE_URI', 'postgresql+psycopg2://flask:not_the_password@webserver_db_1:5432/flask_db')

while 1:
    try:
        e = create_engine(NGN)
        e.execute('select 1')
    except exc.OperationalError:
        print('Waiting for database...')
        time.sleep(1)
    else:
        break

print('Connected!')

and here is the requirements file

alembic==1.3.3
blinker==1.4
Click==7.0
Flask==1.1.1
Flask-Login==0.4.1
Flask-Mail==0.9.1
Flask-Migrate==2.5.2
Flask-SQLAlchemy==2.4.1
Flask-WTF==0.14.2
gunicorn==20.0.4
itsdangerous==1.1.0
Jinja2==2.10.3
Mako==1.1.1
MarkupSafe==1.1.1
psycopg2==2.8.4
PyJWT==1.7.1
python-dateutil==2.8.1
python-editor==1.0.4
six==1.14.0
SQLAlchemy==1.3.13
Werkzeug==0.16.0
WTForms==2.2.1

Have fun!

Tag summary

Content type

Image

Digest

Size

190.8 MB

Last updated

about 6 years ago

docker pull romanmc72/flask:0.0.4