Ответ
Для сборки Go-приложения в Docker нужно создать Dockerfile и выполнить команду docker build.
Пример для Go-приложения (многоэтапная сборка):
# Используем официальный образ Go для сборки
FROM golang:1.21 as builder
# Устанавливаем рабочую директорию внутри контейнера
WORKDIR /app
# Копируем файлы go.mod и go.sum для кэширования зависимостей
COPY go.mod go.sum ./
RUN go mod download
# Копируем исходный код и собираем приложение
COPY . .
# CGO_ENABLED=0: отключает CGO, создавая статически слинкованный бинарник
# GOOS=linux: указывает целевую ОС для компиляции
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/main .
# Используем минимальный образ для запуска (уменьшает размер итогового образа)
FROM alpine:latest
WORKDIR /app
# Копируем собранный бинарник из предыдущего этапа
COPY --from=builder /app/main .
# Команда для запуска приложения при старте контейнера
CMD ["/app/main"]
Сборка и запуск Docker-образа:
docker build -t my-go-app .
docker run -p 8080:8080 my-go-app
Оптимизации, примененные в примере:
- Многоэтапная сборка (
FROM ... as builder): Позволяет использовать большой образ с инструментами для сборки, а затем копировать только готовый бинарник в минимальный образ для запуска. Это значительно уменьшает итоговый размер Docker-образа. - Отключение CGO (
CGO_ENABLED=0): Создает статически слинкованный бинарник, который не зависит от системных библиотек целевой ОС, что позволяет использовать очень маленькие базовые образы, такие какalpine. - Использование
alpine:alpine— это очень маленький дистрибутив Linux, который идеально подходит для создания минимальных Docker-образов. - Кэширование зависимостей (
COPY go.mod go.sum ./передCOPY . .): Если файлыgo.modиgo.sumне меняются, Docker может использовать кэшированный слой для загрузки модулей, ускоряя последующие сборки.
Ответ 18+ 🔞
Ах ты ж, ёпта, опять эти докер-файлы! Ну ладно, разберём, как из вашего кода на Go сделать такую банку, чтобы её можно было таскать куда угодно, не боясь, что она там сдохнет без нужных библиотек.
Смотри сюда, вся магия начинается с создания файла под названием Dockerfile. Это как инструкция для докера, что и в каком порядке делать, чтобы получился образ. А потом командочка docker build — и понеслась.
Вот тебе пример, как это делают умные люди (многоэтапная сборка, блядь):
# Берём здоровенный образ Go со всеми инструментами для сборки
FROM golang:1.21 as builder
# Говорим докеру: "Работать будем вот в этой папке внутри контейнера"
WORKDIR /app
# Сначала копируем только go.mod и go.sum. Это хитрая жопа!
# Если они не менялись, докер возьмёт зависимости из кэша и не будет качать их заново.
COPY go.mod go.sum ./
RUN go mod download
# Теперь копируем ВЕСЬ остальной код
COPY . .
# А теперь самое важное: собираем бинарник.
# CGO_ENABLED=0 — выключаем эту хуйню, чтобы бинарник был статическим и ни от кого не зависел.
# GOOS=linux — говорим компилятору: "Собери нам программу для Линукса, нахуй!"
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/main .
# Второй этап, ёбушки-воробушки! Берём крошечный образ alpine
FROM alpine:latest
WORKDIR /app
# И волшебным образом копируем в него ТОЛЬКО готовый бинарник из первого этапа.
# Ни компилятора, ни исходников — ничего лишнего!
COPY --from=builder /app/main .
# И команда, которая выполнится, когда контейнер запустят
CMD ["/app/main"]
Ну а чтобы это всё ожило, в терминале пишешь:
docker build -t my-go-app .
docker run -p 8080:8080 my-go-app
А теперь, блядь, почему этот способ — овердохуища хорош:
- Многоэтапная сборка (
FROM ... as builder): Сначала мы в большом, жирном образе всё собираем, а потом забираем только готовый исполняемый файл и суём его в образ-лилипут. Итоговый размер образа — просто ни в какие ворота, в десятки раз меньше! - Выключение CGO (
CGO_ENABLED=0): Делает бинарник полностью самодостаточным. Ему не нужны системные библиотеки на целевой машине. Поэтому он и вalpineпрекрасно запустится. - Использование
alpine: Это же мартышлюшка какая-то, а не операционка! Очень маленькая, зато всё что нужно для запуска статического бинарника — есть. - Кэширование зависимостей: Сначала копируем
go.modиgo.sum, а потом уже весь код. Если зависимости не менялись, докер не будет их качать снова, а возьмёт из кэша. Экономия времени — просто пиздец!
Вот так, без лишней хуйни и гигабайтов мусора в образе. Красота, ёпта!