Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IV-21-22] Objetivo 5 #35

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion DOCKER_USER

This file was deleted.

117 changes: 103 additions & 14 deletions docs/docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ Para tener una forma de hacer que la aplicación sea portable y esté lista para
* Debe de ser una imagen ligera, siempre que se pueda, es decir, tener las funcionalidades necesarias de Go para cumplir con la correcta construcción y ejecución de nuestro proyecto. Basicamente, esto sirve para acelerar la construcción, la implementación y también reducir costos con el almacenamiento y la salida de la red si está utilizando algún proveedor de la nube.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Te falta una tilde en Básicamente

* Debe de recibir actualizaciones frecuentes, de esta manera se evitarán problemas de seguridad y rendimiento.

### Imagen de Golang
* Debe ofrecer un buen rendimiento, esto abarca desde el tamaño de la imagen hasta la duración de la ejecución de los tests pasando por el tiempo construcción del contenedor.

Teniendo en cuenta los requisitos nombrados podremos lograr un tamaño mínimo de imagen de Docker utilizando imagenes base que se centran en el minimalismo, como Alpine Linux. Dentro de Docker Hub nos vamos a centrar en la imagen oficial de Golang suministrada por Dockerhub, ya que hoy dia es la que más actualizaciones recibe y con mayor frecuencia. Tenemos otras opciones de *Verified Publisher* que son entidades comerciales que publican imagenes muy confiables y estan mantenidas por ellos, como Circle CI o portainer, en el caso de Circle CI las actualizaciones se reciben cada 3/4 semanas y en el caso de portainer la última actualización se recibió hace 4 años. Por tanto, teniendo en cuenta los principios básicos vamos a centramos en las imagenes oficiales de Dockerhub.

## Imagen de Golang

Teniendo en cuenta los requisitos nombrados podremos lograr un tamaño mínimo de imagen de Docker utilizando imagenes base que se centran en el minimalismo, como Alpine Linux. Dentro de Docker Hub nos vamos a centrar en la imagen oficial de Golang suministrada por Dockerhub, ya que hoy dia es la que más actualizaciones recibe y con mayor frecuencia. Tenemos otras opciones de *Verified Publisher* que son entidades comerciales que publican imagenes muy confiables y estan mantenidas por ellos, como Circle CI o portainer, en el caso de Circle CI las actualizaciones se reciben cada 3/4 semanas y en el caso de portainer la última actualización se recibió hace 4 años. Por tanto, teniendo en cuenta los requisitos nombrados vamos a centramos en las imagenes oficiales de Dockerhub.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aquí tienes errores ortográficos en "imagenes base","dia","estan mantenidas" y un error gramatical en "vamos a centramos en".


Las variantes que nos encontramos son:

Expand All @@ -17,41 +20,127 @@ Las variantes que nos encontramos son:
* `golang:<version>-windowsservercore`, esta imagen se basa en Windows Server Core.


