I've been working on a Kubernetes
cluster with microservices written in Flask
for some time now and I'm not sure if my current method for containerizing them is correct.
I've been using this image as a base.
But I've been seeing various posts saying that something like that may be a bit overkill.
The problem I have is that whenever I look up an article about using Flask
with Kubernetes
, 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 Flask
app because it's hard to find a straight answer.
I got your point you are thinking you docker image creation method may be wrong.
The main idea while building docker image. The image should have only your dependencies. As you told to find an answer is hard because we don't know your requirement maybe your dockerfile is only way.
I recommend you to this document. I read this document and really my docker images is improved. I think it will help you.
https://drive.google.com/file/d/16t_-DRTohzyVPJy6Cx8a3PxLQ-95CfYK/view
When I checked you dockerfile; I noticed only, I would like to share you;
Line 5th It should not be perform like that. The dockerfile should not be updated frequently and each dependency should be versioned.
I build this image like that.
I write all dependencies to req.txt with version.
req.txt
flask==1.1.1
Dockerfile
+ COPY req.txt .
+ RUN pip install -r req.txt
Also I would like to perform line between 5 and 28 in a bash script.
An Important Information; My manager don't want comment line in a Dockerfile. She wants to understand when she read it. She wants to simple and readable docker file. :) She is a wiser. You should keep simple your dockerfile and it should be understand whitout any comment lines.
"better" is entirely relative, but here is the one I use.
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 && \
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"]
With that -m entrypoint looking like:
from . import create_app
application = create_app()
def main() -> 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()