<p>I've been working on a <code>Kubernetes</code> cluster with microservices written in <code>Flask</code> for some time now and I'm not sure if my current method for containerizing them is correct. </p>

<p>I've been using <a href="https://github.com/tiangolo/uwsgi-nginx-flask-docker" rel="nofollow noreferrer">this</a> image as a base.</p>

<p>But I've been seeing various posts saying that something like that may be a bit overkill.</p>

<p>The problem I have is that whenever I look up an article about using <code>Flask</code> with <code>Kubernetes</code>, they always skip over the details of the actual container and focus on building the cluster, which is something I already have a pretty solid handle on. I guess what I'm wondering is whether there's a better way to build a docker image for a single <code>Flask</code> app because it's hard to find a straight answer.</p>

<p>"better" is entirely relative, but here is the one I use.</p>

<pre><code>FROM python:3.7 AS build

ENV PYTHONFAULTHANDLER=1 \
    PYTHONUNBUFFERED=1 \
    PYTHONHASHSEED=random \
    PIP_NO_CACHE_DIR=off \
    PIP_DISABLE_PIP_VERSION_CHECK=on \
    PIP_DEFAULT_TIMEOUT=100

RUN pip install poetry==1.0.5

WORKDIR /app
COPY poetry.lock pyproject.toml /app/
RUN poetry config virtualenvs.create false &amp;&amp; \
    poetry install --no-dev --no-interaction --no-ansi


FROM gcr.io/distroless/python3-debian10

WORKDIR /app
ENV PYTHONPATH=/usr/local/lib/python3.7/site-packages/
COPY --from=build /usr/local/lib/python3.7/site-packages/ /usr/local/lib/python3.7/site-packages/
COPY . /app

CMD ["-m", "myapp"]
</code></pre>

<p>With that -m entrypoint looking like:</p>

<pre><code>from . import create_app

application = create_app()


def main() -&gt; None:
    import sys
    from twisted import logger  # type: ignore
    from twisted.internet import reactor  # type: ignore
    from twisted.internet.endpoints import TCP4ServerEndpoint  # type: ignore
    from twisted.python import threadpool  # type: ignore
    from twisted.web.server import Site  # type: ignore
    from twisted.web.wsgi import WSGIResource  # type: ignore
    from prometheus_client.twisted import MetricsResource  # type: ignore

    observers = [logger.textFileLogObserver(sys.stdout)]
    logger.globalLogBeginner.beginLoggingTo(observers)
    logger.Logger().info("myapp starting on :8000")

    pool = threadpool.ThreadPool()
    reactor.callWhenRunning(pool.start)
    django_resource = WSGIResource(reactor, pool, application)
    django_site = Site(django_resource)
    django_endpoint = TCP4ServerEndpoint(reactor, 8000)
    django_endpoint.listen(django_site)
    metrics_resource = MetricsResource()
    metrics_site = Site(metrics_resource)
    metrics_endpoint = TCP4ServerEndpoint(reactor, 9000)
    metrics_endpoint.listen(metrics_site)
    reactor.run()
    pool.stop()


if __name__ == "__main__":
    main()
</code></pre>
