Hola a todos.
Tengo una instancia de Discourse bastante pequeña en funcionamiento (de hecho, lleva años funcionando sin apenas problemas): https://discuss.cubeisland.de/.
He estado utilizando el proceso de despliegue estándar basado en launcher en una máquina virtual dedicada (en mi propio hardware en un centro de datos). Lo único que he cambiado a lo largo de los años ha sido migrar a una base de datos PostgreSQL externa compartida.
Recientemente empecé a migrar aplicaciones desde máquinas virtuales dedicadas a un clúster Docker Swarm como paso preparatorio para eventualmente migrar a un clúster de Kubernetes, principalmente para ahorrar recursos y hacer que partes de la infraestructura sean más “elásticas”.
Hoy fue el día en que me enfoqué en esta pequeña instancia de Discourse, una de las pocas máquinas virtuales de aplicación dedicadas que quedaban. “Ya se está ejecutando en Docker, ¿qué tan difícil puede ser desplegarla en un clúster?”, pensé. Y según lo que leí, en realidad podría serlo. Solo tendría que tomar la imagen de la instancia actualmente en ejecución, subirla a nuestro registro interno y ejecutarla en el clúster, y todo funcionaría perfectamente, lo cual es genial.
Revisé los archivos de launcher, especialmente las plantillas y ejemplos, y pensé que probablemente sería una buena idea tener Redis separado en este tipo de despliegue, y quizás podría configurar un trabajo de CI para construir nuevas imágenes cuando añada plugins o quiera actualizar. Así que descargué discourse_docker localmente, copié mi definición de contenedor app.yml existente al clon e intenté ejecutar ./launcher bootstrap app para construir una imagen que luego podría subir a mi registro, sin desplegarla inmediatamente.
Para mi sorpresa, el script intentó conectarse al servidor PostgreSQL de “producción” para migrar la base de datos, lo cual, afortunadamente, no pudo hacer desde mi estación de trabajo local.
Miré alrededor aquí y aparentemente así es como funciona esto, lo que me hace preguntarme:
- ¿Cómo se construiría un contenedor para una nueva instancia, donde aún no tengo base de datos? ¿Necesitaría configurar la base de datos de producción antes de poder construir la imagen?
- Asumo que db:migrate se ejecuta solo una vez, así que si tengo varias instancias similares (por ejemplo, producción y pruebas), tendría que actualizar una de las instancias para construir la nueva imagen y luego no podría usar la misma imagen para la segunda instancia, aunque la imagen sería idéntica.
- ¿Cómo procedería para construir imágenes para instancias donde el servidor de base de datos no es accesible desde el sistema que construye la imagen (lo cual no debería ser tan poco común)?
Después de leer varios posts (obviamente incluyendo este), soy perfectamente consciente de las razones del proceso de construcción tal como está ahora y veo el valor que tiene para el 99% de las personas que despliegan Discourse de manera casual en su máquina virtual estándar completa. Y estoy muy acostumbrado a los modelos de contenedores “todo en uno” y no me opongo a ello. Después de todo, el valor clave de Docker radica en el hecho de que el proveedor de software puede preconfigurar configuraciones altamente optimizadas y empaquetarlas en un entorno de ejecución reproducible, eliminando la necesidad de mucho conocimiento muy específico de la aplicación por parte del equipo de operaciones. Así que estoy totalmente de acuerdo con usar las herramientas que proporcionan, ¿por qué esperaría que alguien más construya contenedores mejores que el propio proveedor del software? ¿Por qué querría separar nginx y la aplicación Ruby cuando no hay ningún beneficio que obtener, solo para hacer el despliegue más “puro” (lo que quiera que eso signifique…)?
Sin embargo, es extraño ver un contenedor que modifica el estado en tiempo de ejecución cuando ni siquiera está cerca de ejecutarse. Ya ejecuto bastantes aplicaciones en contenedores y he contenedorizado varias yo mismo, algunas de las cuales nunca estuvieron pensadas para ejecutarse en contenedores.
El ejemplo principal que me viene a la mente, de una aplicación que trata requisitos/problemas similares de manera parecida a Discourse, es GitLab. Aunque ahora ofrecen un elegante gráfico Helm para un despliegue completamente descompuesto de Kubernetes “cómo debería ser”, supongo (sin mirar ningún número) que un 99% similar de sus despliegues de tamaño pequeño-mediano están utilizando la imagen Docker omnibus de GitLab (o el paquete OS, que es prácticamente lo mismo). Tienen un proceso de arranque similar, pero basado en Chef dentro del contenedor, que se ejecuta en cada inicio y realiza las tareas habituales como migraciones de base de datos y compilación de activos.
Sí, el inicio de GitLab puede tardar varios minutos debido a esto, pero nunca ha sido un problema en los despliegues que he visto (algunos en empresas más grandes). Especialmente con sistemas modernos de orquestación como Docker Swarm y Kubernetes y lo que sea, que pueden ejecutar actualizaciones rodantes por ti, donde la instancia antigua se apaga solo si la nueva instancia está en ejecución y ha pasado con éxito las verificaciones de salud y lista, un proceso de despliegue largo podría no ser realmente un problema. Pero incluso sin actualizaciones rodantes sofisticadas, que pueden o no funcionar, también puedes tolerar bastante tiempo de inactividad en muchas situaciones.
Entonces: ¿Es posible configurar launcher para omitir las operaciones dependientes de la base de datos durante la construcción de la imagen y realizar estas operaciones en su lugar durante el inicio del contenedor?
Estoy definitivamente dispuesto a invertir algo de tiempo yo mismo, pero mi tiempo por la noche es limitado, así que cualquier orientación sería muy bienvenida.
También estoy abierto a procesos completamente diferentes si crees que esto es estúpido o ni siquiera posible, etc.
¡Gracias por cualquier comentario!