В продолжение предыдущей статьи контейнеризируем проект Go и создадим прокси-сеть с Envoy.
Контейнеризация приложения — это процесс преобразования приложения и всех его компонентов в пакет или контейнер с использованием платформы Docker. Контейнер Docker определяется как компактное, перемещаемое и автономное пространство, в котором приложение выполняется без воздействия внешней среды.
Dockerfile
FROM golang:1.23-alpine AS builder
RUN apk update && apk add --no-cache git
ENV GO111MODULE=on \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o main .
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/main .
EXPOSE 9090
EXPOSE 9000
CMD ["./main"]
Этим Dockerfile создается многоэтапная сборка для приложения Go, интегрированного с прокси-сервером Envoy.
На первом этапе, чтобы извлечь зависимости и скомпилировать приложение в статический двоичный файл, используется легковесный образ Go.
На втором настраивается прокси-сервер Envoy, в контейнер копируется конфигурационный файл envoy.yaml.
На заключительном этапе для запуска скомпилированного бинарника Go используется минимальный образ Alpine Linux, при этом приложение копируется из этапа builder.
Для трафика приложения и прокси-сервера контейнером предоставляются порты 9090, 9000 и 5209 со стандартным набором команд для выполнения приложения Go.
Docker Compose
services:
grpc-example:
build:
context: ./
dockerfile: Dockerfile
container_name: grpc-example
ports:
- "9090:9090" # HTTP-сервер на Gin
- "9000:9000" # gRPC сервер
extra_hosts:
- "host.docker.internal:host-gateway"
depends_on:
- db
restart: always
envoyproxy-grpc-example:
build:
context: ./
dockerfile: Dockerfile-envoy
container_name: envoy-grpc-example
ports:
- "5209:5209"
extra_hosts:
- "host.docker.internal:host-gateway"
restart: always
db:
image: postgres:15
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: admin123
POSTGRES_DB: learnInternLen
ports:
- "5432:5432"
volumes:
- ./db:/docker-entrypoint-initdb.d/
Этим файлом Docker Compose определяется многоконтейнерная структура с тремя службами: grpc-example, envoyproxy-grpc-example и db.
Первой службой создается gRPC и HTTP-сервер на Go из Dockerfile, предоставляются порты 9090 и 9000 соответственно, она зависит от службы PostgreSQL db.
Второй создается прокси-сервер Envoy из отдельного Dockerfile-envoy, предоставляется порт 5209 для взаимодействия с прокси-сервером.
У обеих служб имеется конфигурация extra_hosts для взаимодействия с хост-машиной, они автоматически перезапустятся при сбое.
Службой db используется официальный образ PostgreSQL 15 с переменными среды для конфигурирования базы данных и скриптом инициализации, подключаемым из локального каталога ./db. База данных PostgreSQL доступна через порт 5432.
Конфигурация Envoy
Dockerfile-envoy
FROM envoyproxy/envoy-dev:latest
COPY ./envoy.yaml /etc/envoy/envoy.yaml
EXPOSE 5209
CMD /usr/local/bin/envoy -c /etc/envoy/envoy.yaml -l trace --log-path /tmp/envoy_info.log
Для наглядности, модульности и сопровождаемости обычно используется отдельный dockerfile. Им определяется структура контейнера Envoy на основе образа envoyproxy/envoy-dev:latest и копируется пользовательский конфигурационный файл envoy.yaml из локальной машины в каталог контейнера /etc/envoy/.
В Dockerfile предоставляется порт 5209 для входящего трафика и задается стандартная команда CMD для запуска Envoy с указанным конфигурационным файлом /etc/envoy/envoy.yaml.
envoy.yaml
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 5209 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: "*"
routes:
- match:
prefix: "/"
route:
cluster: grpc_service
http_filters:
- name: envoy.grpc_web
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: grpc_service
connect_timeout: 0.25s
type: LOGICAL_DNS
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http2_protocol_options: {}
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: grpc_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: grpc-example
port_value: 9000
Этим файлом Envoy конфигурируется как прокси-сервер HTTP, которым через порт 5209 прослушивается входящий трафик. Им же настраивается фильтр диспетчера HTTP-подключений для обработки запросов с маршрутизацией, определенной для всех доменов * с префиксом / для перенаправления трафика в серверную службу gRPC grpc_service.
Служба gRPC определяется в разделе clusters при помощи DNS-разрешения LOGICAL_DNS для направления трафика в службу grpc_example, запускаемую на порту 9000.
В файле также содержится фильтр HTTP маршрутизатора для управления HTTP-запросами. При маршрутизации используется политика циклической балансировки нагрузки для серверной службы.
Сборка контейнера
Настроив все, собираем и запускаем контейнер такими командами:
docker-compose build
docker-compose up
Вот результат:

Тестируем сеть Envoy, отправляя на localhost:5209 gRPC-запрос:

Заключение
Процесс контейнеризации приложения Go состоит из различных аспектов, в том числе создания ориентированной на взаимодействия архитектуры, особенно для микросервисных систем.
Комбинированием Docker, Go и Envoy службы легко оркестрируются и развертываются, чем обеспечивается стабильное и предсказуемое расширение.
Envoy — высокопроизводительный прокси-сервер, который находится перед приложением для маршрутизации трафика, балансировки нагрузки, служб gRPC и других инструментов наблюдаемости.
Конфигурацией envoy.yaml также предоставляется функционал маршрутизации запросов в серверные службы, такие как написанные на Go серверы gRPC. Этим повышаются масштабируемость, безопасность и гибкость.
Кроме того, упрощаются развертывание и конфигурирование сложных сетевых задач, таких как разрешение DNS-запросов или осуществление трафика.
Наконец, контейнеризацией рабочего процесса проекта на Go с помощью Envoy ускоряются разработка, тестирование и производственные процессы эксплуатации и сопровождения в пространстве распределенных систем.
Читайте также:
- Конкурентность на Go: горутины и каналы для масштабируемых приложений
- Рекомендации по Go: выделение памяти с new
- Как писать безопасный код на Go
Читайте нас в Telegram, VK и Дзен
Перевод статьи Izzan Alfadhil: Dockerize a GO Project with Envoy





