DevGang
Авторизоваться

Оптимизация образов Docker с помощью многоэтапных сборок и бездистрибутивного подхода

Когда мы перевели наше приложение с Node.js (Express) на Go, нам удалось уменьшить размер образа Docker с 2,8 ГБ до 400 МБ, что изначально нас устраивало. Однако, стремясь к более эффективному использованию ресурсов и более быстрому развертыванию, мы поняли, что все еще есть возможности для дальнейшего уменьшения размера изображения, поэтому мы решили попробовать новый подход.

Возможно, это знакомая территория для инженеров с опытом работы в DevOps, но для новичков я поделюсь улучшениями, которые мы внесли.

Исходный Dockerfile

Наш исходный файл Dockerfile использовал базовый образ golang:1.21.0 и включал шаги по загрузке модулей Go, созданию приложения и его выполнению. Однако этот подход означал, что все файлы, необходимые для среды разработки, были включены в образ, что приводило к увеличению конечного размера образа.

# Base the image on the official Go image
FROM golang:1.21.0

# Create the application directory
WORKDIR /app

# Enable Go modules
ENV GO111MODULE=on

# Copy and download dependencies
COPY go.mod .
COPY go.sum .
RUN go mod download

# Copy the application source
COPY . .

# Build the application
RUN go build -o main .

# Expose the port
EXPOSE 8081

# Execute the application command
CMD ["./main"]

Улучшенный Dockerfile

В улучшенном файле Dockerfile мы внедрили многоступенчатые сборки. Многоступенчатые сборки определяют несколько этапов сборки в одном файле Dockerfile, и в конечный образ включаются только необходимые файлы. На первом этапе создается приложение, а на следующем этапе только созданный исполняемый файл копируется в облегченный образ alpine. Это значительно уменьшает конечный размер изображения за счет включения только необходимых файлов.

# Base the image on the official Go image
FROM golang:1.21.0-alpine as builder

# Create the application directory
WORKDIR /app

# Enable Go modules
ENV GO111MODULE=on

# Copy and download dependencies
COPY go.mod .
COPY go.sum .
RUN go mod download

# Copy the application source
COPY . .

# Build the application
RUN go build -o main .

# Execution stage
FROM alpine:3.19

WORKDIR /root/

# Copy the built binary
COPY --from=builder /app/main .

# Expose the port
EXPOSE 8081

# Execute the application command
CMD ["./main"]

Сравнение результатов

При использовании оригинального Dockerfile размер образа составлял около 400 МБ. Однако после применения многоэтапной сборки размер образа сократился всего до 10 МБ. Без многоэтапной сборки, но с использованием golang:1.21.0-alpine в качестве базового образа размер составил около 160 МБ.

Об образах без дистрибутива

Для этого проекта мы выбрали образ Alpine с оболочкой для целей отладки, но мы также рассматривали возможность использования образов Distroless от Google. Образы без дистрибутива известны как очень легкие и безопасные среды, содержащие только минимальное количество необходимых файлов, без удаленных оболочек и ненужных пакетов.

При использовании образов Distroless приложениям, написанным на Go, требуются статически связанные двоичные файлы, которые не зависят от внешних библиотек C. Это связано с тем, что Distroless предоставляет минимальную среду без внешних библиотек и оболочек. Поэтому необходимо установить CGO_ENABLED=0, чтобы отключить CGO (интерфейс между языками C и Go), создав автономный двоичный файл, включающий все зависимости.

Dockerfile с использованием Distroless будет выглядеть так:

# Build stage
FROM golang:1.21.0 as builder

# Set the application directory
WORKDIR /app

# Enable Go modules
ENV GO111MODULE=on

# Copy and download dependencies
COPY go.mod .
COPY go.sum .
RUN go mod download

# Copy the application source
COPY . .

# Build the application
RUN CGO_ENABLED=0 go build -o main .

# Execution stage
FROM gcr.io/distroless/base-debian10

# Copy the built binary
COPY --from=builder /app/main /

# Execute the application
CMD ["/main"]

Заключение

Подводя итог, наш опыт оптимизации образов Docker для приложения Go преподнес нам ценные уроки об эффективности и безопасности в контейнерных средах. Внедрив многоэтапные сборки, мы смогли значительно уменьшить размер образа, тем самым повысив скорость развертывания и минимизировав использование ресурсов. Такой подход не только способствует более упорядоченному и экономически эффективному процессу развертывания, но также хорошо согласуется с принципами современной практики DevOps.

Более того, изучение таких вариантов, как образы Distroless, открыло нам глаза на важность безопасности в средах Docker. Хотя мы выбрали Alpine из-за нашей срочной потребности в оболочке для отладки, Distroless представляет собой привлекательную альтернативу для производственных сред, где безопасность и минимализм имеют первостепенное значение.

Это мероприятие является свидетельством непрерывного развития в области разработки и внедрения программного обеспечения. Это подчеркивает важность того, чтобы оставаться адаптируемыми и всегда искать лучшие и более эффективные решения. По мере развития технологий развиваются и инструменты и методы, позволяющие нам создавать и развертывать приложения, которые являются не только мощными, но также эффективными и безопасными.

Как для опытных профессионалов DevOps, так и для новичков эти результаты подчеркивают важность оптимизации образов Docker и влияние, которое она может оказать на общий жизненный цикл поставки программного обеспечения. По мере нашего продвижения вперед становится ясно, что внедрение таких оптимизаций будет иметь ключевое значение для повышения операционной эффективности и предоставления программного обеспечения в темпах и масштабах, требуемых современной цифровой средой.

Источник:

#Golang #Docker
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу