¡Hola a todos!
Realmente quiero comenzar de inmediato con el tema, pero es correcto contar un poco sobre mi historia:
Introducción
Soy programador con experiencia en el desarrollo de aplicaciones de una sola página frontend, scala/java y nodejs en el servidor.
Durante bastante tiempo (ya son un par — tres años), he mantenido la opinión de que Docker es un regalo del cielo y en general una herramienta muy genial que absolutamente todo desarrollador debería saber utilizar. Y de aquí se desprende que cada desarrollador debería tener Docker en su máquina local. No solo es mi opinión, pueden revisar las ofertas de trabajo que se publican en hh. En cada segunda hay una mención a Docker y si lo dominan, será su ventaja competitiva 😉
En mi camino, me he encontrado con muchas personas, cada una con su diferente actitud hacia Docker y su ecosistema. Algunos decían que es una herramienta conveniente que garantiza la multiplataforma. Otros no entendían por qué deberían ejecutarse en contenedores y qué beneficio obtenían de ello, a otros simplemente no les importaba y no se complicaban (solo escribían código y se iban a casa — envidio, por cierto, a esas personas 🙂)
Razones para usar
¿Por qué utilicé Docker? Probablemente por las siguientes razones:
- lanzar bases de datos, el 99% de las aplicaciones las utilizan
- lanzar nginx para servir el frontend y hacer proxy al backend
- puedes empaquetar la aplicación en una imagen de Docker, de esta manera mi aplicación funcionará en cualquier lugar donde haya Docker, el problema de la distribución se resuelve de inmediato
- descubrimiento de servicios desde el principio, puedes crear microservicios, cada contenedor (conectado a una red común) puede acceder fácilmente a otro por alias, es muy conveniente
- es divertido crear un contenedor y 'jugar' con él.
Lo que siempre NO me ha gustado de Docker:
- para que mi aplicación funcione, Docker necesita estar en el servidor. ¿Y para qué necesito esto, si mis aplicaciones funcionan en jre o en nodejs y su entorno ya está en el servidor?
- si quiero ejecutar mi imagen (privada) creada localmente en un servidor remoto, necesito mi propio repositorio de Docker, y también necesito que haya un registro funcionando en algún lugar y hay que configurar https porque Docker cli solo funciona a través de https. Oh, maldita sea... hay opciones, claro, guardar la imagen localmente a través de
docker savey a través de scp simplemente enviar la imagen... Pero son tantos movimientos. Además, se ve como una solución 'provisoria' hasta que haya un repositorio propio. docker-composeSolo se necesita para iniciar contenedores. Y eso es todo. No puede hacer nada más.Docker-composetiene un montón de versiones de sus archivos, su propia sintaxis. Por muy declarativa que sea, no quiero leer su documentación. No la necesitaré en ningún otro lugar.- en el trabajo en equipo, la mayoría de las personas escriben Dockerfile de manera muy deficiente, no entienden cómo se cachea, añaden a la imagen todo lo que necesitan y lo que no, heredan de imágenes que no están en dockerhub o en un repositorio privado, crean algunos
docker-composearchivos con bases de datos y no persisten nada. A pesar de ello, los desarrolladores afirman con orgullo que Docker es genial, que todo funciona localmente y a los reclutadores les importa tanto que escriben en sus ofertas: “Usamos Docker y necesitamos un candidato con esta experiencia” - siempre tienen la idea de levantar en Docker todo y cualquier cosa: postgresql, kafka, redis. Es una lástima que no todo funcione en contenedores, no todo se puede configurar y lanzar fácilmente. Esto es soportado por desarrolladores externos y no por los propios proveedores. Y, por cierto, surge inmediatamente la pregunta, si los proveedores no se preocupan por mantener sus productos en Docker, ¿por qué será, quizás saben algo?
- siempre surge la pregunta sobre la persistencia de datos del contenedor. Y aquí te preguntas, ¿debería simplemente montar un directorio del host o crear un volumen de Docker o hacer un contenedor de datos que ahora
está obsoleto? Если я монтирую директорию то мне нужно убедиться что uid и gid пользователя в контейнере соответствует id пользователя запустившего контейнер, иначе файлы созданные контейнером будут созданы с правами владельца root. Если используюvolumenlos datos simplemente se crearán en algún/usr/*y será la misma historia con uid y gid como en el primer caso. Si inicias un componente externo, debes leer la documentación y buscar la respuesta a la pregunta: “¿En qué directorios del contenedor escribe archivos el componente?”
Siempre me ha molestado que tengo que lidiar tanto tiempo con Docker en la etapa inicial: pensaba en cómo ejecutar contenedores, de qué imágenes iniciar, hacía Makefile que contenía alias a largos comandos de Docker. No soportaba Docker-compose, porque no quería aprender otro instrumento del ecosistema Docker. Y docker-compose up me estresaba, especialmente si allí se presentaban build estructuras en lugar de imágenes ya compiladas. Todo lo que realmente quería era hacer el producto de manera eficaz y rápida. Pero no podía desglosar el uso de Docker.
Introducción a Ansible
Recientemente (hace tres meses), trabajé con un equipo de DevOps, casi cada miembro de este equipo tenía una opinión negativa sobre Docker. Por las razones:
- Docker controla iptables (aunque se puede desactivar en daemon.json)
- No vamos a ejecutar Docker en producción
- Si el daemon de Docker falla, todos los contenedores de infraestructura también fallan
- No hay necesidad de Docker
- ¿Para qué Docker si tenemos Ansible y máquinas virtuales?
En mi trabajo también conocí otra herramienta: Ansible. Había oído hablar de ella, pero nunca había probado a escribir mis propios playbooks. Ahora empecé a escribir mis tareas y mi perspectiva cambió por completo. Porque entendí: Ansible tiene módulos para ejecutar contenedores Docker, construir imágenes, redes, etcétera, y se pueden ejecutar contenedores no solo localmente, sino también en servidores remotos. ¡Mi alegría no tenía límites! Encontré una herramienta SOLVENTE y deseché mis archivos Makefile y docker-compose, que fueron reemplazados por tareas YAML. El código se redujo gracias al uso de construcciones como loop, when, etc.
Docker se utiliza para ejecutar componentes externos como bases de datos
Recientemente conocí los túneles SSH. Resulta que es muy sencillo "redirigir" un puerto de un servidor remoto a un puerto local. El servidor remoto puede ser una máquina en la nube o una máquina virtual ejecutándose en VirtualBox. Si yo o mi colega necesitamos una base de datos (o algún otro componente externo), simplemente podemos iniciar un servidor con ese componente y detenerlo cuando no se necesite. La redirección de puertos proporciona el mismo efecto que una base de datos ejecutándose en un contenedor Docker.
Este comando redirige mi puerto local al servidor remoto con PostgreSQL:
ssh -L 9000:localhost:5432 user@example.com
Usar un servidor remoto resuelve el problema del desarrollo en equipo. Varios desarrolladores pueden usar ese servidor al mismo tiempo, no necesitan saber cómo configurar PostgreSQL, lidiar con Docker y otras complicaciones. En el servidor remoto, se puede instalar la misma base de datos en Docker, si se necesita una versión específica. Lo único que requerirán los desarrolladores es acceso SSH.
Recientemente leí que los túneles SSH son una funcionalidad limitada de una VPN convencional. Se puede configurar fácilmente OpenVPN u otras implementaciones de VPN, establecer la infraestructura y ponerla a disposición de los desarrolladores. ¡Es realmente genial!
Afortunadamente, AWS, Google Cloud y otros ofrecen un año de uso gratuito, ¡así que úsalos! Son económicos si los apagas cuando no están en uso. Siempre me he preguntado para qué podría necesitar un servidor remoto tipo gcloud, parece que finalmente lo he encontrado.
Como máquina virtual en local, puedes usar el mismo Alpine que se usa activamente en contenedores de Docker. O bien, alguna otra distribución ligera para que la máquina arranque más rápido.
En resumen: correr bases de datos y otras funcionalidades de infraestructura se puede y se debe hacer en servidores remotos o en VirtualBox. No necesito Docker para estos propósitos.
Un poco sobre las imágenes de Docker y la distribución
Ya he escrito en la que quería transmitir que el uso de imágenes de Docker no ofrece ninguna garantía. Las imágenes de Docker son necesarias solo para crear contenedores de Docker. Si te basas en una imagen de Docker, significa que te basas en el uso de contenedores de Docker y solo estarás con ellos.
¿Has visto en alguna parte a desarrolladores de software portando sus productos solo en forma de imagen de Docker?
El resultado de la mayoría de los productos son archivos binarios para una plataforma específica, que simplemente se añaden a la imagen de Docker que hereda de la plataforma necesaria. ¿No te has preguntado por qué hay tantas imágenes similares en Docker Hub? Por ejemplo, escribe nginx, verás 100500 imágenes de diferentes personas. Estas personas no desarrollaron nginx, solo añadieron el nginx oficial a su imagen de Docker y lo complementaron con sus configuraciones para facilitar el arranque de contenedores.
En general, se puede almacenar simplemente en tgz; si alguien necesita ejecutarlo en Docker, que lo agregue en el Dockerfile, herede del entorno necesario y cree funcionalidades adicionales que no cambien la propia aplicación en tgz. Quien vaya a crear la imagen de Docker sabrá qué es ese tgz y qué necesita para que funcione. Así es como utilizo Docker.
En resumen: no necesito un registro de Docker, usaré algún S3 o simplemente un almacenamiento de archivos como Google Drive/Dropbox.
Docker en CI
Todas las empresas en las que he trabajado son similares entre sí. Por lo general, son de productos. Es decir, tienen una aplicación única, una pila de tecnologías (bueno, quizás un par o trío de lenguajes de programación).
Estas empresas utilizan Docker en sus servidores donde se ejecuta el proceso de CI. La pregunta es: ¿por qué es necesario compilar proyectos en un contenedor Docker en sus servidores? ¿Por qué no simplemente preparar el entorno para la compilación, por ejemplo, escribiendo un playbook de Ansible que instale las versiones necesarias de Node.js, PHP, JDK, copie claves SSH, etc., en el servidor donde tendrá lugar la compilación?
Ahora entiendo que esto es dispararse en el pie, porque Docker no aporta ningún beneficio con su aislamiento. Los problemas con CI en Docker con los que me he encontrado son:
- de nuevo se necesita una imagen de Docker para la compilación. Hay que buscar una imagen o escribir su propio Dockerfile.
- 90% de probabilidad de que haya que pasar algunas claves SSH, datos secretos que no se quieren escribir en la imagen de Docker.
- el contenedor se crea y muere, se pierden todas las cachés con él. La siguiente compilación descargará todas las dependencias del proyecto desde cero, lo que es largo e ineficiente, y el tiempo es dinero.
Los desarrolladores no compilan proyectos en contenedores Docker (yo solía ser un gran fanático, la verdad, me da pena mi yo del pasado xD). En Java hay la posibilidad de tener múltiples versiones y cambiarlas con un solo comando a la que se necesita en el momento. En Node.js es lo mismo, existe nvm.
Salida
Creo que Docker es una herramienta muy poderosa y flexible, en eso radica su desventaja (suena extraño, ¿verdad?). Con ella, las empresas fácilmente se "enganchan", la utilizan donde es necesario y donde no lo es. Los desarrolladores inician sus contenedores, su propio entorno, luego todo esto fluye hacia CI y a producción. El equipo de DevOps escribe algunos "ciclos" para iniciar estos contenedores.
Usa Docker solo en la etapa más tardía de tu proceso de trabajo, no lo lleves al proyecto al principio. No resolverá tus problemas empresariales. Solo trasladará problemas a OTRO nivel y ofrecerá sus propias soluciones, lo que te hará hacer el trabajo dos veces.
Cuándo se necesita Docker: llegué a la conclusión de que Docker es muy bueno para optimizar el proceso establecido pero no para construir la funcionalidad básica.
Si decides usar Docker, entonces:
- ten mucho cuidado
- no impongas el uso de Docker a los desarrolladores
- localiza su uso en un solo lugar, no lo repartas por todos los repositorios Dockerfile y docker-compose.
PD:
- Recientemente me topé con Y dicen que funciona muy bien con Ansible y permite unificar el proceso de creación de imágenes (incluida la imagen de docker)
¡Gracias por leer hasta aquí! Les deseo soluciones transparentes en sus asuntos y días laborales productivos.
Fuente: habr.com
