Docker与Go:从零开始实现Golang应用容器化

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Docker и Go: полное руководство по контейнеризации Golang-приложений



Контейнеризация стала стандартом де-факто для развертывания современных приложений. Язык Go (Golang) идеально подходит для контейнерной среды: его скомпилированные бинарные файлы не требуют рантайма, а статическая линковка позволяет создавать минимальные образы Docker. В этой статье мы разберем процесс контейнеризации Go-приложений от написания Dockerfile до оптимизации размера итогового образа.



Почему Go и Docker — идеальная пара



Go компилируется в один статический бинарный файл, который не зависит от системных библиотек. Это означает, что для запуска Go-приложения в контейнере не нужно устанавливать Go Runtime, интерпретаторы или дополнительные зависимости. В результате вы получаете:



  • Минимальный размер образа — часто менее 10-15 МБ
  • Быстрый запуск — миллисекунды, а не секунды
  • Высокую безопасность — меньше компонентов = меньше уязвимостей
  • Простоту деплоя — один бинарный файл вместо множества скриптов и библиотек


Рассмотрим это на примере простого HTTP-сервера на Go.



Шаг 1: Создаем Go-приложение



Для начала напишем простое веб-приложение, которое будем контейнеризировать. Создайте файл main.go:



package main

import ( "fmt" "log" "net/http" "os")

func main() { port := os.Getenv("PORT") if port == "" { port = "8080" }

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Привет из контейнера Go! 🐳") })

log.Printf("Сервер запущен на порту %s", port) log.Fatal(http.ListenAndServe(":"+port, nil))}


Это минимальный HTTP-сервер, который слушает порт, заданный переменной окружения PORT (по умолчанию 8080).



Шаг 2: Многоэтапная сборка (Multi-stage build)



Для создания минимального образа Docker используется многоэтапная сборка. Первый этап — компиляция приложения, второй — создание финального образа только с бинарным файлом. Создайте Dockerfile:



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

WORKDIR /app

# Копируем go.mod и go.sum для кэширования зависимостейCOPY go.mod go.sum ./RUN go mod download

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

# Собираем статический бинарный файлRUN CGO_ENABLED=0 GOOS=linux go build -o /app/server .

# Этап 2: Финальный минимальный образFROM alpine:3.19

# Добавляем CA-сертификаты для HTTPSRUN apk --no-cache add ca-certificates

WORKDIR /root/

# Копируем бинарник из первого этапаCOPY --from=builder /app/server .

# Открываем портEXPOSE 8080

# Запускаем приложениеCMD ["./server"]


Обратите внимание на ключевые моменты:

  • golang:1.22-alpine — легковесный образ для сборки
  • CGO_ENABLED=0 — отключаем CGO для статической линковки
  • alpine:3.19 — минимальный Linux-образ (~5 МБ)
  • ca-certificates — нужны, если приложение использует HTTPS


Шаг 3: Сборка и запуск контейнера



Соберите Docker-образ и запустите контейнер:



# Сборка образаdocker build -t go-hello:latest .

# Запуск контейнераdocker run -d -p 8080:8080 --name go-app go-hello:latest

# Проверкаcurl http://localhost:8080# Вывод: Привет из контейнера Go! 🐳


Проверьте размер полученного образа:



docker images go-hello# REPOSITORY   TAG       IMAGE ID       CREATED          SIZE# go-hello     latest    abc123def456   10 seconds ago   14.2 MB


Всего 14.2 МБ — это ничтожно мало по сравнению с образами на Node.js (сотни МБ) или Python (десятки МБ).



Шаг 4: Оптимизация Dockerfile для продакшена

博客

书籍推荐