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.