← Назад к вопросам

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

1.3 Junior🔥 161 комментариев
#Контейнеризация и DevOps

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как собрать Docker-образ для Go-приложения

Сборка Go-приложения в Docker — стандартная практика для создания переносимых, изолированных и воспроизводимых окружений. Вот полное руководство по этому процессу.

1. Основные этапы сборки

Сборка образа состоит из нескольких ключевых шагов:

  1. Написание Dockerfile — инструкции для сборки
  2. Подготовка кода — структурирование проекта
  3. Выполнение сборки — создание образа
  4. Оптимизация — уменьшение размера образа

2. Пример базового Dockerfile

Создайте файл Dockerfile в корне проекта:

# Этап 1: Сборка приложения
FROM golang:1.21-alpine AS builder

# Устанавливаем рабочую директорию
WORKDIR /app

# Копируем файлы зависимостей
COPY go.mod go.sum ./
RUN go mod download

# Копируем исходный код
COPY . .

# Собираем приложение
# CGO_ENABLED=0 для статической сборки
# -ldflags="-s -w" для уменьшения размера бинарника
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o myapp ./cmd/main.go

# Этап 2: Создание минимального образа
FROM alpine:latest

# Устанавливаем необходимые пакеты (если нужны)
RUN apk --no-cache add ca-certificates

# Создаем непривилегированного пользователя
RUN addgroup -g 1000 appuser && \
    adduser -D -u 1000 -G appuser appuser

# Устанавливаем рабочую директорию
WORKDIR /home/appuser

# Копируем бинарник из этапа сборки
COPY --from=builder --chown=appuser:appuser /app/myapp .

# Переключаемся на непривилегированного пользователя
USER appuser

# Определяем точку входа
ENTRYPOINT ["./myapp"]

3. Многоэтапная сборка (Multi-stage build)

Многоэтапная сборка — ключевая техника для Go:

  • Первый этап (builder): Использует полный образ Go для компиляции
  • Второй этап: Использует минимальный образ (Alpine или scratch) для запуска
  • Результат: Маленький финальный образ (часто 10-20 МБ вместо 1 ГБ)

4. Оптимизация размера образа

Для Go-приложений доступны несколько уровней оптимизации:

# Вариант 1: scratch (минимальный)
FROM scratch
COPY --from=builder /app/myapp /
ENTRYPOINT ["/myapp"]

# Вариант 2: distroless (без оболочки)
FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/myapp /
ENTRYPOINT ["/myapp"]

# Вариант 3: Alpine (с оболочкой для отладки)
FROM alpine:3.18
RUN apk --no-cache add ca-certificates
COPY --from=builder /app/myapp /usr/local/bin/
ENTRYPOINT ["myapp"]

5. Сборка и управление образами

Сборка образа:

# Базовая сборка
docker build -t myapp:latest .

# Сборка с указанием контекста
docker build -f Dockerfile.prod -t myapp:v1.0 .

# Сборка для другой архитектуры
docker build --platform linux/amd64 -t myapp:amd64 .

Полезные команды:

# Просмотр истории сборки
docker history myapp:latest

# Анализ размера слоев
docker images --digests

# Запуск контейнера
docker run -p 8080:8080 --name myapp-container myapp:latest

# Просмотр логов
docker logs -f myapp-container

6. Дополнительные оптимизации

  • Использование .dockerignore:

    .git
    .env
    Dockerfile
    *.test
    vendor/
    coverage.out
    
  • Кэширование зависимостей:

    # Копируем только go.mod и go.sum сначала
    COPY go.mod go.sum ./
    RUN go mod download
    
    # Затем копируем остальной код
    COPY . .
    
  • Параметризация сборки:

    # Использование build-args
    docker build \
      --build-arg VERSION=1.0.0 \
      --build-arg BUILD_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
      -t myapp:latest .
    

7. Best Practices для Go-приложений

  1. Статическая линковка: CGO_ENABLED=0 устраняет зависимости от системных библиотек
  2. Безопасность: Запуск от непривилегированного пользователя
  3. Повторяемость: Фиксируйте версии базовых образов
  4. Логирование: Настройте вывод логов в stdout/stderr для Docker
  5. Здоровье: Добавьте healthcheck в Dockerfile:
    HEALTHCHECK --interval=30s --timeout=3s \
      CMD curl -f http://localhost:8080/health || exit 1
    

8. Пример продвинутой конфигурации

# syntax=docker/dockerfile:1.4
FROM --platform=$BUILDPLATFORM golang:1.21-alpine AS builder

ARG TARGETOS TARGETARCH
ARG VERSION="dev"
ARG COMMIT="unknown"

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

COPY . .
RUN --mount=type=cache,target=/root/.cache/go-build \
    GOOS=$TARGETOS GOARCH=$TARGETARCH \
    CGO_ENABLED=0 \
    go build \
    -ldflags="-X main.Version=$VERSION -X main.Commit=$COMMIT -s -w" \
    -o /app/myapp \
    ./cmd

FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/myapp /myapp
USER 1000:1000
EXPOSE 8080
ENTRYPOINT ["/myapp"]

9. Интеграция с CI/CD

Для автоматизации:

  • GitHub Actions: Используйте официальные actions docker/*
  • GitLab CI: Встроенная поддержка Docker
  • Jenkins: Docker pipeline plugin

Пример GitHub Actions:

name: Build and Push
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build Docker image
        run: docker build -t myapp:${{ github.sha }} .

Заключение

Сборка Go-приложений в Docker сочетает простоту и эффективность. Многоэтапная сборка позволяет создавать минимальные образы (часто менее 10 МБ), что улучшает безопасность и ускоряет деплой. Ключевые моменты: статическая линковка, использование .dockerignore, запуск от непривилегированного пользователя и правильное кэширование зависимостей. Такой подход обеспечивает воспроизводимость, портативность и соответствие modern DevOps практикам.