Рекомендации по работе с Docker для Golang-разработчиков (Multistage Building)

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Старайтесь всегда использовать многоэтапную сборку, для создания более компактных Docker образов. Давайте, рассмотрим на примере, как многоэтапная сборка позволяет значительно уменьшить размер Docker образа. В качестве примера, мы будем использовать простое веб-приложение на Golang:

package main

import (
	"fmt"
	"log"
	"net/http"
)

func main() {
	http.HandleFunc("/", HelloServer)
	fmt.Printf("Starting server at port 8080\n")
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal(err)
	}
}

func HelloServer(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Hello world")
}

Сначала, соберем Docker образ в один этап:

FROM golang:1.16-alpine
RUN mkdir /build
WORKDIR /build
COPY go.mod .
#COPY go.sum .
RUN go mod download
COPY . .
RUN go build -o /main main.go
ENTRYPOINT ["/main"]

На выходе мы получили Docker образ, размер которого 308 MB. Давайте, теперь мы пересоберем тоже самое приложение, но с использованием многоэтапной сборки:

# Этап, на котором выполняется сборка приложения
FROM golang:1.16-alpine as builder
RUN mkdir /build
WORKDIR /build
COPY go.mod .
#COPY go.sum .
RUN go mod download
COPY . .
RUN go build -o /main main.go
# Финальный этап, копируем собранное приложение
FROM alpine:3
COPY --from=builder main /bin/main
ENTRYPOINT ["/bin/main"]

Мы получили Docker образ, размер которого всего 11.8 MB. Неплохо, мы уменьшили образ в более, чем 25 раз. Но, за счет чего нам удалось добиться такого результата?

В первом случае, мы используем сборку в один этап, а следовательно размер финального Docker образа состоит из размера golang:1.16-alpine (302 MB) + размер исходников (0.5 MB) + размер скомпилированного приложения (6.2 MB).

Во, втором случае, мы выполнили компиляцию и сборку приложения, а затем в финальный этап, перенесли уже скомпилированный результат. Таким образом, для создания Docker образа используется лишь один, финальный этап, который состоит из размера alpine:3 (5.59 MB) + размер скомпилированного приложения (6.2 MB).

А можно ли еще уменьшить размер Docker образа?

Можно, но для этого в качестве финального образа, мы должны использовать docker scratch - это пустой образ в докере, размер которого 0 MB.

FROM golang:1.16-alpine as builder
RUN mkdir /build
WORKDIR /build
COPY go.mod .
#COPY go.sum .
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /main main.go
FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder main /bin/main
ENTRYPOINT ["/bin/main"]

В итоге наш контейнер занимает всего лишь 6.34 MB (размер скомпилированного приложения). На что стоит обратить внимание?

Первое, нам пришлось изменить команду сборки, а именно добавить дополнительные флаги:

CGO_ENABLED - мы отключаем CGO, таким образом мы получаем скомпилированное Go-приложение вместе с статически связанными C-библиотеками, поэтому наш бинарник будет работать без каких-либо внешних зависимостей. Более подробно, можно почитать тут.

GOOS - мы указываем Linux в качестве ОС.

Второе, на что стоит обратить внимание - это SSL. Т.к. scratch пуст, то там просто нету рутовых SSL сертификатов, а значит их нужно добавить вручную.

Источник: https://habr.com/ru/post/647255/


Интересные статьи

Интересные статьи

Выгрузка пользователей из 1C ЗУП в Битрикс24 или правдивая история о том как настроить интеграцию 1С-Битрикс24 с ЗУП без 1С-ника.В жизни так бывает, причём бывает чаще чем хотелось бы, хоть в целом и ...
Пришел ко мне коллега и спросил: "Как проигнорировать .dockerignore при сборке docker-образа?" После совместных поисков и проверок, было найдено простое решение, состоящее в сл...
Что нас побудило создать курс по Docker — хотя на рынке десятки предложений по этой теме, и практически каждая IT-школа отметилась в этом направлении? Побудили нас студенты «Вечерней...
В 1С Битрикс есть специальные сущности под названием “Информационные блоки, сокращенно (инфоблоки)“, я думаю каждый с ними знаком, но не каждый понимает, что это такое и для чего они нужны
Фираза недавно назначили директором компании стоимостью в миллиард долларов, где он работал на различных должностях в течение девяти лет. Два года он добивался этой позиции, но, получив её, Ф...