Una lista de verificación de 10 pasos sobre cómo dockerizar cualquier aplicación.
Ya hay muchos tutoriales sobre cómo dockerizar aplicaciones disponibles en Internet, entonces, ¿por qué estoy escribiendo otro ?
La mayoría de los tutoriales que veo se centran en una tecnología específica (por ejemplo, Java o Python) que puede no cubrir lo que necesita. Tampoco abordan todos los aspectos relevantes que son necesarios para establecer un contrato bien definido entre los equipos Dev y Ops (que es de lo que se trata la contenedorización ).
Compilé los pasos a continuación en base a mis experiencias recientes y las lecciones aprendidas . Es una lista de verificación de detalles y cosas que las otras guías pasan por alto.
Descargo de responsabilidad: Esta NO es una guía para principiantes. Le recomiendo que aprenda los conceptos básicos de cómo configurar y usar la ventana acoplable al principio, y vuelva aquí después de haber creado y lanzado algunos contenedores.
Empecemos.
Hay muchas imágenes base específicas de la tecnología , como:
Si ninguno de ellos funciona para usted, debe comenzar desde un sistema operativo base e instalar todo usted mismo.
La mayoría de los tutoriales que existen comenzarán con Ubuntu (por ejemplo, ubuntu: 16.04), lo cual no es necesariamente incorrecto.
Mi consejo es que consideres usar imágenes de Alpine :
https://hub.docker.com/_/alpine/
Proporcionan una imagen base mucho más pequeña (tan pequeña como 5 MB).
Nota: los comandos "apt-get" no funcionarán en esas imágenes. Alpine utiliza su propia herramienta y repositorio de paquetes. Para más detalles ver:
https://wiki.alpinelinux.org/wiki/Alpine_Linux_package_management
https://pkgs.alpinelinux.org/packages
Esto suele ser trivial. Algunos detalles que te pueden faltar:
a-) Debe escribir apt-get update y apt-get install en la misma línea (lo mismo si está usando apk en Alpine). Esta no es solo una práctica común, debe hacerlo , de lo contrario, la imagen temporal (capa) "apt-get update" se puede almacenar en caché y es posible que no actualice la información del paquete que necesita inmediatamente después (consulte esta discusión https://forums .docker.com/t/dockerfile-run-apt-get-install-all-packages-at-once-or-one-by-one/17191 ).
b-) Vuelva a verificar si está instalando SOLO lo que realmente necesita (suponiendo que ejecutará el contenedor en producción). He visto gente instalando vim y otras herramientas de desarrollo dentro de sus imágenes.
Si es necesario, cree un Dockerfile diferente para el tiempo de compilación/depuración/desarrollo. No se trata solo del tamaño de la imagen, piense en la seguridad, la mantenibilidad, etc.
Algunos consejos para mejorar sus Dockerfiles:
a-) Comprender la diferencia entre COPIAR y AÑADIR:
https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#add-or-copy
b-) (Intente) Seguir las convenciones del sistema de archivos sobre dónde colocar sus archivos:
http://www.nombrederuta.com/fhs/
Por ejemplo, para aplicaciones interpretadas (PHP, Python), utilice la carpeta /usr/src .
c-) Verifique los atributos de los archivos que está agregando. Si necesita permiso de ejecución, no es necesario agregar una nueva capa en su imagen (EJECUTAR chmod +x …). Simplemente corrija los atributos originales en su repositorio de código.
No hay excusa para eso, incluso si está usando Windows, consulte:
¿Cómo crear permisos de modo de ejecución de archivos en Git en Windows? _No es necesario hacer esto en dos confirmaciones, puede agregar el archivo y marcarlo como ejecutable en una sola confirmación..._stackoverflow.com
Primero, tómate un descanso y lee el siguiente gran artículo:
Comprender cómo funcionan uid y gid en contenedores Docker _Comprender cómo los nombres de usuario, los nombres de grupo, las identificaciones de usuario (uid) y las identificaciones de grupo (gid) se asignan entre los procesos que se ejecutan dentro de un…_medium.com
Después de leer esto entenderás que:
a-) Solo necesita ejecutar su contenedor con un usuario específico (ID fijo) si su aplicación necesita acceso a las tablas de usuarios o grupos ( /etc/passwd o /etc/group ).
b-) Evite ejecutar su contenedor como root tanto como sea posible.
Desafortunadamente, no es difícil encontrar aplicaciones populares que requieran ejecutarlas con identificadores específicos (por ejemplo, Elastic Search con uid:gid = 1000:1000).
Intenta no ser uno más...
Este suele ser un proceso muy trivial, por favor, simplemente no cree la necesidad de que su contenedor se ejecute como root porque quiere que exponga un puerto bajo privilegiado (80). Simplemente exponga un puerto no privilegiado (por ejemplo, 8080) y mapéelo durante la ejecución del contenedor.
Esta diferenciación viene de mucho tiempo atrás:
https://www.w3.org/Daemon/User/Installation/PrivilegedPorts.html
La forma estándar: simplemente ejecute su archivo ejecutable de inmediato.
Una mejor manera: cree un script " docker-entrypoint.sh " donde pueda enlazar cosas como la configuración usando variables de entorno (más sobre esto a continuación):
Esta es una práctica muy común, algunos ejemplos:
elastic/elasticsearch-docker _elasticsearch-docker - Docker oficial de Elasticsearch image_github.com
docker-library/postgres _postgres - Paquete de imagen oficial de Docker para Postgres_github.com
Cada aplicación requiere algún tipo de parametrización. Básicamente hay dos caminos que puedes seguir:
1-) Use un archivo de configuración específico de la aplicación: necesitará documentar el formato, los campos, la ubicación, etc. (no es bueno si tiene un entorno complejo, con aplicaciones que abarcan diferentes tecnologías).
2-) Uso (sistema operativo) Variables de entorno: Simple y eficiente.
Si cree que este no es un enfoque moderno o recomendado, recuerde que esto es parte de Los Doce Factores :
La aplicación Twelve-Factor _Una metodología para crear aplicaciones de software como servicio modernas, escalables y mantenibles._12factor.net
Esto no significa que deba desechar sus archivos de configuración y refactorizar el mecanismo de configuración de su aplicación.
Simplemente use un comando envsubst simple para reemplazar una plantilla de configuración (dentro de docker-entrypoint.sh , porque debe realizarse en tiempo de ejecución).
Ejemplo:
nginx _Edición oficial de Nginx. Repositorio de GitHub: https://github.com/nginxinc/docker-nginx Referencia de la biblioteca Este contenido es…_docs.docker.com
Esto encapsulará el archivo de configuración específico de la aplicación, el diseño y los detalles dentro del contenedor.
La regla de oro es: no guardes ningún dato persistente dentro del contenedor .
El sistema de archivos contenedor se supone y está destinado a ser temporal, efímero. Por lo tanto, cualquier contenido generado por el usuario, archivos de datos, salida del proceso debe guardarse en un volumen montado o en un montaje de enlace (es decir, en una carpeta en el sistema operativo base vinculado dentro del contenedor).
Sinceramente, no tengo mucha experiencia en volúmenes montados, siempre he preferido guardar los datos en un enlace de montajes , utilizando una carpeta previamente creada y definida cuidadosamente con una herramienta de gestión de configuración (como Salt Stack).
Como cuidadosamente creado , me refiero a lo siguiente:
Soy consciente de que mis " datos persistentes " anteriores están lejos de ser una definición precisa, y los registros a veces caen en el área gris. ¿Cómo debes manejarlos?
Si está creando una nueva aplicación y desea que se ciña a las convenciones de la ventana acoplable , no debe escribir ningún archivo de registro. La aplicación debe usar stdout y stderr como un flujo de eventos . Al igual que la recomendación de variables de entorno, también es uno de los doce factores . Ver:
La aplicación Twelve-Factor _Una metodología para crear aplicaciones de software como servicio modernas, escalables y mantenibles._12factor.net
Docker capturará automáticamente todo lo que envíe a la salida estándar y lo pondrá a disposición a través del comando " docker logs ":
https://docs.docker.com/engine/reference/commandline/logs/
Sin embargo, hay algunos casos prácticos en los que esto es particularmente difícil. Si está ejecutando un contenedor nginx simple, tendrá al menos dos tipos diferentes de archivos de registro:
Con diferentes estructuras, configuraciones e implementaciones preexistentes, puede que no sea trivial canalizarlas en la salida estándar.
En este caso, simplemente manipule los archivos de registro como se describe en la sección anterior y asegúrese de rotarlos.
Si su aplicación escribe archivos de registro o agrega archivos que pueden crecer indefinidamente , debe preocuparse por la rotación de archivos.
Esto es fundamental para evitar que el servidor se quede sin espacio , aplicar políticas de retención de datos (que es fundamental cuando se trata de GDPR y otras regulaciones de datos).
Si está utilizando montajes de enlace , puede contar con la ayuda del sistema operativo base y usar las mismas herramientas que usaría para una configuración de rotación local, es decir, logrotate (manual aquí ).
Un ejemplo simple pero completo que encontré recientemente es este:
Configurar - Rotación de registros _Gestione las rotaciones de registros mediante la herramienta de Linux, logrotate, con la base de datos NoSQL en memoria de Aerospike._www.aerospike.com
Otro bueno:
Cómo administrar archivos de registro con Logrotate en Ubuntu 16.04 | DigitalOcean _Logrotate es una utilidad del sistema que administra la rotación y compresión automáticas de los archivos de registro. Si los archivos de registro no fueran…_www.digitalocean.com
—
Avíseme si tiene algún comentario. Consulte mis otros artículos técnicos en https://hackernoon.com/@htssouza