El contexto en el que surgió escribir este artículo es el siguiente:
Tenemos una aplicación Java + Spring, la cual ya está dockerizada. Existen dos entornos: Desarrollo local y un entorno docker. Tenemos definido un application.properties
dentro de nuestro proyecto, donde se definen múltiples variables, las cuales cambian dependiendo del entorno. Al cambiar de entorno, hay que cambiar manualmente el valor de esas variables.
Estado de application.properties
actual
|
|
Para cambiar dicho entorno, es necesario estar modificando este fichero, corriendo el riesgo que se acabe llegando a producción con las propiedades incorrectas.
Para solucionar esta casuística, debemos saber que Spring no es más que una aplicación java, y que una vez se empaqueta la aplicación, esta se lanza con un comando java -jar [nombre de la librería].jar
, pudiendo aceptar argumentos.
Por suerte, Spring reconoce dichos argumentos y les da prioridad frente a los del fichero application.properties
, de tal forma que podríamos lanzar el siguiente comando:
$ java- jar api-0.0.1.jar --spring.datasource.url=jdbc:postgresql://database:5432/license
Si nos llevamos esta línea a un Dockerfile, podríamos indicar lanzar el comando CMD y que nuestro docker por defecto siempre lance la aplicación apuntando al contenedor de base de datos del docker de la siguiente forma:
|
|
La opción anterior es completamente válida y resuelve nuestro problema, ya no tendremos que estar cambiando ficheros de configuración constantemente, corriendo el riesgo de que al cliente le llegue una versión inválida, pero podemos mejorarla un poco más.
De la misma forma que java admite argumentos, docker también lo hace. Esto puede permitir que nuestros clientes puedan decidir no conectar con nuestra base de datos dockerizada, sino con una que tengan desplegada en otra máquina. Spring se encarga de sobreescribir las variables, pero… ¿y nosotros?
Dentro de un Dockerfile, podemos definir argumentos usando la instrucción ARG. La forma más común es recibir un argumento y definirla como variable de entorno usando ENV.
ARG my_arg=default_value
ENV my_env ${my_arg}
Si extrapolamos esto a nuestro Dockerfile, podemos definir que se va a conectar por defecto a nuestra base de datos dockerizada, salvo que nos indiquen lo contrario por argumentos:
|
|
Por lo tanto, cuando construyamos nuestro contenedor, solo tendremos que pasar dicha variable para sobreescribir el valor.
Si nuestro ecosistema se construye a través de un docker-compose.yml, únicamente tendremos que identificar el servicio en cuestión y hacer uso de la propiedad args
, para darle un valor de la siguiente manera:
|
|
De esta forma, cumplimos con la premisa de tener el mismo entorno para producción, desarrollo y test, minimizando el riesgo de problemas por entorno.
Además, permite a los clientes modificar ciertas características de la aplicación, sin tener que llegar a bajo nivel, simplemente editando un valor en un contexto con el que ya está familiarizado.
Al final, no hemos hecho otra cosa que propagar una variable hacia capas más profundas, que, en caso de no indicarse en una de esas capas, tomará el que se entiende que es valor por defecto más sensato en ese ámbito:
docker-compose.yml
El valor dado por el cliente o no aplica ninguno.Dockerfile
-> La base de datos dockerizada en el entorno.application.properties
-> La base de datos local.¿Quieres más? te invitamos a suscribirte a nuestro boletín para avisarte cada vez que recopilemos contenido de calidad que compartir.
Si disfrutas leyendo nuestro blog, ¿imaginas lo divertido que sería trabajar con nosotros? ¿te gustaría?
Pero espera 🖐 que tenemos un conflicto interno. A nosotros las newsletter nos parecen 💩👎👹 Por eso hemos creado la LEAN LISTA, la primera lista zen, disfrutona y que suena a rock y reggaeton del sector de la programación. Todos hemos recibido newsletters por encima de nuestras posibilidades 😅 por eso este es el compromiso de la Lean Lista