¡Esta es una revisión vieja del documento!
Tabla de Contenidos
Docker a fondo e Introducción a Kubernetes: aplicaciones basadas en contenedores
Notas del curso Docker a fondo e Introducción a Kubernetes: aplicaciones basadas en contenedores del Clúster TIC de Galicia.
- Horas: 60
- Fecha Inicio: 13/02/2024
- Fecha Fin: 09/04/2024
Objetivos
En este curso aprenderás a dominar Docker desde cero hasta el nivel avanzado, y tendrás las nociones necesarias para empezar a trabajar con Kubernetes.
En la primera parte del curso, aprenderás los conceptos básicos de Docker, como qué es y cómo funciona, además de conocer los usos que tiene y lo que es un contenedor y una imagen. Aprenderás a gestionar imágenes y contenedores, cómo crear imágenes y subirlas a un repositorio.
En la segunda parte, abordaremos escenarios multicontenedor con herramientas como docker-compose, además de aprender a trabajar con networking en Docker y cómo usar contextos.
La tercera parte se centra en escenarios avanzados para, por ejemplo, usar Docker para compilar y crear imágenes sin tener que instalar el framework (como .NET o Node) o cómo depurar utilizando contenedores. También sabrás cómo sacar partido a la tecnología de contenedores en entornos Windows y no solo Linux.
En la última parte del curso abordaremos Kubernetes, el orquestador de contenedores más utilizado del mundo. Aprenderás los conceptos básicos de Kubernetes, cómo funciona, cómo crear y configurar pods, cómo desplegar aplicaciones sin estado y cómo exponer tu aplicación al exterior.
Con este curso, tendrás las habilidades necesarias para crear y desplegar aplicaciones en contenedores con Docker y Kubernetes, y estarás preparado para aplicar tus conocimientos en proyectos reales tanto para desarrollo como para despliegue de sistemas.
Temario
- Parte 1. Conceptos básicos de Docker
- Módulo 1: Introducción a Docker.
- Módulo 2: Gestión de imágenes y contenedores
- Módulo 3: Creación de imágenes
- Parte 2. Escenarios multi-contenedor
- Módulo 4: Docker Compose
- Módulo 6: Un ejemplo práctico real
- Módulo 7: Las redes en Docker
- Módulo 8: Contextos en Docker
- Parte 3. Escenarios “avanzados” con Docker
- Módulo 9: Usar Docker para compilar
- Módulo 10: Contenedores Windows
- Módulo 11: Depurar contenedores
- Módulo 12: Visual Studio Code "Dev Containers"
- Parte 4. Kubernetes (k8s)
- Módulo 13: Introducción a Kubernetes
- Módulo 14: Pods y servicios
- Módulo 15: Despliegues declarativos en Kubernetes
- Módulo 17: Configurar contenedores
- Módulo 18: Exponer la aplicación al exterior
Preguntas
Conceptos básicos de Docker
¿Qué diferencia hay entre las instrucciones ARG y ENV del Dockerfile?
- ENV admite valores por defecto, mientras que ARG no
- Ninguna. Son dos comandos equivalentes
- ARG crea una variable de entorno del contenedor y ENV crea una variable en tiempo de construcción
- ENV crea una variable de entorno del contenedor y ARG crea una variable en tiempo de construcción (correcto)
¿Qué diferencias hay entre bind mounts y volúmenes?
- Los bind mounts se ven como un directorio en el contenedor. Los volúmenes como una unidad externa
- Los volúmenes pueden persistir en almacenamientos externos. Los bind mounts solo en el host (correcto)
- Los bind mounts son de lectura y escritura. Los volúmenes de solo lectura
- Los volúmenes son manejados por Docker, los bind mounts solo mapean una carpeta del host al contenedor (correcto)
- La CLI
docker volumespermite ver y eliminar volúmenes y bind mounts - La CLI
docker volumespermite ver y eliminar volúmenes, pero no bind mounts (correcto)
Dadas las siguientes instrucciones del Dockerfile:
CMD node server.js
y
CMD ["node", "server.js"]
Marca todas las opciones correctas.
- La primera es incorrecta. Solo la segunda es válida
- La segunda es incorrecta. Solo la primera es válida
- Ambas son correctas (correcto)
- La primera establece “node server.js” como comando inicial del contenedor
- La segunda establece “node server.js” como comando inicial del contenedor (correcto)
- La primera establece “/bin/sh - c 'node server.js'” como comando inicial del contenedor (correcto)
- La segunda establece “/bin/sh - c 'node server.js'” como comando inicial del contenedor
La imagen “my-image” recibe peticiones por su puerto 5000. Creas un contenedor usando: docker run -p 5000:5000 my-image ¿Cómo envías peticiones al contenedor?
- Usando
http://my-image:5000 - Usando
http://localhost:5000(correcto) - No puedes acceder al puerto 5000 del contenedor desde tu máquina
- Usando
http://localhost - Usando
http://my-image
Tienes un contenedor de MySql. Te das cuenta de que cada vez que lo pones en marcha (con docker run), los datos de la base de datos se han perdido. ¿Qué soluciones hay? (Marca todas las correctas)
- Asegurarse de no parar nunca el contenedor
- Usar un bind mount, de forma que los datos de la bbdd se guarden en el host (correcto)
- Usar un volumen (correcto)
- Tener dos contenedores MySql configurados en clúster, de forma que siempre haya al menos uno de ellos levantado
¿Qué relación hay entre contenedores y microservicios?
- Los contenedores no son apropiados para arquitecturas de Microservicios
- Si usas microservicios debes usar contenedores
- Si usas contenedores ya estás usando microservicios, aunque es posible microservicios sin contenedores
- Los contenedores pueden ayudar en arquitecturas de Microservicios (correcto)
¿Qué relación hay entre imagen y contenedor?
- Una imagen es un contenedor pausado. La imagen puede copiarse a otro ordenador y continuar la ejecución
- Una imagen describe los datos de un contenedor y su configuración. A partir de una imagen se crean contenedores (correcto)
- A partir de un contenedor se crean imágenes para conservar distintos estados de su ejecución y volver a ellos más tarde
- Un contenedor contiene (de ahí su nombre) varias imágenes, permitiendo cambiar de una a otra
Marca todas las respuestas correctas referentes a los bind mounts:
- Los usamos cuando queremos compartir ficheros entre el contenedor y el host (correcto)
- Un bind mount puede persistirse en almacenamientos externos (discos virtuales, etc)
- El contenedor no puede escribir datos en un bind mount ya que esos son de solo lectura
- Un bind mount mapea un directorio del host en un directorio del contenedor (correcto)
Desde un terminal ejecutas tres veces el comando “docker run -d hello-world”. ¿Qué es lo que ocurre?
- No puedes ejecutarlo tres veces, el primer “docker run” bloquea el terminal hasta que el contenedor termine
- La segunda vez te da un error de que el contenedor “hello-world” ya existe
- Terminas con tres contenedores distintos ejecutando tres veces la imagen “hello-world” (correcto)
- Terminas con un solo contenedor ejecutando “hello-world”, ya que la 2a y 3a vez que usas el comando este se ignora por ya existir el contenedor
¿Qué hace la sentencia FROM del Dockerfile?
- Indica la imagen base de la imagen que se está definiendo (correcto)
- Indica la URL de donde descargar el sistema de ficheros de la imagen
- Indica la ubicación en disco de la imagen base
- Indica qué ficheros forman parte del sistema de ficheros de la imagen
Escenarios multicontenedor
¿Qué pasa si usas el comando?: docker compose up -f compose-file1.yml -f compose-file2.yml
- Compose combina ambos ficheros en un único fichero y levanta la aplicación definida por ese “fichero combinado” (correcto)
- Compose levanta primero la aplicación del primer fichero y luego la aplicación del segundo
- Da un error ya que solo se admite un fichero compose
- Compose levanta primero la aplicación del primer fichero y cuando se termina (todos los contenedores finalizan) levanta la aplicación del segundo
¿Es buena idea que la configuración forme parte de la imagen?
- No. Lo ideal es que la configuración la proporcione el entorno (correcto)
- Sí: debes usar instrucciones ENV para establecer dicha configuración
- Sí: debes usar instrucciones COPY para copiar los ficheros de configuración en la imagen
- Sí, porque de esa manera la imagen funciona con independencia del entorno.
Para configurar compose usamos:
- Ficheros en formato XML
- Ficheros en formato JSON
- Ficheros en formato YAML (correcto)
- Ficheros en un formato propio de compose
Tienes el siguiente fichero compose:
version: '3.4' services: helloworld: image: dockercampusmvp/go-hello-world ports: - "80:80" db: image: mysql profiles: - db
Si lo ejecutas con docker compose --profile db up, ¿Cuántos contenedores se crean?
- Se ejecuta un contenedor ejecutando la imagen
dockercampusmvp/go-hello-world - Se ejecuta un contenedor ejecutando la imagen
mysql - Se crea un contenedor ejecutando la imagen
dockercampusmvp/go-hello-worldy otro ejecutando la imagenmysql(correcto) - Da error, ya que el fichero es incorrecto
Tienes un contenedor que:
- Escucha por su puerto 80
- Su IP propia es 10.72.10.3
- El puerto 80 del host está mapeado al 8000 del host
Abres un navegador y verificas que http://localhost:8000 funciona correctamente. No obstante hay otro contenedor ejecutándose que se intenta conectar con este. Cuando intenta usar http://localhost:8000 da error. Ambos contenedores se han lanzado usando docker compose up.
¿Qué URL se podría usar para que el segundo contenedor se pueda comunicar con el primero?
http://10.72.10.3:8000http://10.72.10.3:80(correcto)http://localhost:80http://localhost:8000es correcto, pero debe abrirse el firewall de la red de Dockerhttp://localhost:8000es correcto, pero ambos contenedores deben estar en la misma red docker
Conceptos avanzados de Docker
Un desarrollador te pasa un fichero en Kotlin. No tienes SDK ni runtime de Kotlin en tu máquina, pero necesitas ejecutar el proyecto. ¿Qué harías?
- Crear una máquina virtual con el SDK de Kotlin y ejecutar el proyecto allí.
- Instalarte el SDK de Kotlin
- Crear un Dockerfile multi-stage build para generar una imagen de Docker y ejecutarla (correcto)
- Ir con un compañero que tenga Kotlin instalado
Un desarrollador está haciendo pruebas con Docker y ha ejecutado el comando docker build -t myimage .. El Dockerfile es muy sencillo, simplemente contenía una sentencia FROM, pero la construcción de la imagen ha tardado mucho tiempo. El desarrollador ya tenía la imagen base descargada. ¿Qué otra posible causa puede haber?
- Ha ejecutado la sentencia desde un directorio con un contexto de build muy grande. (correcto)
- Falta de memoria RAM
- Falta de espacio en disco, que provoca el uso de swap
- Versión antigua de docker, que no usa BuildKit
Tienes un servidor de docker, pero quieres controlarlo desde tus ordenadores. ¿Cómo puedes hacerlo, de la forma más sencilla?
- Pones el servidor en un lugar accesible y cuando sea necesario te desplazas allí y usas docker
- Instalas algún sistema de control remoto (como p. ej. TeamViewer) y accedes al servidor desde tu ordenador
- Usas un contexto de docker, apuntando al daemon de Docker del ordenador remoto (correcto)
- Abres una conexión SSH, entras en el ordenador remoto y usas docker
¿Es admisible que un contenedor use stdout para lanzar trazas?
- Es irrelevante: toda salida a stdout es ignorada y se pierde
- Sí, ya que eso permite el uso de docker logs para analizar las trazas (correcto)
- No. Los contenedores no tienen acceso a stdout (genera un error)
- Sí, ya que eso permite el uso de docker cp para analizar las trazas
¿Cuál es la mejor manera de pasarle un fichero de configuración a un contenedor? Sin este fichero el contenedor da error nada más arrancar
- Abriendo sesión interactiva con el contenedor, crear a mano el fichero de configuración y luego usar
docker commitpara crear una nueva imagen - Copiando el fichero con el comando “
docker cp” - Usando un “bind mount” (correcto)
- Añadiendo una sentencia
COPYen elDockerfilepara copiar el fichero de configuración y recrear la imagen
Resumen comandos
Listado de todos los comandos que salen en el curso:
docker --version: verifica la versión de Docker instalada.docker contextdocker context ls: listar contextosdocker context use <NOMBRE_CONTEXTO>: alternar contexto.docker pull <NOMBRE_IMAGEN>: descarga una imagendocker images: lista las imágenes descargadasdocker images -q: solo muestra las IDs de las imágenesdocker images -f: filtra las imágenes según criteriodocker images -a: muestra las imágenes intermedias.docker images --no-trunc: muestra el ID entero de las imágenes.
docker rmi <IMAGEN>: borra una imagen (hay que indicar la ID para que la borre realmente).docker rmi $(docker images -q): borra todas las imágenes que tengamos.docker rmi -f <IMAGEN>: borra la imagen aunque tenga contenedores en marcha que la usen.docker rmi $(docker images -f "dangling=true" -q): elimina las imágenes que no están en uso por otras imágenes.
docker run <NOMBRE_IMAGEN>: crea un contenedor a partir de una imagendocker run –name <NOMBRE_CONTENEDOR> <NOMBRE_IMAGEN>: establecer un nombre al contenedor.docker run -d <NOMBRE_IMAGEN>: libera el terminal tras la creación (segundo plano).docker run -d -p 8080:80 <IMAGEN>: redirige el puerto 8080 del host al 80 del contenedor creado.
docker ps: lista los contenedores en ejecución.docker ps -a: lista los contenedores en ejecución y parados.docker ps -q: lista solo las IDs de los contenedores en ejecución.docker rm $(docker ps -q -a): borra todos los contenedores.docker rm $(docker ps -q -a -f): borra todos los contenedores (incluso los que están en marcha).
docker stop <CONTENEDOR>: detiene un contenedordocker kill <CONTENEDOR>: mata el proceso del contenedor.docker start <CONTENEDOR>: reinicia un contenedor.docker inspect <ID_CONTENEDOR> -f "{{ .NetworkSettings.IPAddress }}": muestra la IP del contenedordocker build . -t <NOMBRE>: crea una imagen llamadaNOMBREa partir de unDockerfiledel mismo directorio.docker save <MI_IMAGEN> -o <MI_IMAGEN.tar>: exporta una imagen a un fichero.tar.docker history <IMAGEN>: información de las capas que componen una imagen.docker exec <CONTENEDOR> <COMANDO>: ejecuta un proceso nuevo en un contenedor en marcha.
Listado de ficheros:
/var/run/docker.sock: named pipe que utilizan cliente y servidor de Docker para comunicarse.Dockerfile: instrucciones para la creación de imágenes.
Dockerfile:
FROM <IMAGEN>: indica la imagen base.ENV <variable>=<valor>: define variables de entorno del contenedor.WORKDIR <DIRECTORIO>: se sitúa enDIRECTORIOen el contenedor (como hacercd DIRECTORIO)COPY <ORIGEN_LOCAL> <DESTINO_CONTENEDOR>: copia ficheros de un directorio local a un directorio del contenedor.ADD <ORIGEN> <DESTINO_CONTENEDOR>: igual queCOPY, pero admite como origen una URL o fichero comprimido.RUN <COMANDO>: comandos a ejecutar en el contenedor (durante la fase de construcción de la imagen).CMD <COMANDO>: comando a ejecutar al iniciar el contenedor.CMD [<COMANDO1>, <COMANDO2>]: ejecuta en forma exec (COMANDO1 COMANDO2)CMD <COMANDO1> <COMANDO2>: ejecuta en forma shell (/bin/sh -c 'COMANDO1 COMANDO2')
ENTRYPOINT <COMANDO>:
