You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

339 lines
20 KiB

3 years ago
https://trastienda.sindominio.net/Estibadores
https://git.sindominio.net/meskio/ansible_laminar/src/branch/master/playbook.yml
https://docs.docker.com/
https://docs.docker.com/get-started/
https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
http://xfmro77i3lixucja.onion/book/ivKkU9FIkf59BV_Z
3 years ago
# Primer dia de tutorial:
#
3 years ago
Docker trabaja con imagenes, una imagen contiene un sistema base (una debian por ejemplo) con todo lo que necesitas para ejecutar tu aplicacion ya instalado.
Las imagenes son de solo lectura, asi que la arrancas y todo lo que hagas dentro se pierde cuando la reinicias.
Las imagenes son portables, yo puedo hacer una imagen en mi maquina y funciona exactamente igual en la tuya.
3 years ago
Una imagen (.tar) con el sistema instalado dentro y algo de metadatos; se define en un fichero llamado **Dockerfile** (script) que lo usamos para generar la image.
3 years ago
https://git.sindominio.net/estibadores/registry/src/branch/master/Dockerfile
Una imagen se puede basar en otra imagen, por ejemplo ese Dockerfile usa 'registry.sindominio.net/debian' como imagen base.
Otra imagen podria estar basada en esta y asi sucesivamente.
Es decir que podemos tener un arbol grande de imagenes unas basadas en otras, de forma que usamos el sistema instalado de una imagen para construir la siguiente.
3 years ago
**como hacer imagenes, como ejecutarlas y que es un registry:**
3 years ago
3 years ago
1.) En el **script** vemos diferentes infos, como ‘from’:
Si haces un **debootstrap** [debootstrap es una herramienta de debian para generar un sistema de ficheros con debian instalado, por ejemplo se usa para montar chroots, a debootstrap le das una carpeta y te monta un debian dentro] y lo metes en un tar es muy parecido a lo que es una imagen de docker.
3 years ago
3 years ago
Un comando muy importante es el **run**, que es el que junto con **copy** y **add** (para otro dia estos dos), usamos para poner lo que necesitamos en la imagen.
3 years ago
3 years ago
Asi que ese Dockerfile basicamente coje la imagen base de debian e instala el paquete **'docker-registry'**.
Dockerfile se usa con **docker build**.
3 years ago
docker run lo que hace es descargarse una imagen ya generada
Lo interesante de las imagenes es que no solo son de solo lectura, sino que se componen de 'overlays' (capas) asi que la imagen registry.sindominio.net/debian es una capa y cuando haces el run hace otra capa y asi sucesivamente.
3 years ago
De tal forma que en una maquina donde tengamos 50 imagenes, pero todas usen registry.sindominio.net/debian esa capa solo esta una vez instalada, imaginate un monton de ficheros .tar (uno debian.tar, otro foo.tar,…) y cuando ejecutas la imagen lo que hace es primero descomprimir debian.tar luego encima de debian.tar descomprime foo.tar y asi sucesivamente.
**Todo eso lo pone en modo solo lectura y te pone otra capa encima donde puedes escribir pero se pierde cuando paras la imagen**
3 years ago
3 years ago
Por terminar de explicar ese dockerfile que he puesto de ejemplo **entrypoint** es el comando que se ejecuta cuando arrancas la imagen
una imagen docker no es como una debian que tiene muchos procesos corriendo, lo normal es que solo tenga un programa, y este es el que pones en entrypoint y **cmd** son los parametros que le pasas al entrypoint [linea 8 del Dockerfile]
3 years ago
3 years ago
***Por defecto las imagenes se ejecutan como root, user lo uso para que le quite privilegios y se ejecute como el usuario docker-registry
3 years ago
Esto es como en el lxc lo de hacer los contenedores unprivileged
3 years ago
añadiendo user hacemos que la imagen sea unpvileged.***
3 years ago
3 years ago
[[momento en que entramos en la maquina donde jugaremos, compartimos terminal y descargamos la imagen git clone https://git.sindominio.net/estibadores/registry
y meskio propone en otro momento contarnos como se genera la imagen de debian, que es mas complicado]]
3 years ago
3 years ago
2.) Si entras en el repo puedes **buildear la imagen** con **docker build**:
3 years ago
3 years ago
$ docker build -t minuevaimagen .
**-t** es para darle un nombre a la imagen
3 years ago
docker build hay que ejecutarlo en la carpeta donde tienes el Dockerfile
3 years ago
recordar **el punto (.)** del final para decirle que quiero buildear el directorio en el que estoy
si ves los steps basicamente son cada linea del Dockerfile ha sido muy rapido por que ha usado la cache, que esta misma imagen ya la tengo generada en esta maquina y no ha tenido que ejecutar apt de nuevo
3 years ago
ahora si haces docker images veras tu imagen en el listado de imagenes que hay en el docker daemon de esta maquina. Con less o con grep por si hay mucha basura.
3 years ago
De momento hemos **construido** la imagen, pero todavia no la hemos **ejecutado**, para ejecutarla:
3 years ago
3 years ago
docker run -d test1
y para verla en ejeccucion
docker ps
**-d** despues de docker run para que no se te lleve la terminal
3 years ago
matar tu imagen con un ctrl-c
3 years ago
ahora no esta tu imagen en ejecucion, solo hay otras imagenes que meskio tiene ahi
pues ahora le añadimos un -d al docker run para que haga **detach** y la lance en segundo plano
ahora vemos el output del programa **docker-registry** que se esta ejecutando dentro
???stdout??? ahora podemos ver el stdout del comando con **docker log**
3 years ago
para ello se tendra que usar el container_id que te sale en el docker ps
3 years ago
docker logs 798585f1f771
(id que sale en docker ps)
docker stop [id]
(para pararla)
3 years ago
3 years ago
3.) Abrir **puertos** y usar **volumenes**
***Los contenedores por defecto estan aislados, no pueden ni acceder al disco duro, si que pueden comunicarse por la red, tienen acceso a internet, pero no pueden abrir puertos.
Y como son de solo lectura cuando los apagas se pierde todo lo que hayan hecho***
3 years ago
3 years ago
**Primero a aprender a abrir puertos**
3 years ago
docker-registry (que explicare luego lo que es) usa por defecto el puerto 5000
en la maquina en la que estamos el puerto 5000 ya esta ocupado, asi que vamos a decirle a docker run que cuando lance el contenedor el puerto 5000 de dentro del contenedor lo mapee al puerto 5005 de la maquina en la que estamos.
para eso le añadimos un -p 5005:5000 al docker run
Ponle siempre el -d para no perder la terminal.
3 years ago
**-p** le dice que el puerto 5000 de dentro del contenedor lo tiene que mapear al puerto 5001 del host.
3 years ago
3 years ago
docker run -d -p 5005:5000 test1
curl http://localhost:5005/v2/_catalog
3 years ago
Hasta puedes hacer un curl desde tu portatil y funcionara:
3 years ago
curl http://178.32.130.81:5005/v2/_catalog
3 years ago
Asi que el puerto 5005 ahora esta abierto al mundo entero.
3 years ago
**Segundo, para esa imagen que le vamos a pasar un volume**
3 years ago
Los volumes es como llama docker a dejarle acceder al contenedor a una carpeta o fichero de fuera del contenedor
En plan para poder copiar cosas de esa carpeta o fichero, asi que el puerto es la manera que docker se abre al exterior, como los puertos del server, y los volumenes son con los que comparte cosas.
Para que cada vez que pares el contendor los datos no se pierdan.
3 years ago
Para montar una carpeta de fuera del contenedor dentro y que pueda escribir cosas que se guarden entre reinicios docker-registry guarda cosas en **/var/lib/docker-registry**
3 years ago
Si ahora lo lanzamos con -v /tmp/test1:/var/lib/docker-registry dentro del contenedor en /var/lib/docker-registry podra acceder al /tmp/test1
3 years ago
**-v** es un parametro de docker run cuando digo he creado /tmp/test1 lo que he hecho es mkdir y chmod para darle permisos.
3 years ago
-v le dice que la carpeta /tmp/test1 tiene que aparecer dentro del contenedor en /var/lib/docker-registry
/var/lib/docker-registry es algo que solo existe dentro de la imagen test1
lo que hacemos es mapear /tmp/test1 (que existe en la maquina en la que estas) en /var/lib/docker-registry del contenedor.
Entonces el comando es docker run -v /tmp/test1:/var/lib/docker-registry
3 years ago
docker run -d -p 5005:5000 -v /tmp/test1:/var/lib/docker-registry test1
3 years ago
[el container id cambia de una ejecucion a otra puedes tener multiples veces la misma imagen ejecutandose con diferentes ids]
3 years ago
docker ps
docker stop [id]
(para prar el registry)
docker run -d -p 5005:5000 -v /tmp/test1:/var/lib/docker-registry test1
3 years ago
al montar el volumen estamos salvando la imagen en la que hemos trabajado.
3 years ago
4.) Vamos a aprender a **subir** tu imagen test1 ahi. Hasta ahora todo lo que hemos hecho es en **local**. Las imagenes solo existen en esta maquina y nadie mas tiene acceso a ellas, la forma de compartir imagenes es usar un registry
3 years ago
Abriendo el puerto 5005 al exterior solo le hemos dado acceso externo.
La imagen que has buildeado es un registry donde puedes compartir imagenes con otra gente
Todo el mundo ahora puede subir imagenes a ese registry
hub.docker.io es otro registry (hablamos de este en otra sesion)
3 years ago
Para poder subir una imagen primero tenemos que **taguearla** para el registry que usemos:
3 years ago
3 years ago
docker tag test1 localhost:5005/test1
3 years ago
Con esto le decimos que la imagen test1 tambien tiene el nombre localhost:5005/test1
3 years ago
y ahora podemos **pushearla** al registry:
3 years ago
3 years ago
docker push localhost:5005/test1
3 years ago
3 years ago
Para ver los nombres de las imagenes puedes usar **docker images | grep localhost:5005**
3 years ago
Ahora si miras en /tmp/test1 veras que el contenedor ha creado cosas ahi, basicamente la imagen que has subido y ahora que la imagen esta en el registry cualquiera puede descargarla y ejecutarla con:
3 years ago
docker run 178.32.130.81:5005/test1
3 years ago
docker tiene configurado para usar hub.docker.io como registry por defecto
asi que cuando haces docker run debian en realidad estas haciendo docker run hub.docker.io/debian
3 years ago
[otro dia hablamos de docker compose]
3 years ago
3 years ago
# Segundo dia de tutorial:
#
3 years ago
Si os fijais registry.sindominio.net apunta a esta misma maquina https://git.sindominio.net/estibadores/registry < aca dentro hay una repo que se puede descargar con wget
3 years ago
si mirais en ese repo hay un **docker-compose.yml**
En este file hay un restart:
3 years ago
3 years ago
registry:
restart: always
image: sindomninio
3 years ago
3 years ago
Si ponemos **always** docker se encargara de volver a lanzar la imagen si por alguna razon muere, lo mismo que el **systemctl restart** sirve para pasar variables de entorno, si hay mucho mas que se puede poner en **docker-compose**, pero con esto esta lo basico.
3 years ago
3 years ago
[Complicandose el tutorial: Se pueden poner en un solo fichero multiples imagenes y coordinar cosas como puertos que necesita una imagen para cominar con otra y cosas asi
pero esto lo tengo en pendientes de aprender mas para servicios complicados, donde necesitas multiples imagenes puedes coordinarlas asi; por ejemplo lanzar una base de datos, hacer que se comunique con otra imagen que corre php y una tercera que tiene nginx. Por ejemplo un wordpresss necesitaria un nginx, un php-fpm y un mariadb. Todo eso se pondria en el docker-compose.]
3 years ago
3 years ago
El objetivo es **atomizar y coordinar** con **docker compose** y no hacer dockers mas complejos.
3 years ago
Y lo bueno de usar docker compose es que tenemos una descripcion clara de como se lanza el servicio.
Ahora si que tenemos la imagen parada con docker stop [id], esta que teniamos del registry corriendo que hemos visto con docker ps.
3 years ago
Para lanzar la imagen con docker compose: **docker-compose.yml que esta en el directory donde nos encontramos**
docker-compose up -d
3 years ago
3 years ago
Pruebas que meskio tiene de como le gustaria el **CI (integracion continua)** para generar las imagenes de sindominio.
3 years ago
La idea del CI es que definimos nuestras imagenes en git.sd.net y automaticamente se buildean y aparecen en nuestro registry ahi hay un par de graficos de como funciona:
https://git.sindominio.net/meskio/ansible_laminar/src/branch/master/playbook.yml
https://trastienda.sindominio.net/Estibadores#Image_pipeline
Podemos ver que hay en http://178.32.130.81:9000/hooks/build_image cada vez que cualquier repositorio de ese grupo tiene un comit gitea hace una conexion http con http://178.32.130.81:9000/hooks/build_image
3 years ago
Esa conexion http la recibe un servicio que hay en castiello si veis hay un paquete instalado llamado **webhook**
Este es un pequeño demonio (webhook- apt show webhook) que escucha conexiones http y lanza comandos dependiendo de lo que le envian por ahi en **/etc/webhook.conf** esta la configuracion
Ejecuta el comando **"/usr/local/bin/build_image"**
3 years ago
pero antes comprueba que el secret es ese valor y que es un comit en master <<<<< ?????????
Tiene varias secciones este config:
3 years ago
**id.** le dice cual es el nombre del hook que va a llamar
3 years ago
(si os fijais es el mismo nombre que esta configurado en el hook en gitea)
3 years ago
**execute-command.** que comando se va a ejecutar cuando reciba una conexion http
**pass-arguments-to-command.** pues eso, le pasa argumentos al comando, en este caso le pasa repository.name osea el nombre del repositorio
3 years ago
Gitea le hara una entrega por defecto http POST a esa url con un json (fichero estructurado), nosotros sacamos el nombre del repo de ese json [es un formato para estructurar datos, el fichero de configuracion webhook.conf que estamos mirando esta en json]
https://docs.gitea.io/en-us/webhooks/ <<<estudiar!!!!
https://en.wikipedia.org/wiki/JSON
3 years ago
~~~
3 years ago
Con los webhooks con cosas como el user, el repo, la rama ... y si queremos un token??? de autenticación.
Y así al hacer git push a master se dispara y se levantan los contenedores que se definan. Se buildean y hay cosas para que se relancen.
3 years ago
**Laminar:**
3 years ago
No esta en debian todavia, espero que entre pronto y si no a ver si le puedo meter un empujon. Laminar es un CI minimo, todo lo que hace es gestionar colas de tareas. Laminar es un demonio al que le dices ejecuta esto, y si el resto de tareas han termininado lo ejecuta. L web que tiene es de solo lecutra, osea no puedes mandarle ordenes por la web, asi que laminar lo soluciona. La idea es montar algo seguro que no sea facil de penetrar, por que esta es la maquina que genera todas las imagenes y la seguridad de sindominio depende de ella.
laminar es un demonio que ejecuta los trabajos que le decimos y en esa interfaz web muestra el resultado de los trabajos. laminar, se compone de un demonio que acepta tareas que ademas incopora un interfaz web para visualizarlas build_image es una de las tareas que tengo definidas en laminar. piensa en laminar como un duende que le dices ejecuta este escript y lo ejecuta y ademas te lo muestra en una web
3 years ago
**webhook** lanza un comando: [webhook lo que hace es añadir un trabajo a la cola de laminar]
vim /usr/local/bin/build_image
LAMINAR REASON=$1 /usr/bin/laminarc queu build_image image=$1
3 years ago
http://178.32.130.81:8080/ para ver que pinta tiene la interfaz web que es la interfaz web de laminar
3 years ago
systemctl restart laminar
3 years ago
una vez reiniciado el demonio de laminar
[[C++ es un lenguaje de programacion y GO es otro (por ejemplo lowry esta escrito en go) docker tambien es go]]
3 years ago
en **/var/lib/laminar/cfg/jobs** se ponen los scripts que quieres que laminar pueda ejecutar
3 years ago
Los que importan son 3:
3 years ago
**1.) build_image.run**
**2.) base_image.run**
**3.) check_updates.run**
3 years ago
3 years ago
**1.) El webhook lo que lanza es el build_image:**
3 years ago
${image} es un parametro que le pasa el webhook con el nombre del repo
3 years ago
si veis en la **linea 5 clona** el repo si no esta clonado ya
en la **linea 10 verifica** que todos los comits tienen una firma gpg valida
y en la **linea 15 buildea, tagea y pushea** la imagen al registry que esta corriendo en local
3 years ago
[[vim set nu para poner numeros a cada linea]]
https://git.sindominio.net/meskio/ansible_laminar/src/branch/master/build_image.run
3 years ago
la idea es que no necesitemos confiar en gitea, cada comit que hacemos en estibadores deberia estar firmado y si no lo esta laminar no buildea la imagen asi si gitea esta comprometido no nos pueden meter una imagen malefica.
3 years ago
3 years ago
tienen que comprometer nuestras maquinas donde tenemos nuestra clave gpg suena facil, pero hay algo de miga laminar se ejecuta con el user laminar [[(como el user ftp) laminar es un demonio, podrias configurarlo para ejecutarse con el user que quieras, aqui esta configurado para usar el usuario laminar esta instalado del paquete debian que da upstream que lo configura asi]]
3 years ago
*Meskio dice y yo me pierdo: Os muestro diferentes trabajos que tengo configurados en laminar y luego os cuento como esta montado el registry:
3 years ago
en la **linea 20** si os fijais hay un 'update_images ${image}'
3 years ago
este es un script que he puesto en laminar
Recordais que las imagenes pueden depender unas de otras de tal forma que tenemos un arbol de imagenes en el Dockerfile la primera linea suele ser image debian por ejemplo pero podriamos tener una imagen php que depende de nuestra imagen debian y una imagen nextcloud que depende de la imagen php
Cada vez que buildeamos una imagen puede que tengamos otras imagenes que dependan de esta imagen y que queramos rebuildear tambien. Si rebuildeamos la imagen debian deberiamos rebuildear todas las imagenes que usan debian como imagen base pues eso es lo que hace update_images mira en el registry que imagenes dependen de la imagen que acabamos de construir y las rebuildea
basicamente le dice a laminar que lance el trabajo build_image para esa imagen,
build_image es un script en /usr/loca/bin que tambien usa webhook para lanzar la tarea de buildear una imagen en laminar
3 years ago
grep "FROM ${base}"
Para filtrar lo que depende de la imagen nueva.
3 years ago
Al lanzar este escript le paso como parametro el nombre de la imagen si ves base es el tag del registry.sd.net de la imagen.
Resumiendo:
3 years ago
En el caso de tener: **debian->php->nginx**
3 years ago
Cuand buildeamos la imagen debian mirara en el registry y vera que hay que rebuildear php y cuando buildee php mirara en el registry y vera que hay que rebuildear nextcloud asi podemos rebuildear la parte del arbol de imagenes que hace falta … recorre toda la rama.
3 years ago
**2.) A parte del job 'build_image' tengo definidos otros dos trabajos**
3 years ago
base_image este es el que buildea la imagen de debian. Esta es especial y no la puedo buildear desde un repo usa debuerrotype, que es lo que usa la gente de debian para generar las imagenes de docker oficiales es como un debootstrap pero que genera un tar reproducible no hace falta que entendamos los detalles!!
“Simplemente” hace un debootstrap y usa docker import para generar una imagen 'from scratch'
La idea es no depender de la imagen que hay en dockerhub Asi que esto buildea la ultima version de debian stable scratch == de la nada. Generar una imagen docker que no viene de otra imagen.
3 years ago
**deboostrap** explicado en el primer dia de tutorial
3 years ago
3 years ago
**dockerhub** es el registry oficial de docker, con este proyecto estoy intentando no usarlo para nada por que no me fio de el
3 years ago
3 years ago
**debuerrotype** algo asi como debootstrap pero con imagenes reproducibles
3 years ago
https://github.com/debuerreotype/debuerreotype
3 years ago
**chroot** lo que hace es mover el / a una carpeta, como si todo lo que hay por encima no existiera.
3 years ago
3 years ago
La tarea **base_image** genera la imagen registry.sd.net/debian de la que dependen casitodo el resto de imagenes
3 years ago
https://git.sindominio.net/meskio/ansible_laminar/src/branch/master/base_image.run
3 years ago
si veis en la **linea 18 tambien llama a update_images** asi cuando se genera una nueva imagen debian regenera todas las imagenes que dependen de ella.
3 years ago
3 years ago
*he enseñado dos tareas que hay configuradas en laminar:
**build_image.run buildea una imagen desde un repo en git.sd.net
base_image.run buildea la imagen base de debian**
3 years ago
y me falta:
3 years ago
**check_updates.run**
3 years ago
este solo tiene una linea:
3 years ago
**check_updates "debian"**
3 years ago
este es un poco tonto, todo lo que hace es llamar a un script que esta en los scripts de laminar, check_updates lo que hace es comprobar si hay actualizaciones de algun paquete dentro de la imagen
basicamente hace un docker run apt update y mira si hay algo para actualizar
pero hay un check.updates en script
3 years ago
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Y aqui ya no se que hacen:
3 years ago
3 years ago
sudo su crontab -e
3 years ago
si os fijais todas las noches ejecuta el check_updates
asi que si alguna imagen tiene paquetes que necesitan ser rebuildeados los rebuildea
asi reconstruye la imagen de debian si hay actualizaciones y/o cualquiera del resto
queda poco de lo que tengo montado
la semana que viene podemos repasar lo que nos hayamos perdido de esto
y mirar como esta montado el registry
DUDAS:
imaginemos que usamos docker para montar mailman3
algo un dockerfile con dependencias a debian, postfix i el pakete de mailman3
pero para que no se borre cada vez que reinicio el proceso, tengo que guardar los datos en algun lado
le creo un volumen y lo asigno
lo normal seria meter postfix en una imagen y mailman3 en otra
ok, pero estamos en desarrollo y probamos mil cosas
instalo, desintalo, configuro, ....
como hago para desarrollar imagenes de docker de una manera un poco más sencilla
es decir, es un poco incomodo estar todo el rato reconstruyendo el dockerfile y haciendo los configs..
podemos levantarnos un entorno para testear cosas
o puedes levantar las imagenes docker en tu propia maquina para probarlas
lo bueno de docker es que lo que tienes en la imagen es lo mismo en el servidor que en tu maquina