428 - Mejores prácticas con contenedores Docker

PodcastPodcast

428 - Mejores prácticas con contenedores Docker

Ultimamente ando haciendo imágenes Docker como si la vida me fuera en ello. Por esta razón he recopilado las mejores prácticas con contenedores Docker

1:25
-3:15

Aunque creo que ya te lo he mencionado anteriormente, lo cierto es que ando confabulando con Dani, de Daniel Primo. Estamos tramando algo. No se exactamente el que, porque los detalles, los maneja él en absoluto secreto, pero ahí andamos. Tampoco creas, que lo que hago es secreto, ni mucho menos, porque prácticamente todo queda en Internet, y en particular, todo lo que hago queda registrado perfectamente en GitHub, para que todo el mundo lo pueda aprovechar, si así lo considera. Sea, como fuere, lo cierto es que ando haciendo un servicio en Rust, y para utilizarlo con facilidad, lo estoy contenerizando… Creo que esto de contenerizar no está muy bien, pero, vaya, básicamente lo estoy metiendo en un contenedor, y no precisamente de barco, para poder desplegarlo en un VPS y así poder hacer pruebas tanto él como yo. Así, en estas últimas semanas he estado preocupándome de hacer los contenedores con cariño, y es de aquí precisamente de donde sale esta guía de mejores prácticas con contenedores Docker. Si bien, los contenedores los estoy haciendo para un servicio en Rust, lo cierto, es que esta guía la puedes aplicar a cualquier contenedor que hagas.

Mejores prácticas con contenedores Docker

Mejores prácticas con contenedores Docker

Inicialmente esta guía está pensada mas para la construcción de imágenes Docker, sin embargo, te recomiendo que la leas al completo aunque no hagas imágenes, y ya te digo que deberías, porque te puede ayudar en el uso de contenedores.

Versiona las imágenes

En general estamos muy acostumbrados a no poner etiqueta a las imágenes que utilizamos en nuestros contenedores, o bien a utilizar la etiqueta latest, que al fin y al cabo es lo mismo.

Sobre esto, ya te he hablado en alguna que otra ocasión, los problemas que me ha traído cuando he hecho actualizaciones con WatchTower.

Está bien tener tu imagen a la última pero hay que ser muy consciente de lo que estás haciendo y de los problemas que esto te puede traer.

Pero sobre todo, para la construcción de tus propios imágenes evita a toda costa utilizar esa etiqueta para el caso de la imagen base. Aquí es mas que fundamental, porque las dependencias de una versión, como bien sabes son distintas de las de otra versión.

Cuidado con el contenido sensible

Ni se te ocurra meter el contenido sensible dentro de tus imágenes. Y cuando hablo de contenido sensible no me refiero a fotografías tuyas en la playa, como ya te puedes imaginar. Básicamente me refiero a claves SSH, contraseñas certificados y cualquier otra información que no te gustaría encontrarte a lo largo y ancho de internet. Probablemente tampoco te gustaría esas fotografías.

Sobre todo, tienes que tener especial cuidado en el caso de que tus imágenes estén disponibles en un repositorio público.

En general utiliza utiliza variables de entorno, y en la medida de lo posible procura que estas variables de entorno estén cifradas.

Sin embargo, en el contenedor estarán disponibles, y se pueden ver. Tan sencillo como ejecutar esto,

docker inspect <nombre-del-contenedor>  --format='{{range .Config.Env}}{{println .}}{{end}}'

Con este comando obtendrás una bonita lista con todas las variables de entorno que estés utilizando en el contenedor. Así, que lo mejor es que tus contraseñas vayan cifradas, y en tu proceso, las descifres para hacer uso de ellas.

Utiliza un .dockerignore

Al igual que en Git tienes el .gitignore en el caso de Docker tienes el .dockerignore. Este archivo se utiliza para definir el contexto de construcción. Antes de evaluar los comandos COPY y ADD, el proyecto entero se envía a Docker, evita hacerlo para no volverte loco. Esto, me está siendo de especial interés en la compilación de los proyectos en Rust.

En un momento comenzaron a volverse algo imposible de gestionar, pero fue añadir el dockerignore y mano de santo.

Utiliza un linter

Gracias a Neovim, del cual como bien sabes, estoy completamente enamorado, tengo también un linter o analizador estático de código para, analizar mis Dockerfiles, y dejarlos limpitos y aseados.

Por supuesto que analizadores de código no solo hay para Neovim, no te preocupes. Yo lo he estado utilizando en PyCharm y otros fantásticos editores.

El mundo de las multietapas

Este mundo lo conocía, pero no lo había utilizado con la profusión con lo que lo estoy haciendo actualmente. Tanto con Python como con Rust, lo estoy haciendo ya de forma habitual.

Así, por ejemplo, en el caso de Rust en concreto, puedes utilizar una etapa preliminar para construir el ejecutable, y solo copias este en la etapa final ese ejecutable. De esta forma te quitas de encima todas las dependencias que aparecen en la construcción de la imagen.

Esto mismo lo estoy utilizando en Python, donde creo un entorno virtual, y luego solo tengo que copiar ese entorno virtual a la imagen final, olvidándome del resto.

Imágenes slim

Esta es otra de las características que me tienen totalmente obsesionado y la razón de que Alpine Linux se haya convertido en un compañero inseparable de aventuras. Actualmente utilizo la última versión de Alpine Linux, en concreto, en el momento de preparar el podcast es la 3.16 y solo añado aquellas dependencias que me hacen falta.

Por supuesto, respecto a las dependencias, decirte que, como indiqué al principio del podcast, las voy versionando, para evitar encontrarme en una versión con la que mi código no es compatible.

Cuantas menos capas mejor

Aquí es justo lo contrario de lo que sucede en el caso con la ropa. Yo prefiero llevar mas capas que menos, mas que nada, porque si hace frío voy preparado, pero si hace calor, no tengo que hacer nada mas que ir quitando capas. Si, en ocasiones, parece que vaya disfrazado, pero *¿y lo calentito que voy?.

En el caso de las imágenes no es nada bueno, porque las capas lo que hacen es aumentar el tamaño final de la imagen resultante por el cacheo. Puedes reducir el número de capas combinando. Esto lo puedes ver fácilmente en mis Dockerfile con los pasos que son RUN.

COPY mola mas que ADD

COPY y ADD no son exactamente iguales. El primero se utiliza para copiar imágenes locales, mientras con ADD puedes hacer operaciones mas ambiciosas como puede ser descargar archivos externos.

Un proceso un contenedor

Esto es algo que ya he comentado en mas de una ocasión. Lo mas interesante es utilizar un único proceso por cada contenedor. Si necesitas utilizar varios procesos simplemente tienes que combinarlos entre ellos en un docker-compose, por ejemplo.

Esto te da una serie de ventajas como,

  • creas contenedores reutilizables
  • Para realizar actualizaciones o parcheos de seguridad es algo relativamente sencillo, dado que solo tienes un proceso.
  • Puedes aumentar el número de procesos aumentando el número de contenedores si lo necesitas.

En general, prefiero tener tres contenedores coordinados con un docker-compose antes que uno. Si tengo que actualizar uno de ellos, simplemente, lo que tengo que hacer es descargarlo y levantarlo… y resuelto.


Espero que te haya gustado este nuevo episodio del podcast. Si puedes, te agradecería una valoración en iVoox y/o en Apple Podcast.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *