Skip to main content

3.2 Publicando

De nada sirve crear una imagen de Docker si no la distribuimos por el mundo. Así que sigamos el proverbio friki de Obijuan y demos el paso

Más vale proyecto publicado con licencia libre, que ciento en el cajón Juan Gonzalez (Obijuan)

3.2.1 Tags

Nuestras imágenes deben ir correctamente versionadas para permitir que otras personas o nosotros mismos podamos consumirlas con ciertas garantías de inmutabilidad.

En el capítulo 2.2.1 remarcaba lo importante que es hacer un uso correcto de los tags como uno de los factores decisivos a la hora de usar una imagen. Como individuos que publicamos imágenes tenemos la responsabilidad de usar tags de una forma coherente ya sea con el uso del versionamiento semántico u otra metodología.

Además tendremos que tomar una decisión sobre el polémico / mal entendido uso del tag latest, ya que en ocasiones podemos tener resultados inesperados que podrían generar frustración en los usuarios, sobre todo a la hora de hacer un buen triage en el soporte. En general, cuanto más empujemos como colectivo hacía la inmutabilidad, más sencillo será la gestión de incidencias posteriormente.

3.2.2 Firmando imágenes

Como vimos en el capítulo 2.2.1 es importante que usemos imágenes que estén firmadas. El proceso de firmado de las imágenes es complejo y ha requerido mucho trabajo por parte del equipo de Docker y la comunidad.

A efectos prácticos tenemos dos vertientes que cubrir cuando queremos trabajar con imágenes firmadas. Por un lado queremos consumir imágenes que estén firmadas (dentro de lo posible) y por otro queremos firmar nuestras imágenes. Combinando ambos reducimos enormemente los riesgos de ataque man in the middle y similares.

Consumir imágenes firmadas

Como usuarios podemos hacer uso de la variable de entorno DOCKER_CONTENT_TRUST=1 para forzar que todas las imágenes que usemos estén firmadas o no serán descargadas del registro.

Por defecto esta variable estaría desactivada DOCKER_CONTENT_TRUST=0 por lo que sería nuestra responsabilidad asegurarnos que dejamos el valor habilitado, especialmente en las máquinas que destinamos a producción.

Publicar imágenes firmadas

Como cualquier sistema basado en encriptación asimétrica uno de los primeros pasos será crearnos unas llaves que nos permita firmar.

Lo primero será identificarnos contra el servidor de Docker Hub

docker login

En este caso, crearé una llave con nombre personal-laptop-1 para ayudarme a identificarla cuanto tenga más llaves.

docker trust key generate personal-laptop-1

Ahora indicaremos a Docker que queremos que esa llave personal-laptop-1 pueda firmar la imagen ulisesgascon/signed-hello-world

docker trust signer add --key dev1.pub personal-laptop-1 ulisesgascon/signed-hello-world

Desde este momento ya podremos firmar con esa llave ejecutando el siguiente comando (previamente debemos hacer la build con el tag correspondiente)

docker trust sign ulisesgascon/signed-hello-world:latest

Podemos inspeccionar la imagen en detalle de la siguiente forma:

docker trust inspect --pretty ulisesgascon/signed-hello-world:latest

Ya estaríamos listos para publicar la imagen como hacemos habitualmente. Podemos crear múltiples llaves, incluso podemos crear llaves para otras personas que colaboren con nosotros o máquinas.

Recuerda que siempre que uses llaves para firmar deberás guardar una copia de seguridad de las llaves.

3.2.3 Registros

Una vez tenemos nuestra imagen construida debemos hacerla accesible en alguna entidad que actúe como registro, donde podamos publicar, descargar y actualizar esas imágenes ya sea abierto al público o de carácter privado para una organización o grupo de recursos específico.

Con el auge de la nube pública, es común encontrar multitud de alternativas a Docker Hub. Incluso podemos auto-hostearnos nuestro propio registro con Registry

Independientemente de la solución que utilicemos, deberemos garantizar antes de publicar que el acceso a la imagen es el esperado y no debemos hacer públicas imágenes que deben ser privadas.

A su vez es importante seguir las recomendaciones generales en el uso de servicios de terceros como usar 2FA o rotar las contraseñas de forma frecuente, etc.

Esto es especialmente relevante si estás manteniendo imágenes populares que usan muchas personas, ya que en ocasiones las personas que mantienen esas librerías son objetivo de ataques como individuos por parte de agentes maliciosos que intentan publicar imágenes o librerías envenenadas en su nombre como ya pasó en 2018 cuando uno de los paquetes más populares de NPM (ecosistema de Node.js) fue corrompido

consejo

Una forma de mitigar este último escenario, es hacer uso de la firma de imágenes como vimos en el capítulo 3.2.2 y en el caso de utilizar tokens estos deberán ser correctamente custodiados y rotados de forma frecuente.

3.2.4 Dockerignore

Cuando usamos el comando COPY o ADD corremos el riesgo de copiar de manera recursiva ficheros sensibles. Por eso es importante mantener un fichero .dockerignore actualizado.

El comportamiento del fichero .dockerignore es muy similar al de .gitignore, por lo que resulta sencillo su uso.

Por ejemplo, para un proyecto de Node podríamos incluir logs, node_modules, referencias a ficheros .env, etc..

# Node
# Logs

logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Dependency directories
node_modules/

# Secrets
.env
.env.*