Создание минимального Docker образа для Go приложений

29 июня 2020 г. Docker Compilation Upx Ldflags


Создание минимального Docker образа для Go приложений

Давайте обсудим, как создать минимальный Docker образ для Go программы.

Docker поддерживается многими операционными системами — Linux, Unix, Windows и macOS. Docker контейнеры также поддерживаются многими популярными хостинг-платформами — Microsoft Azure, Amazon Web Services, Digital Ocean и другими.

Сборка образа и Dockerfile

Сборка Docker образа выполняется с помощью команды docker build, а Dockerfile необходим для предоставления инструкций по сборке.

Давайте посмотрим на следующий Dockerfile:

FROM rhaps1071/golang-1.14-alpine-git AS build
WORKDIR /build
COPY . .
RUN CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -ldflags "-s -w -extldflags '-static'" -o ./app
RUN apk add upx
RUN upx ./app

FROM scratch
COPY --from=build /build/app /app

ENTRYPOINT ["/app"]

Поскольку мы используем Go модули, нам не нужно помещать исходный код в определенную папку или загружать зависимости вручную — это делается самой командой go build.

Теперь давайте обсудим все особенности этого Dockerfile.

Двухэтапная сборка

Размер Docker образа важен, потому что образ будет загружаться и скачиваться во время сборки и развертывания. Чем больше размер образа, тем больше времени вы потратите на передачу по сети.

На первом этапе (“build”) в Dockerfile я начинаю сборку с образа rhaps1071/golang-1.14-alpine-git, который представляет собой golang:1.14-alpine с установленным git. Alpine — это самый маленький Linux образ, доступный в настоящее время. Размер его образа составляет около 3MB.

На втором этапе я использую scratch просто для размещения бинарного файла там. scratch — это готовый Docker образ с нулевым размером. Это означает, что результирующий размер образа равен размеру бинарного файла.

Размер бинарного файла

Мы можем уменьшить размер бинарного файла, используя два подхода:

  • Флаги линковки (ldflags);
  • Сжатие бинарного файла после компиляции;

Флаги -s -w удаляют отладочную информацию из бинарного файла. В моем случае размер был уменьшен с 15MB до 11MB благодаря этим флагам.

-extldflags '-static' используется для статической линковки бинарного файла даже при включенном CGO. Динамическая линковка делает наш бинарный файл зависимым от внешних библиотек (файлы .so в Linux). Зависимости внешних библиотек можно проверить с помощью команды ldd для бинарного файла. В scratch и Alpine у нас не установлены эти библиотеки. В этом случае нам приходится использовать статическую линковку — все библиотеки будут скомпилированы в наш бинарный файл программы.

Я также использовал инструмент upx для сжатия бинарного файла. Размер был уменьшен с 11MB до 4.1MB.

Исходный код этого примера можно найти в репозитории GitHub.

Tags:

Похожие статьи

1 Jul 2020

Удалённая отладка с Delve

Ранее мы обсуждали локальную отладку с помощью IDE GoLand. Теперь мы обсудим, как удалённо отлаживать программу, работающую внутри Docker-контейнера, используя Visual Studio Code и GoLand IDE.

Read More → Docker Debugger Delve Vscode Goland
1 Jul 2020

Деплой docker swarm из Gitlab CI

Деплой docker swarm из Gitlab CI

Ранее мы рассматривали деплой бинарного файла программы через SSH на сервер

Сейчас мы рассмотрим как реализовать деплой Docker контейнера из Gitlab CI.

Read More → Docker Deploy Gitlab Ci/Cd
30 Jun 2020

Утилита и библиотека net-wait-go

Утилита и библиотека net-wait-go

Утилита и пакет Go для ожидания открытия портов (TCP, UDP).

Read More → Tcp Udp Docker
8 May 2020

Компиляция и деплой через SSH в GitLab CI

Компиляция и деплой через SSH в GitLab CI

Давайте рассмотрим, как работает компиляция Go и как использовать GitLab CI для этого.

Read More → Gitlab Compilation Deploy Ssh Modules Vendor Ci/Cd