Durante mucho tiempo al comienzo de mi carrera profesional como desarrollador (hace +20 años) era habitual que cuando uno comenzaba en un nuevo proyecto/trabajo, tenía que invertir varias horas instalando herramientas y ajustando configuración antes de poder tirar una línea de código. Esta situación sigue ocurriendo en muchas organizaciones/contextos. Sin embargo existe en la actualidad un conjunto de herramientas que pueden ayudarnos a tener experiencia mucho más fluida. Una de esas herramientas es Docker. Personalmente suelo hablar de una experiencia Clone & Run. Llegas a un proyecto, tomas tu host, instalas Git y Docker, ejecutas git clone y docker-compose up, buscas un café y al rato ya estas listo para empezar a codear. Explicar como lograr esto con texto puede resultar muy largo e inconveniente, por ello hice un video explicando y mostrando esta experiencia. Espero les resulte util.
Etiqueta: docker
Uso de RubyMine con Docker-compose
Hace un tiempo escribí como sobre usar RubyMine con Docker. En ocasiones, cuando trabajamos con aplicaciones web es habitual utilizar una configuración docker-compose que incluya un contenedor con el runtime Ruby y algunos otros contenedores por ejemplo con MySql, Redis, etc. Para usar RubyMine en estos escenarios debemos hacer lo siguiente.
Armamos la configuración docker-compose y la ponemos a correr asegurándonos de el contendedor que contiene el runtime Ruby quede levantado. Esto puede hacerse agregando las siguientes 3 líneas en la definición del contenedor:
command: "/bin/bash"
stdin_open: true # esto es equivalente a hacer docker run -i
tty: true # esto es equivalente a hacer docker run -t
Luego, abrimos el proyecto en RubyMine y ajustamos la configuración en «Ruby SDK and Gems». Agregamos una nueva configuración remota.

En la ventana emergente debemos seleccionar la opción «Docker Compose», en «Configuration Files» debemos apuntar al archivo que contiene nuestra configuración de docker-compose y finalmente en «Service» debemos seleccionar el contenedor que contiene el runtime Ruby. Dependiendo de como esté instalado el runtime Ruby en la imagen del contenedor puede que necesitemos ajustar el valor default de «Ruby or version manager path».

Una vez que damos «OK» a ambas ventanas de emergentes el RubyMine puede tardar unos minutos en completar la aplicación de la nueva configuración.
Un detalle más: si queremos utilizar el debugger de RubyMine debemos asegurarnos que nuestro proyecto incluya las gemas «ruby-debug-ide» y «debase» en el Gemfile.

Finalmente les comparto una configuración compose de ejemplo para que se entienda todo el contexto.
version: '3'
services:
test_db:
image: postgres
environment:
POSTGRES_PASSWORD: example
dev_db:
image: postgres
environment:
POSTGRES_PASSWORD: example
webapp:
build:
context: .
dockerfile: Dockerfile.dev
command: "/bin/bash"
stdin_open: true # docker run -i
tty: true # docker run -t
ports:
- "3000:3000"
expose:
- 3000
volumes:
- .:/app
environment:
RACK_ENV: "development"
TEST_DB_URL: "postgres://postgres:example@test_db:5432/postgres"
DEV_DB_URL: "postgres://postgres:example@dev_db:5432/postgres"
depends_on:
- test_db
- dev_db
RubyMine con Docker
En la actualidad es cada vez más habitual utilizar Docker como ambiente de desarrollo, o sea: en lugar de instalar el runtime de desarrollo en nuestro host, armamos una imagen Docker con el runtime del proyecto conteniendo también todas dependencias/libs y en nuestro host instalamos tanto solo Docker Desktop y el IDE de nuestra elección.
Esta estrategia resulta especialmente útil en stacks como Ruby donde es habitual tener que utilizar distintas versiones Ruby. Sin embargo cuando pretendemos utilizar IDEs más potentes como RubyMine, que proveen algunas funcionalidades que dependen del runtime (como es el caso de algunos refactorings), es necesario hacer algunos ajustes de configuración en el IDE. Es por ello que grabe un video explicando estos ajustes. Espero les resulte útil.
Deploy de contenedores a Heroku con GitLab

