Docker en DAW
Last updated
Was this helpful?
Last updated
Was this helpful?
Es una abstracción de la capa de hardware
Despliegues más sencillos
Ahorro costes
Aislamiento
...
Nativo o Bare Metal Hypervisor
Corre directamente en el hardware de la máquina, hacen la función de HAL (Hardware Abstraction Layer)
Ej: VMWare ESXI, Microsoft Hyper-V, Citrix/Xen Server
Host OS Hypervisor.
Corre sobre el sistema operativo, como una aplicación más.
Ej: VMware Workstation, VMware Player, VirtualBox, Parallel Desktop (MAC), ¿KVM?
No es adecuado cuando hay un workload elevado: Active Directory, bbdd...
Adecuados para entornos de test
Más baratos
Instalación más sencilla
Son una abstracción de la capa de aplicación
Más ligeros
Portabilidad
Contrato entre el sysadmin y el developer
Despliegues más rápidos
Mas eficientes -> menor coste
Son efímeros
Menor seguridad y aislamiento
Depende del host
Snapshots
Migraciones en caliente (VMWare vMotion)
Son efímeros
Herramienta open-source que nos permite realizar una virtualización ligera, con la que poder empaquetar entornos y aplicaciones que posteriormente podremos desplegar en cualquier sistema que disponga de esta tecnología
Los objetos principales en Docker son las imágenes, los contenedores y los servicios
Hay otros conceptos relacionados con ellos como volúmenes, registro de imágenes que los veremos conforme los necesitemos.
Plantilla que define todas las dependencias de mi aplicación
Es habitual que las imágenes se creen en base a otras (herencia)
Ejemplo:
Instancia ejecutable de una imagen
Son efímeros, la persistencia se logra mediante el uso de volúmenes
Cada contenedor se ejecuta en un entorno aislado (podemos controlar el nivel de aislamiento):
variables de entorno
Volúmenes montados
Interfaces de red
Podemos crear una imagen a partir de un estado del contenedor.
Los servicios permiten escalar contenedores a través de múltiples demonios de Docker, los cuales trabajarán conjuntamente como un enjambre (swarm).
Un contenedor -> Un proceso
Mejor escalabilidad
Mejor reutilización
Actualizaciones
En Linux Docker no es virtualizado, no hay un hipervisor.
Los procesos que corren dentro de un contenedor de docker se ejecutan con el mismo kernel que la máquina anfitrión.
Linux aisla los procesos, ya sean los propios de la máquina anfitrión o procesos de otros contenedores.
Controla los recursos que se le asignan a contenedores pero sin la penalización de rendimiento de los sistemas virtualizados.
Actualmente docker puede usarse en Windows
De las múltiples maneras posibles, la mejor es Docker Desktop
Windows puede crear contenedores Windows o contenedores Linux, pero no simultaneamente. Debemos decirle si vamos a usar contenedores de un tipo u otro.
El uso de contendeores linux requiere instalar LSW, Linux Subsystem for Windows. Es decir, poner un kernel linux a disposición de docker.
Dejo estas notas aunque no explicamos nada. Nosotros ya tenemos instalado docker.
Hasta el 2019 había dos productos:
Docker Enterprise Edition
Docker Community Edition
La versión Enterprise la compró la empresa Mirantis
Nos centraremos en la versión libre, que es la única a la que hace referencia ahora la web de Docker
Ir a la web de Docker
Se puede instalar el Docker Desktop en Windows
Se puede instalar el Docker Engine en Linux
Se puede desplegar una imagen mediante Vagrant que tenga todo
Se puede usar una OVA.
Lo más usual es usar imágenes basadas en Linux https://docs.docker.com/engine/install/ubuntu/
El proceso habitual de instalación es:
Añadir el repositorio de docker
Instalar Docker Engine
Configurar usuarios para uso de docker (sin privilegios root). Ver Linux PostInstall
Instalar Docker Compose
Utilizaremos la terminal (cliente docker)
Utilizaremos Visual Studio Code
Terminal integrada
Extensión Docker
Debug dentro de contenedores
Ejecutar un contenedor nuevo:
docker run
docker container run
Iniciar un contenedor existente:
docker start
docker container start
Parar un contenedor:
docker stop
docker container stop
Borrar contenedor
docker rm
docker container rm
Inspeccionar contenedor
docker inspect
docker container inspect
Ejecutar comando en un contenedor:
docker exec
docker container exec
Ver logs:
docker logs
docker container logs
Ver listado de imágenes
docker images
Borrar una imágen
docker rmi
Descargar imágen:
docker pull
Publicar imágen:
docker push
Traemos la última versión de la imagen de redis:
Aparecen datos útiles:
Órigen de la imágen
Versión
Tamaño que ocupa
Fecha de creación
Recordemos que una imagen en ejecución es un contenedor
CTRL + D para pararlo y podemos comprobar que ya no está
Mejor ejecutar en modo detached:
Si queremos arrancarlo de nuevo (no sabemos id)
Por defecto, no es necesario especificarlo. Los contenedores se comunican entre sí.
Son las más utilizadas
Déjemos que docker se encargue de todo :-)
Ejecutar comandos:
La forma más evidente es entrar a la terminal del contenedor:
Variables de entorno
Estructura ficheros
pocos comandos disponibles!
Comprueba que efectivamente los contenedores se pueden comunicar entre sí.
Accede al fichero /etc/host de cada contenedor para ver su ip
Haz un ping entre contenedores
Los contenedores tienen un nombre aleatorio, pero se puede dar de forma explícita:
Comprueba el estado de imágenes y contenedores de tu equipo
Elimina todas las imágenes
Elimina todos los contenedores (también los parados)
Estado actual:
Borrar imágenes:
Borrar contenedores:
Descarga redis:latest y comprueba su versión
Descarga esa versión específica (redis:x.y.z)
Comprueba que tienes dos imágenes al hacer un listado pero que:
Ambas ocupan el mismo tamaño
Son idénticas:
Mismo IMAGE ID
No se ha producido ninguna descarga de layers adicionales.
Ejecutar contenedor latest y ver versión
Descargar versión actual y comprobar que ambas son idénticas
No es aconsejable utilizar imágenes con etiqueta latest
Se pueden producir breaking changes
No está claro el versionado de la imágen.
Podemos crear una imagen de cero pero lo normal es usar o partir de una ya creada.
Hay un registro oficial de imágenes proporcionado por Docker: Docker Hub
También podemos crear nuestro propio servicio.
Un repositorio de imágenes: descarga y publicación.
Repositorio de imágenes oficiales de Docker, de alta calidad.
Repositorio de imágenes verificadas publicadas por terceros.
Gestor de equipos y organizaciones: acceso a repositorios privados.
Autobuilds: crea nuevas versiones de imágenes en base a cambios en repos de Github/Bitbucket
Webhooks: Ejecuta acciones después para integrar DockerHub con otros servicios
Desde final del 2020 Docker impuso limitaciones en el uso de su registro.
100 descargas de imágenes cada 6 horas para usuarios anónimos (por IP)
200 descargas de imágenes cada 6 horas para usuarios autenticados
Cuentas pro y team para aumentar los límites.
Conclusión: ¡¡¡Debemos hacer docker login!!!
Crear cuenta en Docker Hub
Hacer login desde consola
Se crea un fichero de configuración en $HOME/.docker/config.json
Las siguientes veces que nos autentiquemos, al hacer docker login leerá directamente el fichero
Observa que si cerramos la sesión la entrada auths del fichero config.json queda vacía
Si queremos un repositorio compartido entre varios usuarios necesitamos crear una organización
Desde Junio 2021 los autobuilds son de pago
Si usamos GitHub podemos usar GitHub Actions
Docker viene configurado por defecto para buscar las imágenes de Docker Hub
Es posible usar nuestro propio registro:
Podemos usar la misma implementación vanilla del Docker registry que usa Docker Hub
Otros más avanzados como Harbor (Open Source, era VMWare), Artifactory (JFrog), Nexus (Sonatype), etc.
Docker también ofrece una versión enterprise de su registro llamada Docker Trusted Registry (DTR)
Google Container Registry (GCR), Amazon Elastic Container Registry (ECR), Azure Container Registry (ACR), Quay (Redhat, versión On-Prem y versión cloud), Gitlab Container Registry, Github Packages, etc.
Pueden ser públicos o privados (1 gratis)
Se crean desde Docker Hub
Cada repo puede tener una o varias imágenes, en función de la tag
Las imágenes se publican mediante el comando
Se pueden consultar mediante docker search <keyword>
Lo más habitual es hacerlo vía web, no con consola
redis y redis-commander dockerizados
Evitamos problemas de dependencias
las máquinas host se quedan "limpias"
Paquete de npm para acceder a Redis desde el navegador
Instalación:
Debemos instalar nodejs, la versión de la distribución de Ubuntu es antigua (v10)
Instalamos usando el PPA oficial
Queremos que se comuniquen entre sí utilizando redes bridge:
default: las que utilizabamos hasta ahora
user defined:
Interacionan solo los contenedores definidos en esta red
Hay resolución de nombres
Opciones
Construir nuestra propia imagen (todavía no sabemos)
Utilizar una imagen ya preparada en Docker Hub:
Menos propenso a errores
Más rápido
Modificar una imagen ya preparada:
¿Dockerfile? ¿FROM?
Creación de red:
Uso de red:
Comprueba que efectivamente funciona (docker log)
Entra a uno de los dos contenedores y comprueba el ping por name
Monta un escenario como el anterior con MySQL o MariaDB y phpMyAdmin
Comprueba las versiones de imágenes de httpd
¿Vía web?
¿Vía docker search?
docker search no nos sirve
Vía web aunque es algo "laborioso"
Prueba y error con la versión que queremos
Usando hub tool
Ejecuta una imagen 2.2 de Apache en DockerHub y modifica el index.html para que aparezca HolaMundo
¿Cómo has modificado el index.html?
Instalando en el contenedor un editor y entrando mediante:
Mediante el comando cp de Docker
Mediante el plugin Docker de Visual Studio Code (lo más sencillo)
Imagina que hay un bug importante en Apache que está arreglado en la versión 2.4
Actualiza la versión de nuestra aplicación HolaMundo anterior a Apache2.4
Las dos opciones más adecuadas serían:
Generar una nueva imagen de nuestra aplicación
No sabemos hacerlo todavía
Realmente tampoco lo habíamos hecho, utilizabamos directamente la imagen de Apache
Buscar persistencia de algún modo en nuestro contenedor efímero.
Usámos volúmenes o bind-mounts
Docker gestiona el volumen de forma transparente
Ejemplo con nginx:
El volumen se mapea a un directorio físico acccesible no solo por Docker.
Si el directorio no existe, se crea.
Aprender a crear ficheros Dockerfile
Aprender a crear y publicar imágenes
Entender el concepto de layers en imágenes.
Plantilla en texto plano que define las dependencias de mi aplicación y la imagen.
Cada línea del fichero Dockerfile contiene una serie de comandos que generan una capa en la imágen
Se ejecutan de manera secuencial
Existe una caché que funciona por cada línea o capa.
Es habitual que las imágenes se creen en base a otras (herencia)
Una imágen es un conjunto de capas de solo lectura, generadas por el Dockerfile
¿Qué es un contenedor?
Una imagen en ejecución
Una imágen con una capa de lectura/escritura encima del resto de capas llamada container layer
Cualquier cambio que hagamos en un contenedor, se lleva a cabo en la container layer
Vamos a crear una imagen que visualice el contenido de un fichero al ejecutar el contenedor
Crea un directorio y coloca un fichero holaMundo.txt con el texto ¡Hola Mundo!
Crea un fichero Dockerfile en el mismo directorio con el siguiente contenido:
Creamos la imagen y etiquetamos:
Ejecutamos la imagen:
Subimos la imagen con todas sus tags
FROM nos sirve para partir de una imagen previa
RUN: ejecuta comandos
COPY: copia ficheros de nuestro contexto a la imagen
CMD: Ejecuta un comando al iniciar el contenedor
Más info en las referencias de Dockerfile
Podemos ver las capas también mediante docker inspect y docker history
No todos los pasos generan una nueva capa, algunos comandos solo alteran configuración (CMD, ENV, ENTRYPOINT, EXPOSE, etc.).
La herramienta Dive nos sirve para explorar con más detalle las capas de las imágenes de Docker https://github.com/wagoodman/dive
Las líneas del Dockerfile en principio se cachean
Si se produce un MISS ya no se usa más caché en esa compilación
Escribir las líneas más "frecuentes primero"
Si hay líneas "con dependencias", ej apt-get update y apt-install juntas.
Si no queremos caché (ni para FROM image):
Crea una imagen que se base en Ubuntu y que permita:
Editar ficheros con vim
Ejecutar el comando ping
Observa el -y para evitar la parte interactiva del comando apt-get install
Comprueba con dive los recursos utilizados
Crea una imagen a partir de las instrucciones del ejercicio anterior (vim + ping) pero con el comando docker commit
Verifica la imagen (capas y tamaño)
Vamos a crear una versión v2.0 de nuestro holaMundo, que en vez de coger el fichero de local lo coja de una URL mediante el comando ADD
Compila la imagen y ejecútala
Cambiaremos los datos del fichero apuntado por la URL
Compila de nuevo la imagen y ejecuta otra vez
¿Qué pasa? ¿Comó lo solucionas?
En docker, las imágenes se construyen a base de capas
Cada capa contiene únicamente las diferencias respecto a la capa padre.
Docker utiliza mecanismos de union filesystems para montar en una carpeta la combinación de las distintas capas.
Al crear un contenedor, Docker añade una capa adicional (la capa de contenedor), que es la única sobre la que es posible escribir.
El contenedor modifica aparentemente la imagen base, como si tuviera una copia real, pero únicamente está modificando esta última capa.
Podemos crear múltiples contenedores sobre una misma imagen, reutilizando todas las capas excepto la capa de contenedor.
Al destruir un contenedor, esta capa con las modificaciones se destruye.
Borrar un archivo en un paso del Dockerfile no elimina ese archivo de las capas anteriores de la imagen.
El archivo sigue presente, pero no es accesible desde el contenedor.
Es la forma de comportarse de los union filesystems
Al hacer un build se envían al daemon docker los ficheros de la ruta especificada como contexto:
Es recomendable usar una carpeta separada para almacenar el contexto.
Podemos crear un fichero .dockerignore
Used: Las que aparecen al hacer un docker ps -a
Unused: Las que no aparecen (se usaron en su momento pero se ha borrado el contenedor)
Dangling images: Imágenes que se crean sin nombre, y se muestran como <none>.
Útil cuando estamos haciendo pruebas de compilación
Conforme vamos usando docker, descargando imágenes... empezamos a ocupar espacio
Comprobar el espacio usado:
Eliminación de imágenes:
Se crea la primera imagen que sirve para obtener lo que se usa en el segundo stage (ver --from=n)
Todo lo que no se usa queda fuera del último stage que es el definitivo
Útil para entorno de compilación
Se reduce el tamaño final de la imagen al quedarnos solo con el ejecutable
Herramienta para definir y ejecutar aplicaciones con varios contenedores Docker.
Se definen los contenedores (servicios) de la aplicación mediante un fichero YAML.
Se levantan mediante el comando docker-compose up
Vamos a analizar un caso sencillo con 3 contenedores:
web server con php
db con MySQL
phpMyAdmin
Clona este repositorio
Óptimo para producción, más rápido que un build y todo empaquetado
Crea una imagen de Apache con un HolaMundo
Ejecútala mediante docker-compose.yml
Para dar un servicio externo, en web el puerto es el 80
¿Cómo hacemos para que los servicios anteriores funcionen todos en el 80?
Proxy inverso en función de la url
Similar a un virtual host de apache pero que se configura solo en función de las peticiones que le llegan al docker daemon
Usaremos nginx-proxy o traefik
Seleccionar en DockerHub una imagen de Odoo
Desplegar la imagen con la bbdd adecuada como servicios (usando docker-compose.yml)
Seleccionar en DockerHub una imagen de Dolilbarr
Desplegar la imagen con la bbdd adecuada como servicios (usando docker-compose.yml)
En la web de Docker hay ejemplos de Wordpress, Django o Rails
Una buena forma es usar dockerize
Instalación:
¿Añadir un servicio de crontab a nuestro contenedor?
¡¡¡no!!! Filosofía docker: 1 contenedor = 1 servicio
Podemos crear un crontab en el host con comandos como:
Propongo uso de rsnapshot
rsync para hacer instantáneas con hard links
Interfaz gráfico para su gestión
Y para hacer deploy en Docker
¿Existe esto?
Ver uso contenedores
Procesos en ejecución
Consultas al demonio de docker
Consultas específicas por contenedor
Configuraciones intrínsecas a los servicios (por ej. mod_status en Apache)
El kernel si no tiene suficiente memoria arroja un OOME (Out of memory exception).
Empieza a matar procesos para liberar memoria
Puede tirar todo el sistema si mata el proceso equivocado (por ej. el demonio de Docker)
Docker ajusta la prioridad de OOM del demonio para reducir la probabilidad de recibir un kill.
La prioridad de los contenedores no se debe ajustar.
El host debe tener suficiente memoria
Para evitar errores se debe limitar el uso de memoria de los contenedores
La configuración cambia bastante entre versiones de docker-compose
Buena opción si trabajamos en equipos Windows y no queremos preocuparnos de despliegues
Descargamos Vagrant
Configuramos Vagrant (ver después) o hacemos un git clone de https://github.com/juanda99/vagrant-deploy-virtualbox-docker
Nos situamos en un directorio e inicializamos mediante vagrant init
Modificamos el fichero Vagrantfile creado con algo como:
Añadimos servicios mediante docker-compose cuyo punto de entrada se mapee al host en el 8000
Development
CI/CD
Deployment
Es un monitor que orquesta el acceso de varios SO a los recursos de un servidor físico.
Usar soluciones ya preparadas: Ofelia