Pour réduire la taille d’un container Docker, on peut créer l’image en partant de rien, ou plus précisément, en partant de “scratch”, qui ne contient rien. On obtient à la fin un container beaucoup plus léger que si l’on partait de Debian, ou pire, d’Ubuntu.
Afin de mettre un binaire Go à l’intérieur, quelques précautions sont nécessaires. Nous verrons rapidement comment faire. Mais si vous voulez avoir plus d’infos, vous pouvez consulter la page en anglais de Codeship : Building Minimal Docker Containers For Go Applications
Compiler statiquement votre programme Go :
CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -a -installsuffix cgo -o server
Votre fichier Dockerfile doit ressembler à ça :
FROM scratch
ADD static /static
ADD server /server
CMD /server
Mais si vous avez besoin d’une fonctionnalité de téléversement (upload), cela ne va pas marcher. Le téléversement a besoin d’un dossier temporaire pour traiter les gros fichiers envoyés depuis un formulaire multipart.
Regardons directement dans le code du package Go os.file_unix :
// TempDir returns the default directory to use for temporary files.
func TempDir() string {
dir := Getenv("TMPDIR")
if dir == "" {
if runtime.GOOS == "android" {
dir = "/data/local/tmp"
} else {
dir = "/tmp"
}
}
return dir
}
Comme on est sous Linux, on voit que le dossier temporaire se trouve dans /tmp.
Oui mais notre container, qu’on a construit à partir de scratch, ne contient pas de dossier /tmp. D’où plantage du téléversement :-(
C’était un bug difficile à trouver, mais la solution est simple. Modifions notre fichier Dockerfile pour ajouter une entrée :
FROM scratch
VOLUME /tmp
ADD static /static
ADD server /server
Maintenant on peut lier notre container avec un dossier qui servira de dossier temporaire comme suit :
docker run -P -v /tmp:/tmp your_image
Et voilà ! Une image Docker minimale, avec un binaire Go dedans et rien d’autre.