Version in English

Gopher Container

Introdução

A linguagem Go permite que facilmente compilemos nossa aplicação em um único binário estático, sem dependências externas.

Além da conveniência de ser um único arquivo portátil, o binário estático geralmente é relativamente pequeno, especialmente para aplicações simples. Tamanhos típicos são da ordem de dezenas de megabytes.

Esse arranjo compacto abre a possibilidade de criar imagens de contêiner Docker extremamente pequenas, contendo apenas o binário estático e nada mais. As imagens pequenas contribuem com diversas vantagens:

  • Downloads mais rápidos, reduzindo tempo de implantação/inicialização, tempo de escalonamento e custos de rede.
  • Menor uso de espaço em disco, reduzindo custos de armazenamento.
  • Superfície de ataque reduzida, aumentando a segurança.

A seguir, ilustraremos como compilar uma aplicação Go em um único binário estático e criar uma imagem de contêiner Docker mínima contendo apenas esse binário.

Compilando para um Executável Único

Considere o seguinte comando de compilação.

$ CGO_ENABLED=0 go install -ldflags='-s -w' -trimpath ./app

Podemos verificar que o binário gerado é um executável estático usando o comando file. Note o trecho statically linked na saída.

$ file `which app`

/home/everton/go/bin/app: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=c8a2bee2f51925e2a3b1f2711d116795555588c2, stripped

O arquivo binário estático executável gerado possui apenas 6 MB, pois se trata de uma aplicação simples.

$ ls -al `which app`
-rwxrwxr-x 1 everton everton 6103224 nov 19 21:55 /home/everton/go/bin/app

É importante lembrar que este único arquivo possui tudo o que é necessário para a execução da aplicação.

Podemos criar uma imagem de contêiner Docker que contenha apenas este único arquivo binário.

Criando uma Imagem de Contêiner com um Único Arquivo

O Dockerfile abaixo mostra o build da imagem em dois estágios. No primeiro estágio, usamos a imagem oficial do Go para compilar o binário estático. No segundo estágio, usamos a imagem scratch, que é uma imagem vazia, para criar uma imagem de contêiner mínima contendo apenas o binário compilado.

# STEP 1 build executable binary

FROM golang:1.25.4-alpine AS builder

RUN adduser -D -g '' appuser
COPY app/* /build/app/
COPY go.mod /build/
WORKDIR /build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags='-s -w' -trimpath -o /app ./app

# STEP 2 build a small image

FROM scratch

COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /app /app
USER appuser
ENTRYPOINT ["/app"]

Para construir a image da receita acima, usamos o comando docker build:

docker build -t udhos/web-scratch:latest .

Após a construção, podemos verificar o tamanho da imagem usando o comando docker images:

$ docker images udhos/web-scratch:latest
REPOSITORY          TAG       IMAGE ID       CREATED          SIZE
udhos/web-scratch   latest    b7a2982cab1f   33 minutes ago   6.1MB

6.1 MB!

Mas será que a imagem funciona corretamente? Vamos executar um contêiner a partir da imagem criada:

$ docker run --rm -p 8080:8080 -it udhos/web-scratch:latest
2025/11/20 01:14:42 version=0.8.2 runtime=go1.25.4 pid=1 host=ab8b011a7ada GOMAXPROCS=16 OS=linux ARCH=amd64
2025/11/20 01:14:42 GWH_BANNER='' PORT=''
2025/11/20 01:14:42 user: appuser (uid: 1000)
2025/11/20 01:14:42 banner: banner default
2025/11/20 01:14:42 keepalive: true
2025/11/20 01:14:42 burnCpu=false
2025/11/20 01:14:42 quotaTime=0s
2025/11/20 01:14:42 requests quota=0 (0=unlimited) exitOnQuota=false quotaStatus=500
2025/11/20 01:14:42 TLS key file not found: key.pem - disabling TLS
2025/11/20 01:14:42 TLS cert file not found: cert.pem - disabling TLS
2025/11/20 01:14:42 mapping www path /www/ to directory /
2025/11/20 01:14:42 using TCP ports HTTP=:8080 HTTPS=:8443 TLS=false
2025/11/20 01:14:42 serving HTTP on TCP :8080

Funciona! Basta acessar http://localhost:8080 no navegador para ver a aplicação em funcionamento.

Browser Screenshot

Conclusão

A facilidade para criação de executáveis estáticos em Go, combinada com a imagem base scratch do Docker, permite criar imagens de contêiner extremamente pequenas e eficientes.

Referências