En mi opinión gran parte de la popularidad que alcanzó Heroku se debió a la facilidad con la que era posible desplegar una aplicación: git push. Básicamente teniendo el código fuente en un repositorio Git, solo basta con agregar un nuevo remote provisto por Heroku y hacer push al mismo. Cuando Heroku recibe el código fuente ejecuta un build-pack que básicamente «preparar el ambiente» para poder ejecutar el código recibido. Dependiendo del lenguaje ese build-pack puede instalar dependencias, compilar e incluso ejecutar migrations. Esta es seguramente la estrategia más utilizada al usar Heroku pero no es la única. Otra opción es ejecutar directamente un contenedor Docker. Esta opción trae un poco más de complejidad pero al mismo tiempo trae algunos beneficios interesantes.
La opción de utilizar un contenedor nos da más «libertad»/flexbilidad. Con el modelo de ejecución tradicional nuestra aplicación está restringida a lo establecido por el build-pack (aún cuando es posible crear build-packs, eso ya tiene otro costo), mientras que al correr un contenedor podemos poner lo que querramos dentro. Al mismo tiempo, al poder especificar el Dockerfile tenemos la posibilidad de ajustar ciertos aspectos del runtime. Finalmente, el correr un contenedor nos también la libertad de salir de Heroku a un costo más bajo.
En el contexto de MeMo2 @ Fiuba, utilizamos Heroku en modo «tradicional» durante el primer trabajo grupal pero para el segundo TP grupal tenemos la intención de utilizar un modelo basado en contenedores ya que queremos estudiar algunas de las implicancias de este modelo en términos de configuración management y deployment pipelines.
Explicada la motivación veamos entonces algunas cuestiones de implementación. En primer lugar debemos crear la imagen del contenedor que querramos ejecutar, para esto podemos delegar la creación de la imagen en Heroku o bien podemos crearla nosotros mismo y luego darsela a Heroku. Una vez que la imagen está construida y subida Heroku, basta una invocación a API rest para desplegarla (también es posible haciendo uso del heroku-cli). Al mismo tiempo, si es necesario ejecutar algún tipo de inicialización antes de levantar el contenedor Heroku nos da posibilidad de ejecutar un esa inicialización con otra imagen. Esto eso, debemos crear una imagen llamada «release», subirla a Heroku y cada vez que disparemos un deploy Heroku, se ejecutar primero la imagen release para hacer las tareas de incialización y luego se pondrá a correr el contenedor de nuestra aplicación. Todo esto está explicado con bastante detalle la documentación oficial de Heroku.
Llevando todo esto a nuestro escenario de MeMo2, vamos construir nuestra imagen Docker como parte nuestro pipeline de GitLab y vamos a almacenarla en la propia registry de Gitlab. Luego en el paso de deploy haremos un push de la imagen a Heroku y dispararemos el deploy via la API Rest. A continuación comparto algunos snippets de código de nuestro pipeline que puede resultar útiles para quienes pretendan implementar una solución similar con Heroku y Gitlab.
El siguiente fragmento de código corresponde a job de GitLab que crea la imagen Docker y la publica en la registry de GitLab
package_job: stage: package image: docker:stable before_script: - echo -n $CI_JOB_TOKEN | docker login -u gitlab-ci-token --password-stdin $CI_REGISTRY script: - VERSION=$(cat VERSION.txt) - docker build -f Dockerfile.prod -t $REGISTRY_URL/$APP_NAME:$VERSION . - docker tag $REGISTRY_URL/$APP_NAME:$VERSION $REGISTRY_URL/$APP_NAME:latest - docker push $REGISTRY_URL/$APP_NAME:$VERSION - docker push $REGISTRY_URL/$APP_NAME:latest
A continuación tenemos el fragmento de código correspondiente al job de deploy el cual descarga la imagen a desplegar de la registry de Gitlab y la sube Heroku. Finalmente invoca a script de deploy que interactua con la API Rest de Heroku.
deploy_dev_job: stage: deploy image: docker:stable before_script: - apk add curl - echo -n $CI_JOB_TOKEN | docker login -u gitlab-ci-token --password-stdin $CI_REGISTRY - docker login -u _ -p $HEROKU_TOKEN registry.heroku.com script: - VERSION=$(cat VERSION.txt) - docker pull $REGISTRY_URL/$APP_NAME:$VERSION - docker tag $REGISTRY_URL/$APP_NAME:$VERSION registry.heroku.com/$HEROKU_APP/web - docker push registry.heroku.com/$HEROKU_APP/web - export IMAGE_ID=`docker inspect registry.heroku.com/$HEROKU_APP/web --format={{.Id}}` - ./scripts/deploy_app.sh
Finalmente este es el script que invoca a la API de Heroku (este script es algo que definitivamente puede mejorarse)
#!/bin/sh set -x DATA='{ "updates": [ { "type": "web", "docker_image":"' DATA="$DATA$IMAGE_ID" DATA=$DATA'" } ] }' curl -X PATCH https://api.heroku.com/apps/$HEROKU_APP/formation --header "Content-Type: application/json" --header "Accept: application/vnd.heroku+json; version=3.docker-releases" --header "Authorization: Bearer ${HEROKU_TOKEN}" --data "$DATA" --fail
Cierro con algunos comentarios:
- Estos fragmentos de código requieren del uso de un API token de Heroku que debe ser configurado en las variables del ambiente del pipeline.
- Ambos jobs del Gitlab asumen la existencia del un archivo VERSION.txt que contiene el tag correspondiente a la imagen docker que construye/publica/despliega. Típicamente ese archivo se genera en el build y se lo propaga por el pipeline o bien está en el repositorio de código fuente.
- Estos fragmentos son ejemplos que pueden ser mejorados y/o ajustados para contextos más específicos. De hecho es muy posible que en los próximos días les aplique algunos ajustes.
Taller Online de Docker & Kubernetes: segunda edición completa
La semana pasada completamos la segunda edición de este taller. A diferencia de la primera edición, el flujo de los encuentros fue un poco más «trabado», pues hubo mucha charla. O sea, hubo un par de participantes muy entusiastas con muchas inquietudes que generaron preguntas, idas y vueltas. Esto esto estuvo muy bueno en cierto sentido pero al mismo tiempo generó que algunas de las explicaciones tuvieran menos profundidad o que incluso no llegaramos a hacer algún ejercicio. Al mismo tiempo hubo otros participantes que apenas hablaron. No se si una dinámica así (de mucha idea y vuelta) es mejor o no, pero definitivamente es algo a repensar y moderar para una siguiente edición.
Más allá de este detalle, el resultado del taller fue muy positivo. Estoy completamente convencido de este formato de curso y seguramente lo estaré utilizando en futuros cursos sobre nuevas temáticas.
Nueva edición del Taller online de Docker & Kubernetes
En la última semana estuve trabajando en preparar una nueva edición del taller. El temario será el mismo pero estuve ajustando algunos de los ejercicios y los materiales de estudio:
- Introducción a Docker
- Consideraciones para la elección de imágenes base
- Recomendaciones para la creación de imágenes
- El ecosistema de herramientas Docker
- Tecnologías de contenedores más allá de Docker
- Introducción a Kubernetes
- Recomendaciones para el diseño de aplicaciones Kubernetes
- Manejo de configuración con Secrets y ConfigMaps
- El ecosistema de herramientas Kubernetes
- Deploy y monitoreo
- Distribución de aplicaciones Kubernetes con Helm
El taller será los días miércoles a las 20 hs. (hora Argentina, UTC-3). Serán 5 encuentros cada uno de ~90 minutos. La fecha de inicio será el miércoles 20 de marzo. Los interesados pueden preinscribirse aquí (si ya se habían preinscripto para la edición no hace falta que vuelvan a hacerlo, pues ya tengo sus datos y lo contactaré en forma privada).
Simplificando el setup de Jenkins con Docker
A la hora de hacer el setup de Jenkins hay diversas cuestiones que resolver las cuales pueden variar dependiendo del contexto. En términos muy generales esas cuestiones se resuelven:
- operando directamente sobre Jenkins, por ejemplo para instalar plugins
- o bien operando sobre el servidor en el cual Jenkins está corriendo, por ejemplo para instalar un SDK
La importancia que se le da al primer punto es muy variable y depende de si se trata de un «Jenkins Silvestre» (Jenkins manejado por un equipo de desarrollo sin ningún tipo de soporte organizacional) o si se trata de un «Jenkins Corporativo» que es administrado por un grupo de la organización.
Pero el segundo punto, es algo central si pretendemos utilizar Jenkins para buildear. Si queremos utilizar Jenkins para buildear C#, tendremos que asegurar que el servidor donde corre Jenkins tenga el correspondiente SDK instalado (o eventualmente necesitaremos un Jenkins Slave que tenga el SDK.) Esta situación se repite para cada tecnología/lenguaje que uno pretenda buildear. Más allá de la tarea de instalar el SDK en si misma, el punto es que hay que loguearse en el servidor para llevarla a cabo. Una forma de simplificar este setup es utilizar Docker. O sea, en lugar de instalar los SDK en el servidor de Jenkins, uno instala simplemente Docker y luego utiliza un contenedor Docker que contenga el SDK que cada proyecto requiera. Al mismo tiempo esto simplifica el escenario donde tenemos proyectos con dependencias de SDK que tiene conflictos entre si.
A mi parecer esta estrategia aún no está muy difundida pero me parece que a mediado plazo se impondrá como estándar de facto. De hecho, las últimas versiones de Jenkins (las que vienen nativamente con el plugin de Pipeline 2.5 o superior) simplifican mucho este setup. Basta con tener Docker instalado en el servidor de Jenkins y declarar la imagen builder a utilizar en nuestro Jenkinsfile.
El siguiente fragmento de código muestra un job de Jenkins que utiliza una imagen de node 8.9. Lo que hace es trivial, simplemente invoca node –version y escribe el output en un archivo de texto. Lo interesante es que el archivo de texto resultante queda dentro del workspace del job, o sea: Jenkins se está encargando de «sacar» el archivo que se genera dentro del contenedor Docker.
node {
docker.image('node:8.9-alpine').inside {
stage('Test') {
sh 'node --version > version.txt'
}
}
}
Taller Online de Docker & Kubernetes: resultado de la primera edición
La semana pasada completé la primera edición de este taller. Participaron 8 personas, porque si bien hubo alrededor de 30 interesados, decidí limitar la cantidad de participantes pues no estaba seguro de como funcionaría la herramienta de conferencia. Por suerte funcionó bien.
El taller consistió en 4 sesiones online de entre 1 y 2 horas cada una. Estimar la duración de la sesiones es lo que más me costó, en parte por ser un contenido nuevo y en parte por ser una dinámica nueva.
La evaluación de los participantes fue muy positiva:
- Evaluación general del taller: muy bueno 50% , excelente 50%
- Evaluación de los encuentros online: muy bueno 66%, excelente 30%
- ¿Recomendarías este taller a un colega? Definitivamente si 100%
Por otro lado las respuestas de feedback libre fueron también muy positivas. A partir de estos resultados y dado el interés que hay en la temática, en breve estaré anunciado la fecha de la próxima edición. Los interesados pueden pre-registrarse aquí y los contactaré cuando tenga los detalles de la nueva siguiente edición.
Les comparto una foto de mi «estudio de transmisión». Al centro mi computadora primaria con una segunda pantalla conectada a la izquierda. La pantalla de la computadora la utilizo para pasar las diapositivas y mostrar las herramienta mientras que la pantalla extendida la utilizo para la conferencia y el chat con los participantes. Del lado derecho, mi computadora secundaria como plan B en caso de que por algún motivo mi computadora primaria deje de funcionar. Junto al teclado mi cuaderno de anotaciones. Finalmente en el banquito de madera, un infaltable: el mate.

