Otimizando imagens docker com multi-stage builds

BIANCA ROSA

Vamos começar a usar Docker!

FROM golang:1.14

RUN curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh

WORKDIR /go/src/app
COPY . .

RUN dep ensure
RUN go build -o app-bin .

ENTRYPOINT ["./app-bin"]

Você já parou pra notar quanto de espaço em disco suas imagens docker gastam?

O que acontece no processo de build?

Código-fonte

Executável

Em linguagens compiladas, pra rodar a aplicação, você só precisa do código executável - e nada do que foi necessário pra gerar ele.

Multi-stage builds

FROM golang:1.14 as build

RUN curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh

WORKDIR /go/src/app
COPY . .

RUN dep ensure
RUN go build -o app-bin .

FROM scratch
COPY  --from=build /go/src/app/app-bin ./
ENTRYPOINT ["./app-bin"]

Ops, não funciona!

linkagem estática
vs

linkagem dinâmica

FROM golang:1.14 as build

RUN curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh

WORKDIR /go/src/app
COPY . .

RUN dep ensure
RUN CGO_ENABLED=0 go build -installsuffix nocgo -o app-bin .

FROM scratch
COPY  --from=build /go/src/app/app-bin ./
ENTRYPOINT ["./app-bin"]

E o tamanho da imagem ó

Dá pra usar com quais linguagens?

  • Fácil: build de front-end em JS
  • Médio: linguagens que compilam pra código de máquina - Go, C, C++
  • Difícil: Linguagens que compilam pra bytecode: Python, C#, Java
  • Pro: Estratégias pra criar builds pipeline com testes, linters, etc

Links legais

Aviso: tutoriais de internet  (e até palestras como essa) raramente vão te dar o melhor caminho pra uma imagem produtiva, isso é outro tópico