Initial commit

This commit is contained in:
step305
2026-09-29 20:20:26 +03:00
parent 61d0ec3bcd
commit 17b5d19f69
17 changed files with 808 additions and 14 deletions
+70
View File
@@ -0,0 +1,70 @@
# ==============================================================================
# ЭТАП СБОРКИ (BUILDER)
# ==============================================================================
# Используем официальный образ Go на базе легковесного дистрибутива Alpine Linux.
# Именуем этот этап как "builder", чтобы позже забрать из него скомпилированный файл.
FROM golang:1.27-alpine AS builder
# Устанавливаем Git без сохранения кэша пакетов (уменьшает размер слоя).
# Он необходим Go для скачивания внешних зависимостей (например, golang.org/x/sys).
RUN apk add --no-cache git
# Объявляем переменные окружения для создания изолированного системного пользователя.
ENV USER=stunuser
ENV UID=10001
# Создаем безопасного пользователя внутри сборочного контейнера:
# --disabled-password: без пароля (вход по паролю заблокирован)
# --gecos "": отключает заполнение анкетных данных (имя, телефон и т.д.)
# --home "/nonexistent": без домашней папки
# --shell "/sbin/nologin": запрещает пользователю выполнять bash/sh команды в системе
# --no-create-home: принудительно запрещает создавать домашний каталог
RUN adduser --disabled-password --gecos "" --home "/nonexistent" --shell "/sbin/nologin" --no-create-home --uid "${UID}" "${USER}"
# Устанавливаем рабочую директорию, где будет происходить сборка кода
WORKDIR /app
# Шаг оптимизации кэша Docker: сначала копируем только файлы зависимостей go.mod и go.sum.
# Звездочка * защищает от ошибки сборки, если файла go.sum еще физически не существует.
COPY go.mod* go.sum* ./
# Если файл go.mod существует, скачиваем все внешние библиотеки и проверяем их хэш-суммы.
# Благодаря этому шагу зависимости будут кэшироваться и не будут скачиваться заново при изменении кода.
RUN if [ -f go.mod ]; then go mod download && go mod verify; fi
# Копируем весь оставшийся исходный код проекта (main.go и другие файлы) в рабочую директорию
COPY . .
# Компилируем высокопроизводительный бинарник:
# CGO_ENABLED=0: отключаем зависимости от C-библиотек (делает бинарник полностью автономным)
# GOOS=linux: жестко указываем целевую операционную систему Linux
# -ldflags="-s -w": отключает генерацию отладочной информации (символов) и таблиц DWARF.
# Это уменьшает размер итогового файла почти в 2 раза без потери скорости.
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /app/stun_server .
# ==============================================================================
# ФИНАЛЬНЫЙ ЭТАП (PRODUCTION)
# ==============================================================================
# FROM scratch — это пустой слой. В нем нет Linux, нет bash, нет пакетных менеджеров.
# Это гарантирует минимальный размер контейнера и максимальную безопасность (его невозможно взломать).
FROM scratch
# Переносим файлы пользователей и групп, созданные на этапе сборки.
# Без этого контейнер scratch не узнает, кто такой "stunuser".
COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /etc/group /etc/group
# Копируем единственный скомпилированный исполняемый файл STUN-сервера из этапа builder
COPY --from=builder /app/stun_server /stun_server
# Переключаем контекст выполнения. Сервер будет работать от имени stunuser, а не root.
# Если в коде сервера найдут уязвимость, злоумышленник все равно не получит права root на хосте.
USER stunuser:stunuser
# Документируем, что контейнер слушает порт 3478 по протоколу UDP
EXPOSE 3478/udp
# Точка входа: при старте контейнера автоматически запускается наш STUN-сервер.
# Использование квадратных скобок [строгий JSON] запускает процесс напрямую (PID 1) без лишней оболочки sh.
ENTRYPOINT ["/stun_server"]