Estando todos vivendo numa era onde computação em nuvem vem sendo cada vez mais adotada, saber trabalhar com containers acaba se torna praticamente uma obrigação.
Por isso, nesse post, vamos ver como criar uma imagem Docker otimizada com multi stage build para aplicações escritas em Golang.
Antes de começar escrever nosso Dockerfile, vamos criar um arquivo main.go e escrever uma pequena API para retornar o famoso “Olá Mundo”.
package main import ( "fmt" "log" "net/http" ) func main() { http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) { fmt.Fprintf(rw, "Olá Mundo\\n") }) log.Fatal(http.ListenAndServe(":8000", nil)) }
Agora que já temos essa SUPER API, vamos iniciar nosso Dockerfile pelo stage de build. Para isso, aconselho utilizar a imagem oficial do golang como imagem base.
# stage de build FROM golang:1.19 AS build
Repare que logo após o nome e versão da imagem, criamos um alias para esse stage utilizando um AS build
.
Np próximo passo, vamos criar um WORKDIR e copiar todos os arquivos do projeto.
# stage de build FROM golang:1.19 AS build WORKDIR /app COPY . /app
Por último, vamos fazer o build da aplicação.
# stage de build FROM golang:1.19 AS build WORKDIR /app COPY . /app RUN CGO_ENABLED=0 GOOS=linux go build -o api main.go
Note que adicionamos as flags CGO_ENABLED=0
para desabilitar o CGO, e GOOS=linux
para que o resultado final seja um executável para linux.
Isso é necessário pois, como o Docker executa os containers utilizando parte da arquitetura do OS em que está rodando, caso você esteja utilizando Mac ou Windows e não passe a flag GOOS=linux
, a imagem não irá funcionar no próximo stage, onde vamos usar o linux scratch como imagem base.
E por falar em próximo stage, vamos iniciá-lo adicionando a imagem base mencionada e criar um WORKDIR.
# stage de build FROM golang:1.19 AS build WORKDIR /app COPY . /app RUN CGO_ENABLED=0 GOOS=linux go build -o api main.go # stage imagem final FROM scratch WORKDIR /app
Agora vem a parte mais importante. Copiar o binário do stage anterior para esse.
Para isso, vamos usar o comando COPY
em conjunto com a flag --from
, que serve para referenciar o local/stage onde buscar o arquivo.
# stage de build FROM golang:1.19 AS build WORKDIR /app COPY . /app RUN CGO_ENABLED=0 GOOS=linux go build -o api main.go # stage imagem final FROM scratch WORKDIR /app COPY --from=build /app/api ./
Para finalizar, vamos expor a porta 8000 e executar o binário que foi copiado.
# stage de build FROM golang:1.19 AS build WORKDIR /app COPY . /app RUN CGO_ENABLED=0 GOOS=linux go build -o api main.go # stage imagem final FROM scratch WORKDIR /app COPY --from=build /app/api ./ EXPOSE 8000 CMD [ "./api" ]
Agora é só fazer o build da image docker e utilizá-la.
Deixem suas dúvidas nos comentários.
Até a próxima!