### Versiones de Go
Dentro de las posibles imagenes tenemos que saber elegir la versión de Go para ejecutar nuestro proyecto, las distintas versiones las podemos encontrar [aquí](https://go.dev/doc/devel/release). Tenemos que usar una versión que permita obtener los resultados esperados en nuestra aplicación, que tenga soporte y actualizaciones frecuentemente. Tanto [aquí](https://endoflife.date/go) como la [página oficial](https://go.dev/doc/devel/release), podemos ver que las versiones 1.16 y 1.17 son actualmente tienen soporte, por tanto las versiones 1.15 y anteriores quedan descartadas, según los requisitos nombrados. Vamos a tener en cuenta, por ahora, ambas versiones y realizaremos pruebas con ambas para obtener una conclusión final. Cabe mencionar que la versión 1.17 recibe actualizaciones más a menudo que la versión 1.16.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aquí el mismo errorcillo de poner imagenes sin tilde.



Como candidatos a nuestro proyecto:

* [golang:1.17-stretch](https://github.com/docker-library/golang/blob/6b93987c3ec7bb3082dd54a46e9b6b8de95b0eb1/1.17/stretch/Dockerfile) Debian 11, se elige esta version de Debian porque es la última version más estable que se ha lanzado.
* [golang:1.17-alpine](https://github.com/docker-library/golang/blob/6b93987c3ec7bb3082dd54a46e9b6b8de95b0eb1/1.17/alpine3.15/Dockerfile) Alpine 3.15, se elige está porque es rápida y ligera, una de las más populares imagenes base para contenedores Docker.
* [golang:1.17.6-bullseye](https://github.com/docker-library/golang/blob/6b93987c3ec7bb3082dd54a46e9b6b8de95b0eb1/1.17/bullseye/Dockerfile) Debian 11, se selecciona como candidato porque actualmente es la versión estable de Debian, lo podemos comprobar tanto [aquí](https://wiki.debian.org/Status/Stable) como [aquí](https://wiki.debian.org/DebianBullseye). Dado que uno de nuestro requisitos es elegir una versión estable, esta opción se ajusta a nuestros criterios.
* [golang:1.17.6-alpine](https://github.com/docker-library/golang/blob/6b93987c3ec7bb3082dd54a46e9b6b8de95b0eb1/1.17/alpine3.15/Dockerfile) Alpine 3.15, se elige está porque es rápida y ligera, una de las más populares imagenes base para contenedores Docker.
* [golang:1.16-bullseye](https://github.com/docker-library/golang/blob/6b93987c3ec7bb3082dd54a46e9b6b8de95b0eb1/1.16/bullseye/Dockerfile).
* [golang:1.16-alpine](https://github.com/docker-library/golang/blob/6b93987c3ec7bb3082dd54a46e9b6b8de95b0eb1/1.16/alpine3.15/Dockerfile).

Se elige la versión 1.17 de Golang porque es una de las versiones más recientes y que recibe con mayor frecuencia actualizaciones, nuestro proyecto hasta el momento ha estado trabajando en este versión de Go. Se puede observar el soporte y últimas actualizaciones de Go en [esta página](https://endoflife.date/go).
Vamos a analizar las opciones.

## Análisis de construcción

### Tiempos de construcción
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Muy buen trabajo en esta sección, se nota que lo has trabajado este objetivo.


En esta sección se generan los contenedores usando la herramienta `time`. Se ejecuta la orden `time docker build --no-cache . -f ./Dockerfile -t go_<bullseye|alpine>_1.1X`. Los resultados son los siguientes:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Las comparaciones de tiempo de construcción no sirven para nada.


* Alpine, versión de Go 1.17

```shell
Successfully built 8c6c1dda8a53
Successfully tagged go_alpine_1.17:latest

real 0m5,843s
user 0m0,063s
sys 0m0,057s
```

* Alpine, versión de Go 1.16

```shell
Successfully built 7f201f405681
Successfully tagged go_alpine_1.16:latest

real 0m5,742s
user 0m0,044s
sys 0m0,054s
```

* Bullseye, versión de Go 1.17

```shell
Successfully built d2c15c730270
Successfully tagged go_bullseye_1.17:latest

real 0m5,761s
user 0m0,068s
sys 0m0,050s
```
* Bullseye, versión de Go 1.17

```shell
Successfully built dafa5fb683e3
Successfully tagged go_bullseye_1.16:latest

real 0m5,757s
user 0m0,068s
sys 0m0,046s
```

Los resultados son prácticamente iguales, variando a nivel de milesimas.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tenías en caché las partes necesarias para construir el container ya? Recuerdo que a mí alpine al borrar todo me tardaba más, pero claro, era Python y no Go.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

En el documento dejo la instrucción con la que hago el análisis de tiempo de contrucción, en este caso indico el flag --no-cache. Si es verdad que la primera vez que quise hacer el análisis obtuve un tiempo pero que muy inferior con la imagen de Alpine con la versión 1.17 ya que fue la que use la primera vez que entregué el objetivo, pero investigué de como poder hacer la prueba sin necesidad de cargar de la cache nada para que sean resultados "justos" lo que obtuviese.

Es verdad que viendo correcciones a distintas personas que usan Python con Alpine he visto que había bastantes más problemas en cuanto a tiempo de compilación o incluso de tamaño, siendo en algunos casos más ligera la versión Slim que la de Alpine.


### Tamaño de la imagen
Se analiza en espacio que ocupa cada imagen base:

```
mywallet stretch 232c3b59a871 About a minute ago 879MB
mywallet alpine cbc92daa90aa 2 minutes ago 351MB
go_alpine_1.16 latest 7f201f405681 337MB
go_bullseye_1.16 latest dafa5fb683e3 954MB
go_bullseye_1.17 latest d2c15c730270 976MB
go_alpine_1.17 latest 8c6c1dda8a53 351MB
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

En general, debéis usar siempre la última versión del sistema operativo, que es la que corrige las vulnerabilidades. Comparar versiones por tamaño no tiene sentido, porque son cosas diferentes.

```

Encontramos una diferencia bastante notoria relativa al peso de las imagenes, la imagen Alpine es bastante más ligera que el resto.
Encontramos una diferencia bastante notoria relativa al peso de las imagenes, la imagen Alpine es bastante más ligera que el resto. La más ligera es la de la versión 1.16 de Go, pero en tan solo 14MB. Teniendo en cuenta nuestros requisitos, la imagen de Alpine es una clara candidata para nuestro proyecto.

Aun no se puede tomar una decisión final, analizando el rendimiento de las imagenes encontré [esta página](https://nickjanetakis.com/blog/benchmarking-debian-vs-alpine-as-a-base-docker-image) donde se realiza un benchmarking entre imagenes Debian y Alpine. La conclusión es que son dos imagenes con las que se obtienen resultados muy similares y que a no ser que se encuentren errores significativos con Alpine por su tamaño y velocidad es más recomendable.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Te faltan tildes en aun y en imagenes.



### Tiempos de ejecución

Se ejecutan los contenedores que hemos generado. Los resultados que obtenemos son los siguientes:

* 1.17 BULLSEYE

ok MyWallet/internal/mywallet 0.009s

ok MyWallet/internal/mywallet 0.001s

Me parecio extraño el primer tiempo, volví a ejecutar y se obtuvieron varias veces el segundo tiempo.

* 1.17 ALPINE

ok MyWallet/internal/mywallet 0.001s

* 1.16 ALPINE

ok MyWallet/internal/mywallet 0.001s

* 1.16 BULLSEYE

ok MyWallet/internal/mywallet 0.001s

Aun no se puede tomar una decisión final, analizando el rendimiento de las imagenes encontré [esta página](https://nickjanetakis.com/blog/benchmarking-debian-vs-alpine-as-a-base-docker-image) donde se realiza un benchmarking entre imagenes Debian y Alpine. La conclusión es que son dos imagenes con las que se obtienen resultados muy similares y que a no ser que se encuentren errores significativos con Alpine por su tamaño y velocidad es más recomendable. Destacar las desventajas que nos encontramos con Alpine es L que utiliza **musl libc** en lugar de **glibc**, puede llegar a provocar un comportamiento inesperador en nuestra aplicación. En [este artículo](https://news.ycombinator.com/item?id=10782897) se conversa acerca de los problemas que puede traer este tipos de imagenes.

Por tanto, mi decisión final es que a no ser que se encuentre algún error importante con imagenes Alpine se usará `golang:1.17-alpine` como imagen base para nuestro proyecto.
### Conclusión

Los tiempos de ejecución y de construcción son prácticamente iguales, la principal diferencia se encuentra en el tamaño de la imagen, en este apartado Alpine sale claro vencedor. Por tanto, mi decisión final es que a no ser que se encuentre algún error importante con imagenes Alpine se usará `golang:1.17-alpine` como imagen base para nuestro proyecto. La versión de Go que he elegido es la 1.17, si es verdad que la versión 1.16 pesaba algo menos, pero me parece algo poco significativo, más significativo me parece que una versión reciba más actualizaciones que la otra, por esto se elije la versión 1.17.

### Facilitar uso de Docker con nuestro task runner
## Facilitar uso de Docker con nuestro task runner

Se ha automatizado la ejecución de los tests en el task runner. Esto se consigue añadiendo la siguiente directiva a nuestro Taskfile.yml:

```docker run -t -v `pwd`:/app/test luisarostegui/mywallet```

### Buenas prácticas en nuestro Dockerfile
## Buenas prácticas en nuestro Dockerfile

* Vamos a usar una imagen ligera (Alpine) para optimizar el tamaño y poder tener el control sobre los paquetes necesarios.
* Usar variables con ENV para directorios de trabajo.
* Ejecutar tanto las instalaciones de las dependencias como el task runner como usuario y no como superusuario.

### Justificación de directivas en el Dockerfile
## Justificación de directivas en el Dockerfile

1. Con la directiva FROM especificamos la imagen base.
2. La directiva LABEL la utilizamos para especificar nombre y correo de la persona encargada del Docker.
Expand All @@ -62,7 +151,7 @@ Se ha automatizado la ejecución de los tests en el task runner. Esto se consigu
7. WORKDIR, especificamos la ruta donde queremos trabajar.
8. ENTRYPOINT, indicamos la acción a ejecutar, en este caso `task test`.

### Comentarios en el Dockerfile
## Comentarios en el Dockerfile

```
#Imagen base para docker
Expand Down