Pour développer des microservices en Golang ou tous autres langages, je vous propose de partager mon expérience pour profiter d’une fonctionnalité introduite par les équipes de Docker dans la version 17.05 : le multistage build, cette fontion offre la possibilité dans un seul et même fichier Dockerfile d’avoir 2 phases, le BUILD et le RUN !
Pour illustrer le Docker multi-stage build, je vais utiliser un petit programme en Go, composé de 2 modules, qui affiche à l’écran du texte en couleur.
Code source de l’application Golang
L’application en Go est composée de 2 fichiers :
Elle fait appel à une bibliothèque sur Github.
Voici le début du fichier example.go :
import (
"fmt"
"github.com/raphamorim/go-rainbow"
. "github.com/user/app/frame"
)
Pour construire l’exécutable à partir des sources, dans mon Dockerfile, je place tous mes fichiers dans le répertoire github.com/user/app.
Dans un premier temps, je vais créer un fichier Dockerfile pour compiler cette petite application :
# Docker builder for Golang
FROM golang
LABEL maintainer "Vincent RABAH <vincent.rabah@gmail.com>"
WORKDIR /go/src/github.com/user/app
COPY . .
RUN set -x && \
go get -d -v . && \
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
Avec la commande je vais compiler l’application :
docker build -t itwars/gobuilder .
Maintenant comment récupérer mon binaire ? Comment l’inclure dans une image Docker ? Docker multistage build permet d’enchainer directement les différentes étapes, depuis un seul et même fichier Dockerfile. Dans ce nouveau Dockerfile, j’ai 2 définitions, une pour le BUILD, une pour le RUN. La première étape construit le binaire et s’appelle : builder . La seconde étape est construite depuis : scratch (la plus petite image possible) et dans cette étape à l’avant dernière ligne on copie l’application est copiée depuis builder.
# Docker builder for Golang
FROM golang as builder
LABEL maintainer "Vincent RABAH <vincent.rabah@gmail.com>"
WORKDIR /go/src/github.com/user/app
COPY . .
RUN set -x && \
go get -d -v . && \
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
# Docker run Golang app
FROM scratch
LABEL maintainer "Vincent RABAH <vincent.rabah@gmail.com>"
WORKDIR /root/
COPY --from=builder /go/src/github.com/user/app .
CMD ["./app"]
Pour construire l’image depuis ce nouveau Dockerfile, j’utilise la commande :
docker build -t itwars/mygo .
Une fois le création de l’image Docker terminée, on va regarder les images avec la commande :
docker image ls
Le résultat :
REPOSITORY TAG IMAGE ID CREATED SIZE
itwars/mygo latest 281dd82b86a8 38 seconds ago 2.01MB
<none> <none> 95a40189be5e 40 seconds ago 731MB
On constate 2 choses :
Maintenant le démarre mon container Docker :
docker run --rm itwars/mygo
Et voici le résultat :
Si vous avez des questions, laissez-moi un commentaire !