I am trying to create small docker images with grpc services in Python. To get an idea of the size, I have built a basic hello-world Python grpc service. In order to keep it "small" I have used a multi-stage build, where I start from a python:3.7-alpine and then
1) create a virtualenv for the final python installation
2) add necessary building packages for grpc and protobuf
3) copy the virtualenv to the base installation
4) copy the app files
The docker file is as follows:
FROM python:3.7-alpine as base
FROM base as builder
RUN adduser -D webuser
WORKDIR /home/webuser
RUN apk add --update \
gcc \
g++ \
make \
musl-dev \
python3-dev \
libc6-compat \
&& rm -rf /var/cache/apk/*
# create a virtual env
RUN python -m venv env
# install all requirements
RUN env/bin/pip install protobuf grpcio
FROM base
RUN adduser -D webuser
WORKDIR /home/webuser
COPY --from=builder /home/webuser/env/ env/
# copy the app files
COPY hello/gen-py/ ./
COPY hello/hello.py ./
COPY boot.sh ./
# make webuser the owner of the main folder
RUN chown -R webuser:webuser ./
# activate webuser
USER webuser
# boot.sh is the executable script that basically runs python
# from the env with the grpc server hello.py
RUN chmod +x boot.sh
EXPOSE 50051
ENTRYPOINT ["./boot.sh"]
In terms of sizes I have:
python:3.7-alpine 87MB
"builder" 396MB
hello_app:latest 188MB
That is still a very large hello world app. I have built a similar one in C++ which is only 12.4MB. I don't understand a few things in terms of size
My env comes to 51.1 MB, the base python to 93.5MB (based on du -sh in / on the python:3.7-alpine. It is not clear to me why this is larger than the 87MB reported in docker image ls). In total that is 144.6MB, but still it is reported as 188MB.
My main question: How can I create Python GRPC services with as little overhead as possible? Other questions: Can anyone explain the docker sizes? Why does docker report + 100MB to the base image when only a 50MB virtual env is added.