How to build a Python app with PostgreSQL
I’m currently setting up a Flask app with PostgreSQL and Docker.
Like most examples you’ll find on the internet, the course I’m following uses Alpine Linux as a base image. Alpine’s selling point is the small image size.
But Alpine uses a different C library, musl
, instead of glibc
.
That’s one of the reasons why the website Pythonspeed recommends Debian Buster as the base image for Python (as of 2019).
Let’s say we have a requirements.txt
file with the following packages. We want to get Flask working with a PostgreSQL database.
Flask==1.1.1
Flask-RESTful==0.3.7
Flask-SQLAlchemy==2.4.0
psycopg2-binary==2.8.3
Alpine Linux Docker
Let’s create a Dockerfile
for an Alpine-based image.
## base image
FROM python:3.7.4-alpine
## install dependencies
RUN apk update && \
apk add --virtual build-deps gcc python-dev musl-dev && \
apk add postgresql-dev && \
apk add netcat-openbsd
## set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
## set working directory
WORKDIR /usr/src/app
## add user
RUN adduser -D user
RUN chown -R user:user /usr/src/app && chmod -R 755 /usr/src/app
## add and install requirements
RUN pip install --upgrade pip
COPY ./requirements.txt /usr/src/app/requirements.txt
RUN pip install -r requirements.txt
## add entrypoint.sh
COPY ./entrypoint.sh /usr/src/app/entrypoint.sh
RUN chmod +x /usr/src/app/entrypoint.sh
## switch to non-root user
USER user
## add app
COPY . /usr/src/app
## run server
CMD python manage.py run -h 0.0.0.0
We have to install several libraries (musl-dev
, etc.) with apk add
. Those libraries are required for installing psypcopg2-binary
with pip install
later.netcat-openbsd
is not necessary for PostgreSQL, but I need it in my app for my entrypoint.sh
script.
You should probably use a multi-stage build to minimize the final image.
Debian Buster Slim Docker
Now, the same Dockerfile
for Debian Buster Slim:
## base image
FROM python:3.7.5-slim-buster
## install dependencies
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y netcat-openbsd gcc && \
apt-get clean
## set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
## set working directory
WORKDIR /usr/src/app
## add user
RUN addgroup --system user && adduser --system --no-create-home --group user
RUN chown -R user:user /usr/src/app && chmod -R 755 /usr/src/app
## add and install requirements
RUN pip install --upgrade pip
COPY ./requirements.txt /usr/src/app/requirements.txt
RUN pip install -r requirements.txt
## add entrypoint.sh
COPY ./entrypoint.sh /usr/src/app/entrypoint.sh
RUN chmod +x /usr/src/app/entrypoint.sh
## switch to non-root user
USER user
## add app
COPY . /usr/src/app
## run server
CMD python manage.py run -h 0.0.0.0
We have to install gcc
to get pip install
working with psypcopg2-binary
. (Consider using multi-stage builds to optimize speed and efficiency.)