Как собрать приложение в Docker

Ответ

Для сборки 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, а потом уже весь код. Если зависимости не менялись, докер не будет их качать снова, а возьмёт из кэша. Экономия времени — просто пиздец!

Вот так, без лишней хуйни и гигабайтов мусора в образе. Красота, ёпта!