How do I reduce a python (docker) image size using a multi-stage build?

杀马特。学长 韩版系。学妹 提交于 2020-08-01 05:58:43

问题


I am looking for a way to create multistage builds with python and Dockerfile:

For example, using the following images:

1st image: install all compile time requirements, and install all needed python modules

2nd image: copy all compiled / built packages from first image to the second, without the compilers themselves (gcc, postgers-dev, python-dev etc..)

The final objcetive is to have a smaller image, running python and the python packages that I need.

In short: how can I 'wrap' all the compiled modules (site-packages / external libs) that were created in the first image, and copy them in a 'clean' manner, to the 2nd image.


回答1:


ok so my solution is using wheel, it lets us compile on first image, create wheel files for all dependencies and install them in the second image, without installing the compilers

FROM python:2.7-alpine as base

RUN mkdir /svc
COPY . /svc
WORKDIR /svc

RUN apk add --update \
    postgresql-dev \
    gcc \
    musl-dev \
    linux-headers

RUN pip install wheel && pip wheel . --wheel-dir=/svc/wheels

FROM python:2.7-alpine

COPY --from=base /svc /svc

WORKDIR /svc

RUN pip install --no-index --find-links=/svc/wheels -r requirements.txt

You can see my answer regarding this in the following blog post

https://www.blogfoobar.com/post/2018/02/10/python-and-docker-multistage-build




回答2:


I recommend the approach detailed in this article (section 2). He uses virtualenv so pip install stores all the python code, binaries, etc. under one folder instead of spread out all over the file system. Then it's easy to copy just that one folder to the final "production" image. In summary:

Compile image

  • Activate virtualenv in some path of your choosing.
  • Prepend that path to your docker ENV. This is all virtualenv needs to function for all future docker RUN and CMD action.
  • Install system dev packages and pip install xyz as usual.

Production image

  • Copy the virtualenv folder from the Compile Image.
  • Prepend the virtualenv folder to docker's PATH



回答3:


The docs on this explain exactly how to do this.

https://docs.docker.com/engine/userguide/eng-image/multistage-build/#before-multi-stage-builds

Basically you do exactly what you've said. The magic of multistage build feature though is that you can do this all from one dockerfile.

ie:

FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]  

This builds a go binary, then the next image runs the binary. The first image has all the build tools and the seccond is just a base linux machine that can run a binary.



来源:https://stackoverflow.com/questions/48543834/how-do-i-reduce-a-python-docker-image-size-using-a-multi-stage-build

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!