Как уменьшить размер изображения Python (Docker) с помощью многоэтапной сборки?

Я ищу способ создания многоступенчатых сборок с помощью Python и Dockerfile:

Например, используя следующие изображения:

1-й образ: установите все требования времени компиляции и установите все необходимые модули Python

2-е изображение: скопировать все скомпилированные/собранные пакеты из первого изображения во второе без самих компиляторов (gcc, postgers-dev, python-dev и т.д.)

Последнее, что нужно сделать, - это иметь уменьшенное изображение, на котором запущен python и пакеты python, которые мне нужны.

Вкратце: как мне "обернуть" все скомпилированные модули (пакеты сайтов/внешние библиотеки), созданные в первом образе, и скопировать их "чистым" способом, к 2-му изображению.

Ответ 1

Итак, мое решение использует колесо, оно позволяет нам скомпилировать первый образ, создать файлы колес для всех зависимостей и установить их во втором образе, без установки компиляторов.

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

Вы можете увидеть мой ответ на этот счет в следующем сообщении в блоге

https://galnevis.wixsite.com/website/single-post/2018/02/10/Python-and-Docker-multistage-build

Ответ 2

Надеюсь, что следующие примеры помогут

FROM yourbaseimage as builder

RUN echo install dependencies etc. \
 && echo build

FROM yoursmallbaseimage

RUN mkdir -p /bin/

COPY --from=builder /bin/binary /bin/binary

#[...]

ENTRYPOINT ["/bin/binary"]

вы также можете деформировать их в первом изображении здания и извлечь изображение на изображении меньшего размера. или создать официальный пакет, например deb, rpm с минимальным количеством файлов. возможно, вам нужен только базовый python и venv, которые вы можете передать как tar и т.д.

легче найти информацию, чтобы сделать чистый пакет для вашей задачи - так что вы можете Google, что лучше для вашего проекта и, возможно, установите пакет

Ответ 3

Документы об этом объясняют, как это сделать.

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

В основном вы делаете то, что вы сказали. Магия многострочной функции сборки состоит в том, что вы можете сделать все это из одного файла докеров.

т

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"]  

Это создает двоичный файл go, затем следующее изображение запускает двоичный файл. На первом изображении есть все инструменты построения, а seccond - это только базовая Linux-машина, которая может запускать двоичный файл.