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 :
1CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -a -installsuffix cgo -o server
Votre fichier Dockerfile doit ressembler à ça :
1FROM scratch
2ADD static /static
3ADD server /server
4CMD /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 :
1// TempDir returns the default directory to use for temporary files.
2func TempDir() string {
3 dir := Getenv("TMPDIR")
4 if dir == "" {
5 if runtime.GOOS == "android" {
6 dir = "/data/local/tmp"
7 } else {
8 dir = "/tmp"
9 }
10 }
11 return dir
12}
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 :
1FROM scratch
2VOLUME /tmp
3ADD static /static
4ADD server /server
Maintenant on peut lier notre container avec un dossier qui servira de dossier temporaire comme suit :
1docker run -P -v /tmp:/tmp your_image
Et voilà ! Une image Docker minimale, avec un binaire Go dedans et rien d’autre.