Docker, por que eu prefiro Alpine como base em vez do Ubuntu

Há alguns meses, comecei todos os Dockerfile com esta linha:

FROM ubuntu:xx.xx

onde xx.xxestá a versão mais recente do LTS. OK, fixe. Depois de usar o Docker, percebi que o tamanho e o tempo importam. Comecei a buscar uma nova imagem de base que se adequasse às minhas necessidades e menor (construção mais rápida). Encontrei Alpine. É incrivel.

Aqui está um Dockerfile baseado no ubuntu para executar meu projeto Go de amostra:

FROM ubuntu

MAINTAINER
Balazs Nadasdi <yitsushi@cheppers.com>

# Update package index and install go + git
RUN apt
-get update -q
&& apt-get install -yq golang git-core

# Set up GOPATH
RUN mkdir
/go
ENV GOPATH
/go

# Get dependencies
RUN go
get gopkg.in/mgo.v2 &&
go
get github.com/go-martini/martini &&
go
get gopkg.in/redis.v3

# Add current working directory
ADD
. /go/src/github.com/Yitsushi/livetogether

# Build it :)
RUN go install github
.com/Yitsushi/livetogether

# Every time I start the container I want to rebuild
# because I mount it when I use it for development
ENTRYPOINT go install github
.com/Yitsushi/livetogether &&
/go/bin/livetogether --config=/go/src/github.com/Yitsushi/livetogether/config.json

# Expose where the application wants to listen
EXPOSE
8080

E agora veja na Alpine:

FROM alpine

MAINTAINER
Balazs Nadasdi <yitsushi@cheppers.com>

# Update package index and install go + git
RUN apk
add --update go git

# Set up GOPATH
RUN mkdir
/go
ENV GOPATH
/go

# Get dependencies
RUN go
get gopkg.in/mgo.v2 &&
go
get github.com/go-martini/martini &&
go
get gopkg.in/redis.v3

# Add current working directory
ADD
. /go/src/github.com/Yitsushi/livetogether

# Build it :)
RUN go install github
.com/Yitsushi/livetogether

# Every time I start the container I want to rebuild
# because I mount it when I use it for development
ENTRYPOINT go install github
.com/Yitsushi/livetogether &&
/go/bin/livetogether --config=/go/src/github.com/Yitsushi/livetogether/config.json

# Expose where the application wants to listen
EXPOSE
8080

E agora veja nossas imagens de base:

 docker images | awk '{print $1"t"$2"t"$7" "$8}'
REPOSITORY TAG SIZE

ubuntu latest
187.9 MB
redis latest
109.3 MB
mongo latest
261.6 MB
golang latest
709.5 MB
alpine latest
5.249 MB

Tempo de construção?

 time docker build -t sample_ubuntu livetogetheru/
...
docker build
-t sample_ubuntu livetogetheru 0.17s user 0.03s system 0% cpu 6:22.66 total
time docker build -t sample_alpine livetogether/
...
docker build
-t sample_alpine livetogether 0.15s user 0.01s system 0% cpu 2:09.89 total

o ponto:

ubuntu: 6:22.66 total
alpine
: 2:09.89 total

Nossa … e depois da construção?

 docker images | awk '{print $1"t"$2"t"$7" "$8}'
REPOSITORY TAG SIZE

sample_alpine latest
167.6 MB
sample_ubuntu latest
447.8 MB
<none> <none> 187.9 MB
ubuntu latest
187.9 MB
redis latest
109.3 MB
mongo latest
261.6 MB
golang latest
709.5 MB
alpine latest
5.249 MB

O que? 3 vezes mais tempo para construir e 4 vezes maior o tamanho da imagem do aplicativo e mais de 30 vezes maior a imagem base ? AMD!

como você vê, não use a imagem golang básica porque é muito maior e você não precisa dela