Dinámica del taller online de Docker/Kubernetes
La semana pasada un publiqué artículo contando mi intención de hacer un taller online sobre Docker y Kubernetes. Resulta que hubo varios interesados y por ello ahora quiero compartir algunos detalles sobre la dinámica del taller.
La idea taller es aprender haciendo, con lo cual no bastará con asistir a las sesiones online para aprender. Las sesiones online estarán centradas en 2 cuestiones: presentación/explicación de conceptos y discusión/consultas. Luego, entre sesión y sesión, habrá actividades de estudio y prácticas que es donde espero se produzca el aprendizaje
El taller constará de 4 sesiones online de 2 horas. Cada una de esas sesiones será complementada con un conjunto de ejercicios, lecturas y evaluaciones de nivel que según mi estimación requerirán de unas 2 o 3 horas de trabajo por semana. La duración calendario del taller será 4 semanas.
Los participantes trabajarán localmente en sus máquinas y para algunos ejercicios específicos utilizarán servicios en la nube. Al final de taller los participantes dispondrán de las diapositivas utilizadas, una serie de materiales de estudio y obviamente el código de los ejercicios que hayan resuelto.
Taller online de Docker/Kubernetes
Hace tiempo que vengo haciendo experimentos con distintas técnicas de enseñanza/entrenamiento y finalmente he decidido hacer un taller online. Una parte de la motivación pasa por pura curiosidad y otra parte tiene que ver con un experimento para mi maestría en informática aplicada a educación.
La temática del taller será Docker/Kubernetes. Lo dictaré durante el mes de Enero y tendrá una carga horaria de unas 5 horas semanales divididas en 2 horas de trabajo online (clase + consultas) y unas 3 horas de trabajo offline (tareas varias como lecturas, videos, programación, etc.). Los horarios de los encuentros online los definiré en conjunto con los interesados en participar del taller.
Inicialmente pensaba hacerlo gratuitamente, pero estoy harto de organizar eventos gratuitos en los que rápidamente se completan los cupos de inscripción y luego asisten tan solo 35% de los inscriptos. Explicado mi punto de vista, el taller tendrá un costo de u$d 50 (dólares) para profesionales y 15 dólares para estudiantes que no trabajan.
A grandes rasgos el temario del taller será:
- Introducción a Docker
- Consideraciones para la elección de imágenes base
- Recomendaciones para la creación de imágenes
- El ecosistema de herramientas Docker
- Tecnologías de contenedores más allá de Docker
- Introducción a Kubernetes
- Recomendaciones para el diseño de aplicaciones Kubernetes
- Manejo de configuración con Secrets y ConfigMaps
- El ecosistema de herramientas Kubernetes
- Deploy y monitoreo
- Distribución de aplicaciones Kubernetes con Helm
El taller está destinado de más a usuarios de kubernetes que a administradores de Kubernetes por ello no se cubriran cuestiones tales como la instalación de Kubernetes.
Los interesados pueden completar este formulario de inscripción y si tienen consultas pueden escribir un comentario en este post.