diff --git a/tuto-estibadores.md b/tuto-estibadores.md index f6be35c..ad216ef 100644 --- a/tuto-estibadores.md +++ b/tuto-estibadores.md @@ -11,13 +11,13 @@ https://docs.docker.com/develop/develop-images/dockerfile_best-practices/ http://xfmro77i3lixucja.onion/book/ivKkU9FIkf59BV_Z -Primer dia de tutorial: - +# Primer dia de tutorial: +# 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. -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. +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. 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. @@ -25,102 +25,94 @@ Es decir que podemos tener un arbol grande de imagenes unas basadas en otras, de -como hacer imagenes, como ejecutarlas y que es un registry: +**como hacer imagenes, como ejecutarlas y que es un registry:** -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. +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. -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. +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. -Asi que ese Dockerfile basicamente coje la imagen base de debian e instala el paquete 'docker-registry'. -Dockerfile se usa con docker build. +Asi que ese Dockerfile basicamente coje la imagen base de debian e instala el paquete **'docker-registry'**. +Dockerfile se usa con **docker build**. 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. -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 -mas o menos, 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 +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** -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] +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] -Por defecto las imagenes se ejecutan como root, user lo uso para que le quite privilegios y se ejecute como el usuario docker-registry +***Por defecto las imagenes se ejecutan como root, user lo uso para que le quite privilegios y se ejecute como el usuario docker-registry Esto es como en el lxc lo de hacer los contenedores unprivileged -añadiendo user hacemos que la imagen sea unpvileged. +añadiendo user hacemos que la imagen sea unpvileged.*** ->>>>>>>> -[[ para entrar en la maquina de meskio y jugar, bita@178.32.130.81]] -[[para compartir la terminal tmux attach]] -[[para descargar la imagen git clone https://git.sindominio.net/estibadores/registry]] -en otro momento te cuento como se genera la imagen de debian, que es mas complicada -[[la fingerprint SHA256:gy0DyDcwxDBIg6iEQ/93VT6gCynBVOiK2TC1fyxfNnI]] -<<<<<<<<< +[[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]] -2.) Si entras en el repo puedes buildear la imagen con docker build: +2.) Si entras en el repo puedes **buildear la imagen** con **docker build**: -$ docker build -t minuevaimagen . --t es para darle un nombre a la imagen + $ docker build -t minuevaimagen . +**-t** es para darle un nombre a la imagen docker build hay que ejecutarlo en la carpeta donde tienes el Dockerfile -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 +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 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. -De momento hemos construido la imagen, pero todavia no la hemos ejecutado, para ejecutarla: +De momento hemos **construido** la imagen, pero todavia no la hemos **ejecutado**, para ejecutarla: -docker run -d test1 -y si haces docker ps la veras en ejecucion --d despues de docker run para que no se te lleve la terminal + docker run -d test1 +y para verla en ejeccucion + docker ps +**-d** despues de docker run para que no se te lleve la terminal matar tu imagen con un ctrl-c -ahora no esta tu imagen en ejecucion, solo hay otras imagenes que yo tengo 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 +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** para ello se tendra que usar el container_id que te sale en el docker ps -docker logs 798585f1f771 (id que sale en docker ps) -docker stop [id] (para pararla) + docker logs 798585f1f771 +(id que sale en docker ps) + docker stop [id] +(para pararla) -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.) 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*** -*Primero a aprender a abrir puertos +**Primero a aprender a abrir puertos** 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. --p le dice que el puerto 5000 de dentro del contenedor lo tiene que mapear al puerto 5001 del host. +**-p** le dice que el puerto 5000 de dentro del contenedor lo tiene que mapear al puerto 5001 del host. -docker run -d -p 5005:5000 test1 -curl http://localhost:5005/v2/_catalog + docker run -d -p 5005:5000 test1 + curl http://localhost:5005/v2/_catalog Hasta puedes hacer un curl desde tu portatil y funcionara: -curl http://178.32.130.81:5005/v2/_catalog + curl http://178.32.130.81:5005/v2/_catalog Asi que el puerto 5005 ahora esta abierto al mundo entero. -*Segundo, para esa imagen que le vamos a pasar un volume +**Segundo, para esa imagen que le vamos a pasar un volume** 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. -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 +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** 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 -el -v es un parametro de docker run cuando digo he creado /tmp/test1 lo que he hecho es mkdir y chmod para darle permisos. +**-v** es un parametro de docker run cuando digo he creado /tmp/test1 lo que he hecho es mkdir y chmod para darle permisos. -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 @@ -128,76 +120,77 @@ lo que hacemos es mapear /tmp/test1 (que existe en la maquina en la que estas) e Entonces el comando es docker run -v /tmp/test1:/var/lib/docker-registry -docker run -d -p 5005:5000 -v /tmp/test1:/var/lib/docker-registry test1 + docker run -d -p 5005:5000 -v /tmp/test1:/var/lib/docker-registry test1 [el container id cambia de una ejecucion a otra puedes tener multiples veces la misma imagen ejecutandose con diferentes ids] -docker ps -docker stop [id] << (para prar el registry) -docker run -d -p 5005:5000 -v /tmp/test1:/var/lib/docker-registry test1 + docker ps + docker stop [id] + (para prar el registry) + docker run -d -p 5005:5000 -v /tmp/test1:/var/lib/docker-registry test1 al montar el volumen estamos salvando la imagen en la que hemos trabajado. -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 +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 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) -Para poder subir una imagen primero tenemos que taguearla para el registry que usemos: +Para poder subir una imagen primero tenemos que **taguearla** para el registry que usemos: -docker tag test1 localhost:5005/test1 + docker tag test1 localhost:5005/test1 Con esto le decimos que la imagen test1 tambien tiene el nombre localhost:5005/test1 -y ahora podemos pushearla al registry: +y ahora podemos **pushearla** al registry: -docker push localhost:5005/test1 + docker push localhost:5005/test1 -Para ver los nombres de las imagenes puedes usar docker images | grep localhost:5005 +Para ver los nombres de las imagenes puedes usar **docker images | grep localhost:5005** 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: -docker run 178.32.130.81:5005/test1 + docker run 178.32.130.81:5005/test1 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 ->>>> -otro dia hablamos de docker compose ->>>> + +[otro dia hablamos de docker compose] -Segundo dia de tutorial: +# Segundo dia de tutorial: +# 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 -si mirais en ese repo hay un docker-compose.yml +si mirais en ese repo hay un **docker-compose.yml** + +En este file hay un restart: -En este file hay un restart -registry: - restart: always - image: sindomninio + registry: + restart: always + image: sindomninio -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. +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. -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.]] +[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.] -El objetivo es atomizar y coordinar con docker compose y no hacer dockers mas complejos. +El objetivo es **atomizar y coordinar** con **docker compose** y no hacer dockers mas complejos. 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. -Para lanzar la imagen con docker compose: docker-compose.yml que estas en el directory donde nos encontramos -docker-compose up -d +Para lanzar la imagen con docker compose: **docker-compose.yml que esta en el directory donde nos encontramos** + docker-compose up -d ->>>>> -Pruebas que tengo de como me gustaria el CI (integracion continua) para generar las imagenes de sindominio. +Pruebas que meskio tiene de como le gustaria el **CI (integracion continua)** para generar las imagenes de sindominio. 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 @@ -205,71 +198,65 @@ 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 -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" +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"** pero antes comprueba que el secret es ese valor y que es un comit en master <<<<< ????????? Tiene varias secciones este config: -id. le dice cual es el nombre del hook que va a llamar +**id.** le dice cual es el nombre del hook que va a llamar (si os fijais es el mismo nombre que esta configurado en el hook en gitea) -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 +**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 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/ <<php->nginx +En el caso de tener: **debian->php->nginx** 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. -2.) A parte del job 'build_image' tengo definidos otros dos trabajos +**2.) A parte del job 'build_image' tengo definidos otros dos trabajos** 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. -deboostrap explicado en el primer dia de tutorial +**deboostrap** explicado en el primer dia de tutorial -dockerhub es el registry oficial de docker, con este proyecto estoy intentando no usarlo para nada por que no me fio de el +**dockerhub** es el registry oficial de docker, con este proyecto estoy intentando no usarlo para nada por que no me fio de el -debuerrotype algo asi como debootstrap pero con imagenes reproducibles +**debuerrotype** algo asi como debootstrap pero con imagenes reproducibles https://github.com/debuerreotype/debuerreotype -chroot lo que hace es mover el / a una carpeta, como si todo lo que hay por encima no existiera. +**chroot** lo que hace es mover el / a una carpeta, como si todo lo que hay por encima no existiera. -La tarea base_image genera la imagen registry.sd.net/debian de la que dependen casitodo el resto de imagenes +La tarea **base_image** genera la imagen registry.sd.net/debian de la que dependen casitodo el resto de imagenes https://git.sindominio.net/meskio/ansible_laminar/src/branch/master/base_image.run -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. +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. ->>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 +*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** y me falta: -check_updates.run +**check_updates.run** este solo tiene una linea: -check_updates "debian" +**check_updates "debian"** 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 +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Y aqui ya no se que hacen: -sudo su crontab -e + sudo su crontab -e si os fijais todas las noches ejecuta el check_updates asi que si alguna imagen tiene paquetes que necesitan ser rebuildeados los rebuildea @@ -345,5 +336,3 @@ 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 - -