В этом руководстве я продемонстрирую, как создавать тонкие образы docker с помощью многоступенчатых сборок docker, где вы можете сэкономить до 800 МБ дискового пространства на образ.
Первоначально опубликовано на containers.fan
О
Мы будем использовать многоступенчатые сборки docker из образа alpine в качестве нашего образа сборки, чтобы получить зависимости, создать двоичный файл go и использовать наш скретч-образ для размещения встроенного двоичного файла на нашем целевом изображении, чтобы получить небольшие изображения docker.
Почему размер имеет значение
Итак, давайте предположим, что у вас есть оркестратор, такой как ECS, Swarm или Kubernetes, со 100 узлами за группой автоматического масштабирования, где количество узлов вашего кластера равно 10 при низком трафике и 100 узлам при большом трафике.
По мере масштабирования наш сервис может масштабироваться с 10 реплик до 500 реплик, и давайте предположим, что размер нашего образа контейнера составляет 800 МБ, когда новый узел присоединяется к кластеру, образ контейнера не будет находиться в кэше, поэтому демону docker необходимо загрузить этот образ из реестра docker. Итак, допустим, 100 узлов присоединяются к кластеру, и наш сервис масштабируется до 100 реплик, это означает, что каждому узлу необходимо загрузить 800 МБ из реестра docker, что составляет около 80 ГБ входящей пропускной способности сети в кластер.
Таким образом, когда мы используем многоступенчатые сборки и в данном случае используем Go, мы можем уменьшить наш образ контейнера до менее чем 3 МБ, если мы выполним те же вычисления, то пропускная способность составит чуть менее 300 МБ, и если новый узел присоединяется к кластеру, а образ контейнера отсутствует, потребуется примерно секунда или две на загрузку и запуск контейнера (в зависимости от скорости Интернета), и вы, очевидно, экономите место на диске.
Перейти к приложению
Мы будем использовать библиотеку, которая генерирует случайные данные из go-random data в нашем приложении, app.go
:
package main import ( "fmt" "github.com/Pallinder/go-randomdata" ) func main() { profile := randomdata.GenerateProfile(randomdata.Male | randomdata.Female | randomdata.RandomGender) fmt.Printf("The new profile's username is: %s and password (md5): %s\n", profile.Login.Username, profile.Login.Md5) }
Одноступенчатая Сборка Docker
В этом примере мы будем использовать образ golang для получения зависимостей и сборки приложения в одном образе, нашем Dockerfile.single_stage
:
FROM golang:latest as builder RUN mkdir -p /go/src/github.com/ruanbekker WORKDIR /go/src/github.com/ruanbekker RUN useradd -u 10001 app COPY . . ENV GO111MODULE=auto RUN go get RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main . USER app CMD ["/go/src/github.com/ruanbekker/main"]
Создание имиджа:
docker build -f Dockerfile.single_stage -t goapp:singlestage .
Многоступенчатая Сборка Docker
Наш многоступенчатый состоит из образа сборки, где мы будем использовать образ golang для извлечения наших зависимостей и сборки нашего приложения, затем мы используем образ scratch в качестве цели для копирования скомпилированного двоичного файла и запуска контейнера из slim-образа, нашего Dockerfile.multi_stage
:
FROM golang:latest as builder RUN mkdir -p /go/src/github.com/ruanbekker WORKDIR /go/src/github.com/ruanbekker RUN useradd -u 10001 app COPY . . ENV GO111MODULE=auto RUN go get RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main . FROM scratch COPY --from=builder /go/src/github.com/ruanbekker/main /main COPY --from=builder /etc/passwd /etc/passwd USER app CMD ["/main"]
Создание имиджа:
docker build -f Dockerfile.multi_stage -t goapp:multistage .
Сравнение различий в размерах
Когда мы сравниваем различия в размерах наших изображений docker между обычной сборкой и многоступенчатой сборкой, мы видим огромную разницу:
docker images | head -3 REPOSITORY TAG IMAGE ID CREATED SIZE goapp singlestage 0d0c1f4c98a2 54 seconds ago 896MB goapp multistage d74ac27a39c8 2 hours ago 2.75MB
И просто чтобы показать, что оба контейнера запускаются из встроенных образов docker, наша единая сборка:
docker run -it goapp:singlestage The new profile's username is: Maregrass and password (md5): 56da7705b7648a38f539b043e6a494be
И наша многоступенчатая сборка:
docker run -it goapp:multistage The new profile's username is: Shirtplaid and password (md5): 7d8606ee86f2da3ed12c595ab617bf4e
Спасибо
Если вам понравился этот контент, пожалуйста, обязательно поделитесь им или зайдите поздороваться на мой сайт или в твиттер:
Оригинал: “https://dev.to/ruanbekker/why-you-should-use-multi-stage-docker-builds-571e”