0

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.

Mike
  • 3,775
  • 8
  • 39
  • 79

1 Answers1

5

I can tell you where the additional 50MB come from. If you call docker image history hello_app:latest you will see that the chown call creates a layer consuming about 50 MB. Apparently docker can't save the changed owner in a compact way.

Use the --chown flag for COPY instead. E.g.:
COPY --chown=webuser:webuser --from=builder /home/webuser/env/ env/.
This way the files are created with the correct owner and you can remove the RUN chown ….

Marc
  • 436
  • 3
  • 4