Imágenes Docker Sin Sistema

Docker

*Docker*

Una de las buenas prácticas a la hora de crear imágenes en Docker es hacer que estas sean lo más pequeñsa, en tamaño, posible.

Por popularidad, Alpine es la distribuciión Linux preferida a la hora de crear imágenes de tamaño reducido (poco menos de 5MB), a menos que, por requerimientos de certificacion o algún otro motivo, sea necesario usar alguna distribución certificada en particular, algo común en el entorno empresarial y gubernamental.

El proyecto Google Container Tools aloja una serie de imágenes Docker orientadas a ciertos lenguajes de programación sin sistema, es decir, no tienen ninguna distribución dentro, todo lo que contienen las imágenes son los ficheros necesarios (intérpretes) para ejecutar dicha aplicación, no contiene ni siquiera una shell. Los lenguajes de programación para los que dispones de dichas imágenes son:

  • Java
  • Python 2.7 / 3
  • Go
  • Node.js
  • .Net

Para ver alguna de las diferencias entre estas imágenes y las oficiales de cada plataforma basdas en Alpine, podemos ejecutar los siguientes commandos:

Imagen con Python 3:

docker pull gcr.io/distroless/python3
...

docker pull python:alpine
...

docker image ls
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
python                         alpine              a5f497d596f5        2 weeks ago         79.4MB
gcr.io/distroless/python3      latest              22491e3c6cda        48 years ago        50.4MB

Casi 30 MB de diferencia.

En cuanto a Java:

docker pull gcr.io/distroless/java
...

docker pull java:alpine
...

docker image ls
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
java                           alpine              3fd9dd82815c        17 months ago       145MB
gcr.io/distroless/java         latest              d53055d7a4da        48 years ago        118MB

Unos 27MB de diferencia.

Como se puede ver la diferencia no es enorme, pero sí considerable. Esto no sólo nos ahorra espacio en disco y tráfico de red, sino que también mejora la seguridad. El hecho de no tener librerías o servicios que no necesitemos, reducimos riesgos de seguridad y alertas innecesarias de escaneadores de imágenes por versiones obsoletas o vulnerables.

Las imágenes disponibles actualmente son:

  • gcr.io/distroless/python2.7
  • gcr.io/distroless/python3
  • gcr.io/distroless/nodejs
  • gcr.io/distroless/java
  • gcr.io/distroless/java/jetty
  • gcr.io/distroless/cc (contiene una versión mínima de glibc para lenguajes estáticamente compilados como D o Rust)
  • gcr.io/distroless/dotnet

El hecho que de estas imágenes no contengan una shell no es de gran importancia, a menos que por algún motivo necesitemos saltar dentro del contenedor para depurar o inspeccionar alguna cosa. Para ello, existen las mismas imágenes con la etiqueta debug, la cual incluye busybox. Evidentemente será un poco más grande.

Por ejemplo, si necesitamos depurar un contenedor basado en una aplicación en Java, podemos usar la imagen gcr.io/distroless/java:debug, y una tengamos el contenedor creado, podríamos saltar dentro sobre escribiendo el punto de entrada. Veamos un ejemplo:

docker run -it --rm --entrypoint sh gcr.io/distroless/java:debug
...
/ # ls
busybox  dev      etc      home     lib      lib64    proc     sys      tmp      usr      var
/ #

Para terminar un último apunte, como hemos dicho las imágenes, por defecto, no contienen una shell por lo que CMD o ENTRYPOINT deben ser expresados en modo vector: ENTRYPOINT [‘myapp’].

Para saber más sobre las distintas formas de expresar los comandos que definen una imagen como ENTRYPOINT, CMD, etc, o sobre Docker en general, este recurso es genial! :)