V tomto článku
Přestaňte instalovat Go na hostitelský systém. Žádné zaneřáděné
GOPATH, žádné „u mě to funguje“ a nulový rozptyl verzí. Přesně tento postup jsme použili při přepisu agentů v Javě pro reporty BigBlueButton Learning Analytics a při vývoji zabezpečeného agenta Piler v Go. Ukážeme vám, jak dodávat statické binárky jen s pomocí Dockeru.
Autor: Ghazi Triki, RIADVICE
Problém s radou „prostě si nainstalujte Go“
Když jsme spravovali agenty v Javě pro reporty BigBlueButton Learning Analytics, narazili jsme na klasické „peklo závislostí“. Přechod na Go sliboval jednoduchost, ale jen pokud nezopakujeme stejné chyby. Potřebovali jsme proces sestavení, který bude stejně hermetický jako binárky, které vytváří.
Každý tým na tyto překážky dříve či později narazí:
- Rozptyl verzí. Ahmed má 1.24, Omar 1.26 a produkční server 1.25. Drobná změna v kompilátoru rozbije sestavení, ale jen Ahmedovi.
- Zaneřáděné hostitelské systémy.
GOPATH,GOMODCACHEa globálně nainstalované nástroje (staticcheck,gofumpt), které se na každé pracovní stanici liší. - Pomalý nástup nových lidí. Nový inženýr stráví první den bojem s proměnnými prostředí a toolchainy jazyka C pro
cgo.
V RIADVICE si ceníme disciplíny a pořádku. Chtěli jsme proces sestavení, který to odráží: čistý, předvídatelný a společný.
Standardní odpověď zní „použijte Docker“, většina návodů vám ale ukáže jen to, jak sestavit image kontejneru. Neukáže, jak na hostitelském systému získat obyčejnou, staticky linkovanou binárku, tedy artefakt, který skutečně potřebujete pro službu systemd nebo pro nasazení v izolovaném prostředí, aniž byste lokálně instalovali kompilátor Go.
docker run --rm -v "$(pwd):/app" -w /app golang:1.26.5-trixie \
go build -o dist/myapp ./cmd/myappKompilátorem je oficiální image golang. Váš zdrojový kód je připojen přes bind mount do /app. Binárka se zapíše na hostitelský systém do dist/myapp. Po dokončení příkazu se kontejner odstraní (--rm) a hostitelský systém zůstane stejně čistý jako předtím.
Zkušenosti z praxe: od BigBlueButton po Piler
Nejde jen o teorii. Tento postup jsme uplatnili ve dvou klíčových projektech:
- Reporty BigBlueButton Learning Analytics: Těžkopádné agenty v Javě jsme přepsali do odlehčených binárek v Go. Díky sestavování v Dockeru jsme mohli cílit přesně na prostředí Debianu na serverech BBB, aniž bychom toto prostředí potřebovali na svých noteboocích.
- Agent Piler v Go: Pro naše řešení archivace e-mailů jsme vyvinuli agenta se zvýšeným zabezpečením. Proces sestavení musel být stejně bezpečný jako samotný kód. Připnutím kompilátoru na konkrétní SHA jsme zajistili, že každý bit v binárce má svůj doložený původ.
Proč je to lepší než instalovat Go
| Hledisko | go install na hostiteli | docker run golang:... |
|---|---|---|
| Verze Go | Ta, kterou jste naposledy nainstalovali | Připnutá, pro všechny stejná |
| GOPATH / cache | Zaneřádí ~/go | Hermetické vrstvy kontejneru |
| Toolchain pro cgo | Vyžaduje nastavení hostitele | Součástí oficiálního image |
| Shoda s CI | „U mě to funguje“ | Stejný image, stejná binárka |
BINARY := mini-api
DIST := dist
# Version metadata derived from git
VERSION := $(shell tmp=$$(git describe --tags --always --dirty 2>/dev/null) && echo "$${tmp#v}" || echo dev)
COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null || echo unknown)
BUILD_DATE := $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
LDFLAGS := -X example.com/mini-api/internal/version.Version=$(VERSION) \
-X example.com/mini-api/internal/version.Commit=$(COMMIT) \
-X example.com/mini-api/internal/version.Branch=$(BRANCH) \
-X example.com/mini-api/internal/version.BuildDate=$(BUILD_DATE)
# Pinned toolchain image
GO_IMAGE := golang:1.26.5-trixie
# Run any command inside the Go toolchain container
define run_in_docker
docker run --rm -v "$(PWD):/app" -w /app $(GO_IMAGE)
endef
.PHONY: build test lint
build:
@mkdir -p $(DIST)
$(call run_in_docker) bash -c 'CGO_ENABLED=0 go build -buildvcs=false -ldflags="$(LDFLAGS)" -o $(DIST)/$(BINARY) ./cmd/$(BINARY)'
@echo "Built $(DIST)/$(BINARY) (version $(VERSION))"
test:
$(call run_in_docker) go test -race ./...
lint:
$(call run_in_docker) go vet ./...Makefile: zdroj disciplíny
Kroky sestavení zapisujeme do souboru Makefile. Všimněte si, že GO_IMAGE je připnutý na konkrétní verzi. Nikdy nepoužíváme latest.
Technické detaily, na kterých záleží
1. CGO_ENABLED=0 pro statické binárky
U agenta Piler jsme potřebovali binárky, které poběží na čemkoli, od moderního Debianu po starší server. Vypnutí CGO zajistí, že binárka obsahuje vše, co potřebuje, bez dynamických závislostí na knihovnách hostitele.
2. -ldflags -X pro doložení původu
Vaše binárka by vám měla umět přesně říct, odkud pochází. Commit z gitu a datum sestavení do ní vkládáme při linkování. Pro ladění agentů BigBlueButton napříč desítkami různých clusterů to bylo zásadní.
3. Připnutí image kompilátoru
V naší kultuře věříme v konzistenci. Když místo latest připneme golang:1.26.5-trixie, znamená to, že pokud Ahmed sestaví binárku dnes a Omar za šest měsíců, výstup bude bit po bitu totožný.
Závěr
Kompilátor je nástroj a jako každý nástroj patří na své místo. Přesunem toolchainu Go do Dockeru jsme odstranili celou kategorii chyb typu „u mě to funguje“ a zjednodušili nástup každého nového inženýra, který do RIADVICE přijde.
Ať už přepisujete agenty v Javě, nebo vyvíjíte zabezpečené API pro Piler, tento postup přináší disciplínu a spolehlivost, kterou produkční systémy vyžadují.
Ghazi Triki je zakladatelem RIADVICE. Vyvíjíme výkonné a bezpečné integrace pro BigBlueButton, Piler a další systémy. Pojďme společně vytvořit něco skvělého.





