This content originally appeared on DEV Community and was authored by Nickolena
There's more than one way to skin a cat, but this pattern makes my heart flutter.
Containerize a Python app
The asgi.py
in our app directory
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def hello():
return "World"
Dockerfile
FROM python:3.7-buster as base
ENV SHELL=/bin/bash \
USER=python \
UID=10001
RUN set -eux; adduser \
--disabled-password \
--gecos "" \
--home "/var/lib/python3" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
"${USER}"
RUN mkdir -p "/var/lib/python3" && chown -R "${USER}" /var/lib/python3
FROM base as build-local
USER ${USER}
RUN python -m pip install \
--user \
'uvicorn[standard]' \
'fastapi' \
'wheel'
FROM base
COPY --from=build-local --chown=${USER} /var/lib/python3/.local /var/lib/python3/.local
ENV PATH=$PATH:/var/lib/python3/.local/bin
USER root
ENTRYPOINT ["docker-entrypoint.sh"]
COPY docker-entrypoint.sh /usr/bin/docker-entrypoint.sh
USER ${USER}
WORKDIR /usr/lib/python
COPY ./app ./app
CMD ["app.asgi:app"]
Entrypoint
#!/bin/bash -e
# If the CMD has not changed process it as a pure Python implementation
if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ]; then
set -- uvicorn "$@" --host 0.0.0.0 --http h11 --loop asyncio
fi
echo
echo "Running $@"
echo
exec "$@"
Multi Stage Build
This Dockerfile is separated in a few stages to organized by the function of its build step. The multi-stage build strips our application of unnecessary files.
The first stage is bootstraps our required instructions that the remaining layers share. The user lets us install requirements outside of the root user.
- `--disable-password` prevents prompt for password
- `--home /var/lib/python3` sets the home dir to a well-defined location
- `--no-create-home` instruction to handle that in the Dockerfile
RUN mkdir -p "/var/lib/python3" && chown -R "${USER}" /var/lib/python3
The second stage brings in external requirements.
The last stage is the application where everything is tied together. Here the requirements are copied and the application itself is added in the app
directory owned by the python user.
References
- https://www.docker.com/blog/containerized-python-development-part-1/
- https://stackoverflow.com/a/55757473/12429735
- https://github.com/nodejs/docker-node/blob/master/docker-entrypoint.sh
This content originally appeared on DEV Community and was authored by Nickolena
Nickolena | Sciencx (2021-02-24T16:54:48+00:00) My favorite way to write a Dockerfile for a Python app. Retrieved from https://www.scien.cx/2021/02/24/my-favorite-way-to-write-a-dockerfile-for-a-python-app/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.