Отладка внутри контейнера с помощью GO

Как разработчики, мы тратим значительную часть своего времени на отладку. Но иногда, из-за ограничений по настройке и отсутствия инструментов отладки для разработки контейнеров, это просто невозможно.

При локальной работе достаточно нажать кнопку Debug, и все работает как по волшебству.

Однако при работе с удаленным окружением или при работе внутри контейнеров у нас больше нет опции Debug, и мы даже не можем скомпилировать двоичный файл в режиме отладки.

Некоторые IDE пытаются решить эту проблему, но чаще всего их решение недостаточно хорошо, поэтому мы вынуждены полагаться на специальное протоколирование.

Настоящая проблема заключается в том, что контейнеры не предназначены для активной разработки. Они создают барьеры для перезапуска процессов, перекомпиляции двоичных файлов на лету и других динамических изменений во время выполнения. В результате работа с контейнерными средами становится обременительной, и мы тратим кучу времени на обходные пути:

1. Мы можем добавить журналы и перестроить образ.

Поскольку отладка занимает так много времени на настройку, мы можем сдаться. Вместо этого мы итерационно добавляем дополнительные специальные журналы регистрации вокруг области, которую мы разрабатываем. Мы не только получаем ограниченное количество информации, но и увеличиваем время цикла, поскольку сборка образа и повторное развертывание контейнера (локально или удаленно) может занять минуты вместо секунд.

Иногда это лучший вариант… если в итоге мы найдем ошибку за несколько итераций — в противном случае мы будем прогрессировать, но очень медленно. Проблема в том, что вы никогда не можете знать, сколько итераций потребуется, и обычно мы недооцениваем ;).

2. Мы можем де-контейнеризировать сервис, который мы сейчас разрабатываем.

Оставив все остальные контейнеры в окружении, мы можем остановить контейнер с сервисом, который мы сейчас разрабатываем, и запустить его локально. Это позволит нам отлаживать и запускать с помощью отличного встроенного инструментария-IDE!

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

3. Мы можем отлаживать внутри контейнера, устанавливая необходимые зависимости в образ и пересобирая двоичный файл.

Это наиболее масштабируемый подход к отладке внутри контейнеров, поскольку после единовременных затрат на настройку он позволяет быстро выполнять итерации и использовать все возможности отладки.

Мы углубимся в вариант № 3 и рассмотрим, как отлаживать GO-код внутри контейнера. Чтобы это работало, нам потребуется установить инфраструктуру отладки (delve) и инструментарий, чтобы мы могли компилировать внутри контейнера.

Отладка с помощью GO внутри работающего контейнера

Давайте начнем с простого примера контейнеризированного сервиса Go и внесем необходимые изменения для отладки сервиса с помощью Delve:

FROM golang:1.18-alpine3.15 as builder

WORKDIR /code/
COPY ./go.mod ./go.sum /code/
RUN --mount=type=cache,target=/go/pkg/mod go mod download

COPY . .
RUN go build -o /code/build/server main.go

FROM alpine:3.15
COPY --from=builder /code/build/server /server

ENTRYPOINT ["/server"]
Войти в полноэкранный режим Выход из полноэкранного режима

Шаг 1: Измените способ сборки двоичного файла

В качестве первого шага давайте изменим команду go build так, чтобы она сохраняла символы отладки в полученном бинарном файле:

FROM golang:1.18-alpine3.15 as builder

WORKDIR /code/
COPY ./go.mod ./go.sum /code/
RUN --mount=type=cache,target=/go/pkg/mod go mod download

COPY . .
RUN go build -gcflags "all=-N -l" -o /code/build/server main.go

FROM alpine:3.15
COPY --from=builder /code/build/server /server

ENTRYPOINT ["/server"]
Войти в полноэкранный режим Выйти из полноэкранного режима

Шаг 2: Установите необходимые зависимости (например, Delve)

Далее, давайте установим Delve —

FROM golang:1.18-alpine3.15 as builder

RUN apk add build-base
RUN go install github.com/go-delve/delve/cmd/dlv@latest

WORKDIR /code/
COPY ./go.mod ./go.sum /code/
RUN --mount=type=cache,target=/go/pkg/mod go mod download

COPY . .
RUN go build -gcflags "all=-N -l" -o /code/build/server main.go

FROM alpine:3.15
COPY --from=builder /go/bin/dlv /
COPY --from=builder /code/build/server /

ENTRYPOINT ["/server"]
Войти в полноэкранный режим Выйти из полноэкранного режима

Шаг 3: Запустите процесс с помощью dlv — так мы действительно сможем отлаживать!

Наконец, измените точку входа на исполняемый файл Delve, который мы скопировали, и настройте его на работу в качестве сервера отладки для нашего бинарного файла.

FROM golang:1.18-alpine3.15 as builder

RUN apk add build-base
RUN go install github.com/go-delve/delve/cmd/dlv@latest

WORKDIR /code/
COPY ./go.mod ./go.sum /code/
RUN --mount=type=cache,target=/go/pkg/mod go mod download

COPY . .
RUN go build -gcflags "all=-N -l" -o /code/build/server main.go

FROM alpine:3.15
COPY --from=builder /go/bin/dlv /
COPY --from=builder /code/build/server /

EXPOSE 2345
ENTRYPOINT ["/dlv", "--listen=:2345", "--headless=true", "--api-version=2", 
            "--accept-multiclient", "exec", "/server"]
Вход в полноэкранный режим Выход из полноэкранного режима

Контейнерная отладка, как локальная

В мире R&D очень важно иметь эффективные и простые в использовании среды разработки и рабочие процессы, чтобы мы могли работать без разочарований. Продолжительность цикла разработки (от изменения кода до получения обратной связи) является критически важным компонентом, а отладка дает нам очень богатую обратную связь для данного изменения кода.
Но отсутствие поддержки инструментов отладки в контейнерных средах само по себе постоянно отвлекает и останавливает рабочий процесс и мыслительный процесс ваших сотрудников.

Вот почему возможность — и простота — отладки в контейнерных службах, как если бы они были локальными, может дать огромные преимущества вашим командам.

Даже если контейнеры никогда не предназначались для использования dev таким образом, с Raftt отладка контейнерных сервисов становится такой же простой, как и отладка локальных сервисов на вашей машине.

О компании Raftt

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

Оцените статью
Procodings.ru
Добавить комментарий