Flask in a container: Difference between revisions

From XPUB & Lens-Based wiki
(Create initial page)
 
(Add image with graph)
Line 8: Line 8:


The de-facto standard to deal with container is [https://docker.com Docker], and it is nearly ubiquitous. Nevertheless, this guide uses [https://podman.io Podman], a drop-in replacement that offers some benefits. This means that at any point of the article and also more in general whenever there is a <code>docker</code> command, it can be replaced with <code>podman</code>, and it should work the same. The reasons behind this choice are beyond the scope of this little guide, but I gathered my notes and thoughts about Podman [https://tommi.space/podman/ in the dedicated page].
The de-facto standard to deal with container is [https://docker.com Docker], and it is nearly ubiquitous. Nevertheless, this guide uses [https://podman.io Podman], a drop-in replacement that offers some benefits. This means that at any point of the article and also more in general whenever there is a <code>docker</code> command, it can be replaced with <code>podman</code>, and it should work the same. The reasons behind this choice are beyond the scope of this little guide, but I gathered my notes and thoughts about Podman [https://tommi.space/podman/ in the dedicated page].
[[File:Flask container graph.png|thumb]]


== Make a Dockerfile ==
== Make a Dockerfile ==

Revision as of 12:18, 14 April 2026

Running Flask in a container is tremendously useful to move the same container anywhere and replicate the same exact environment on any device or operating system, without having to modify anything.

Why a container?

A container can be seen a bit like a box with compartments inside it. Running an application (in this case, Flask) on different devices with different operating systems would be like taking different boxes and try to recreate the same compartments inside them, or trying to fit them even if the size of the containing box is not identical. The software equivalent of this would be to install all the dependencies and the required software independently on each device, to try to reach the same result. Using a container would be like taking the original box and move it around, without having to change or adapt its internal structure. Creating a container means that from one device we pack everything that is needed, and then we can ship it (deploy it) anywhere.

Podman

The de-facto standard to deal with container is Docker, and it is nearly ubiquitous. Nevertheless, this guide uses Podman, a drop-in replacement that offers some benefits. This means that at any point of the article and also more in general whenever there is a docker command, it can be replaced with podman, and it should work the same. The reasons behind this choice are beyond the scope of this little guide, but I gathered my notes and thoughts about Podman in the dedicated page.

Flask container graph.png

Make a Dockerfile

The first step is to make a Dockerfile, giving Podman/Docker the instructions to pack the box, which means taking all the software and dependencies necessary to run Flask and place them inside the container.

I have not learned how a Dockerfile actually works (yet). I just made a patchwork of the different Dockerfile examples I found—referenced below.

Here is the essential Dockerfile to run an instance of Flask, block by block.

Download (“pull”) the required images to run the container. In this case, we are pulling Python and uv, and we are telling Podman to move the executable binaries to specific folders in the container.

FROM python:3.12-slim-trixie
COPY --from=ghcr.io/astral-sh/uv:0.11 /uv /uvx /bin/

Assuming that all the files required to run Flask are in ./app, we mat them all to /app, inside the container.

# Copy over project files
COPY app/ /app

Tell the container that we are referring to /app (the directory we just created) whenever we run or do something. In other terms, it is our the working directory of the container.

WORKDIR /app

Tell uv to install the required dependencies, listed in pyproject.toml

RUN uv sync -U

Flask runs through a specific port. We have to tell the container to expose that port, to make available. This does not mean the port is directly exposed to the outside world, it is just “handed over” and made available to Podman, that can be instructed to actually serve that port (see below).

EXPOSE 5000

I couldn’t find a nicer way to do it, but basically this is the final command to be run when the container should be running

CMD ["uv", "run", "flask", "--app", "main", "run", "--debug", "--host", "0.0.0.0", "--port", "5000"]

this is the same as running the following in the command line, which is exactly what we are telling the container to do as the last action of the Dockerfile.

uv run flask --app main run --debug --host '0.0.0.0' --port '5000'

The complete Dockerfile is here, in the flask-intro repository.

Build the container

Once the instructions are compiled, the container has to be built. It’s possible to specify which Dockerfile to read, using -f. By default, the reference Dockerfile is Dockerfile in the present working directory.

podman build -t flask-intro:latest # -f Dockerfile

Run the container

podman run --rm --name flask-intro -p 5000:5000 flask-intro

Production vs development mode

\#TODO))

Create Quadlet

\#TODO))

Serve with Caddy

\#TODO))

Resources