Почему Dockerfile больше не нужен для создания контейнера в Go

Интегрируя, адаптируя и обучая новых инженеров в FlowUp, я пришел к выводу: на формирование глубокого понимания того, как работают Dockerfiles, уходит слишком много времени. И несмотря на то, что для всех своих проектов мы всегда поддерживали (считая это единственной лучшей практикой) Dockerfile, вдруг стало очевидно, что от него нужно по возможности избавиться.

Да, мы продолжаем использовать Dockerfiles в отдельных случаях. Мне лишь хотелось показать вам, что для развертывания чего-либо в облачных средах (Kubernetes, Cloud Run или других контейнерных средах) глубокого понимания не требуется.

🐋 Что делает Dockerfiles лишними?

Есть несколько проектов, предоставляющих стандартные способы создания контейнеров из языков или языковых фреймворков. И при этом знать, что происходит внутри, вовсе не обязательно. Достаточно знать стандартный способ использования языка или фреймворка и применять его. Итак, вот эти проекты:

  • ko, разработанный и поддерживаемый компанией Google. Этот проект позволяет создавать и с легкостью развертывать образы контейнера в средах Kubernetes.
  • Проект Buildpacks, который сейчас находится в инкубаторе CNCF. И есть несколько реализаций для Go, например heroku-buildpack-go или GoogleCloudPlatform/buildpacks.

🔧 Используем Buildpacks

А точнее, Google Cloud Buildpacks. Первым делом нужно установить утилиту pack, которая потом задействует buildpacks (пакеты сборки), совместимые со стандартом.

В случае если вы пользователь Homebrew, устанавливаете так:

brew install buildpacks/tap/pack

А для пользователей Arch Linux, не знакомых с Homebrew, установка доступна одним из следующих двух вариантов:

pack-cli
pack-cli-bin

Если ничто из предложенного вам не подходит, перейдите на страницу установки Pack. Есть еще очень много вариантов установки.

📦 Создание приложения на Go

А теперь переходим к самому интересному  —  созданию приложения. Если вы используете модули Go (наверняка это так), buildpack будет искать модуль в каталоге, загружать зависимости и начинать создавать приложение. А кроме того, он создает минимальный образ с корневыми сертификатами.

pack build <app-name> --builder gcr.io/buildpacks/builder:v1

Полученный контейнер будет иметь название <app-name>, указанное вами в приведенной выше команде. Запускается он так же, как и любой другой образ Docker.

А что если в одном репозитории/каталоге несколько целей?

В этом случае передаем переменную окружения GOOGLE_BUILDABLE в главную цель, где и будет создаваться приложение. Если этого не сделать (а использовать источник с несколькими целями), сборка прекратится и появится сообщение о наличии нескольких источников для ее создания.

pack build
  --env GOOGLE_BUILDABLE=./cmd/service
  --builder gcr.io/buildpacks/builder:v1
  <app-name>

Эта команда сообщает buildpack, что из имеющихся в каталоге целей для сборки выбрана ./cmd/service.

Можно ли опубликовать образ прямо в реестре контейнеров?

Легко. Просто укажите <app-name> в качестве названия образа, который хотите опубликовать, а рядом флаг --publish, и buildpack автоматически добавит этот образ. Например, если надо опубликовать в gcr, используйте такую команду:

pack build
  --env GOOGLE_BUILDABLE=./cmd/service
  --builder gcr.io/buildpacks/builder:v1
  --publish
  gcr.io/<my-project>/<app-name>

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

🚀 Бонус: используйте тот же код в Cloud Build

Поделюсь с вами простым скриптом сборки и публикации, который используется непосредственно в Cloud Build для создания приложения на Go в Google Cloud:

steps:
  - name: 'gcr.io/k8s-skaffold/pack'
    entrypoint: 'pack'
    dir: 'user'
    args: [
        'build',
        '--builder=gcr.io/buildpacks/builder',
        '--env', 'GOOGLE_BUILDABLE=./cmd/service',
        '--publish',
        'gcr.io/<project>/<image>'
    ]

Вот и все

Надеюсь, я немного упростил вам работу с Go. Спасибо за внимание и за то, что дочитали статью до конца.

Читайте также:

Читайте нас в Telegram, VK и Яндекс.Дзен


Перевод статьи Peter Malina: You don’t need a Dockerfile to build a Go Container

Предыдущая статья9 привычек неумелого разработчика
Следующая статьяВладеешь merge  -  освой и rebase