Skip to main content

Crear imágenes de Docker en Kubernetes

Escrito por
Headshot of Vitalis Ogbonna

Vitalis Ogbonna

feature docker k8s code

3 de mayo de 2022

0 minutos de lectura

Cada vez más ingenieros alojan plataformas de CI/CD en Kubernetes. Este enfoque ahorra tiempo gracias a la automatización, garantiza implementaciones consistentes y facilita la supervisión y el manejo de microservicios. Sin embargo, crear imágenes de contenedores en clústeres de Kubernetes implica algunos desafíos técnicos que requieren soluciones alternativas.

En este artículo, exploraremos algunas formas de crear imágenes de Docker en un clúster de Kubernetes para procesos de CI/CD. También hablaremos sobre las ventajas y desventajas de estos métodos.

Herramientas para crear imágenes de Docker en Kubernetes

Si alguna vez creaste una imagen de contenedor, probablemente ejecutaste un comando como docker build. Luego, cuando llegó el momento de automatizar ese proceso, quizá configuraste tus herramientas de CI/CD para que también usaran docker build. Esto funciona con servidores de CI sencillos, pero quizá más adelante quieras implementar una plataforma de CI basada en Kubernetes.

El desafío es que el daemon de Docker no está disponible libremente desde el clúster de Kubernetes. Por eso, debemos usar alternativas y asegurarnos de no poner en riesgo la integridad de nuestra aplicación ni la infraestructura.

Hay varias herramientas para hacerlo:

  • Buildah se especializa en crear imágenes de la Open Container Initiative (OCI). Sus comandos replican todos los comandos de un Dockerfile. Permite crear imágenes con o sin Dockerfiles, sin necesidad de privilegios de root.

  • img es una herramienta independiente para crear imágenes de contenedores compatibles con Dockerfile y OCI, sin daemon ni privilegios. Usa la caché de manera eficiente y puede ejecutar varias etapas de compilación al mismo tiempo, ya que utiliza internamente el solucionador DAG de BuildKit para crear imágenes.

  • kaniko crea imágenes de contenedores a partir de un Dockerfile, dentro de un contenedor o clúster de Kubernetes. kaniko no depende de un daemon de Docker y ejecuta cada comando del Dockerfile completamente en el espacio de usuario.

  • Docker in Docker es una receta para ejecutar Docker dentro de Docker. Crea contenedores de Docker en clústeres de Kubernetes al montar el archivo /var/run/docker.sock como volumen en un contenedor de Docker.

  • Sysbox Enterprise Edition (Sysbox-EE), de Nestybox, permite que los contenedores sin privilegios de root ejecuten cargas de trabajo como Docker, systemd y Kubernetes como si fueran máquinas virtuales.

  • BuildKit CLI crea imágenes OCI y Docker de una o varias arquitecturas en clústeres de Kubernetes. Reemplaza el comando docker build por kubectl build para crear imágenes en clústeres de Kubernetes.

  • Jib para contenedores Java crea imágenes de contenedores sin usar un Dockerfile ni requerir una instalación de Docker. Hay plugins de Jib para Maven y Gradle. Jib también está disponible como biblioteca de Java.

  • KO es una herramienta rápida y sencilla para crear imágenes de contenedores para aplicaciones de Go. Crea imágenes básicamente ejecutando go build en tu máquina local, por lo que no requiere instalar Docker.

Veamos dos métodos populares para crear imágenes de Docker en un clúster de Kubernetes: Docker in Docker y kaniko.

Docker in Docker

El método Docker in Docker (DIND) se usa comúnmente en pipelines de CI/CD, donde las imágenes se crean y se suben después de una compilación de código exitosa. También se usa para integrar Jenkins en pipelines de implementación, por ejemplo, durante pruebas en entornos de sandbox.

El enfoque DIND puede parecer práctico y sencillo. Sin embargo, el ex empleado de Docker y colaborador de DIND Jérôme Petazzoni sostiene que Docker creó este enfoque para acelerar los procesos internos, y alude a problemas de seguridad como motivo para no usarlo en entornos de producción.

Originalmente, Docker creó los contenedores para que se ejecutaran en modo privilegiado con el enfoque DIND. El daemon de Docker se ejecuta como root, por lo que el contenedor también se ejecuta como root en el host. Cualquiera que acceda al socket de Docker tiene acceso root, lo que le permite ejecutar cualquier software, crear usuarios nuevos y acceder a todo lo conectado al contenedor. Esto hace que los contenedores sean vulnerables a ataques que podrían propagarse por toda la arquitectura.

Además, como Kubernetes eliminó oficialmente la compatibilidad con Dockershim, es probable que montar docker.sock en el host deje de funcionar en el futuro, a menos que agreguemos Docker a todos los nodos de Kubernetes. AWS ofrece una herramienta útil para detectar el uso del socket de Docker en clústeres.

El método DIND también presenta problemas de compatibilidad con los controladores de almacenamiento. Además, administrar las cachés de imágenes puede ser complicado porque tenemos que descargar las imágenes de Docker cada vez que iniciamos una compilación.

Una forma de resolver estos problemas es usar herramientas que no requieran un entorno de ejecución de contenedores para crear imágenes. Una de ellas es kaniko, la solución de código abierto de Google para crear imágenes de Docker en un clúster de Kubernetes.

kaniko

kaniko crea imágenes de contenedores a partir de un Dockerfile, dentro de un contenedor o clúster de Kubernetes. No depende de un daemon de Docker y ejecuta cada comando del Dockerfile completamente en el espacio de usuario. Esto te permite crear imágenes de contenedores en entornos donde no es fácil ni seguro ejecutar un daemon de Docker, como los clústeres de Kubernetes estándar.

Usaremos herramientas gratuitas y de acceso público para mostrar el flujo de trabajo de kaniko. Para seguir este tutorial, necesitarás:

  • Docker Desktop instalado en tu PC con Kubernetes habilitado

  • Una cuenta válida de Docker Hub para que el pod de kaniko se autentique y suba la imagen de Docker

  • Una cuenta de GitHub para que kaniko acceda al Dockerfile

Usaremos este proyecto de ejemplo en GitHub para mostrar cómo funciona kaniko. Clónalo con git clone https://github.com/agavitalis/kaniko-kubernetes.git para seguir los pasos.

Este proyecto de ejemplo tiene dos archivos y un archivo README.md:

#sample project directory

kaniko-build-demo

  • dockerfile

  • pod.yml

  • README.md

dockerfile contiene este código para los comandos de creación de imágenes:

FROM ubuntu
ENTRYPOINT ["/bin/bash", "-c", "echo Hello to Kaniko from Kubernetes"]

pod.yml contains this code for the kaniko configurations:

apiVersion: v1
kind: Pod
metadata:
  name: kaniko-demo
spec:
  containers:
  - name: kaniko-demo
    image: gcr.io/kaniko-project/executor:latest
    args: ["--context=git://github.com/agavitalis/kaniko-kubernetes.git",
            "--destination=agavitalis/kaniko-build-demo:1.0.0",
            "--dockerfile=dockerfile"]
    volumeMounts:
      - name: kaniko-secret
        mountPath: /kaniko/.docker
  restartPolicy: Never
  volumes:
    - name: kaniko-secret
      secret:
        secretName: reg-credentials
        items:
          - key: .dockerconfigjson
            path: config.json

En el código de configuración de kaniko, el ejecutor de imágenes de kaniko usa la versión más reciente. También especificamos la ubicación de nuestro Dockerfile y el repositorio de imágenes, así como el nombre de las credenciales del registro de imágenes en Kubernetes.

Cómo funciona kaniko

kaniko funciona de una manera bastante sencilla. La imagen del ejecutor de kaniko gcr.io/kaniko-project/executor:latest ejecuta los comandos del Dockerfile para crear imágenes. Lee el Dockerfile especificado, descarga la imagen base definida en el comando FROM (en este caso, ubuntu) en el sistema de archivos del contenedor definido y luego sube las imágenes a un registro.

Después de descargar la imagen base indicada en la instrucción FROM, kaniko ejecuta por separado cada comando del Dockerfile y toma una instantánea del espacio de usuario después de ejecutar cada uno. Luego, agrega la capa de la instantánea a la capa base en cada ejecución.

Configuramos estos parámetros en el archivo pod.yml:

  • context: ubicación del Dockerfile. En este caso, el Dockerfile está en el directorio raíz del repositorio. Usa las variables GIT_USERNAME y GIT_PASSWORD (token de API) para autenticarte en repositorios privados de Git.

  • destination: Reemplaza <dockerhub-username> por tu nombre de usuario para que kaniko suba la imagen al registro de Docker Hub.

  • docker-file: ruta al Dockerfile relativa al contexto.

Ahora que entendemos cómo funciona kaniko, creemos un Secret de Kubernetes. Luego lo usaremos para crear e implementar una imagen.

Crear un Secret de Kubernetes para Docker Hub

Debemos crear un Secret de Kubernetes para que kaniko pueda acceder a Docker Hub. Para hacerlo, necesitamos la siguiente información:

  • docker-server: servidor del registro de Docker donde se alojarán tus imágenes. Si usas Docker Hub, este valor debe ser https://index.docker.io/v1/.

  • docker-username: nombre de usuario de tu registro de Docker.

  • docker-password: contraseña de tu registro de Docker.

  • docker-email: correo electrónico configurado en tu registro de Docker.

Ejecuta los siguientes comandos y reemplaza cada variable según corresponda:

#bash
$ kubectl create secret docker-registry reg-credentials
--docker-server=<docker-server> --docker-username=<username> --docker-password=<password> --docker-email=<email>

El comando anterior monta este Secret en el pod de kaniko para facilitar la autenticación al subir la imagen creada a un registro de Docker. Deberías recibir un mensaje de confirmación como este:

Terminal que muestra un comando kubectl para crear un secreto de registro de Docker llamado reg-credentials, con los valores de las credenciales ocultos.

Implementar el pod de kaniko para crear una imagen de Docker

Ahora, iniciemos la compilación creando el pod en nuestro clúster de Kubernetes. Implementa el pod con el comando:

#bash
$ kubectl apply -f pod.yaml
Salida de la terminal que muestra el comando "kubectl apply -f pod.yaml" y la confirmación de que se creó pod/kaniko-demo

Esto inicia el proceso de creación de la imagen y luego la sube al registro de Docker especificado.

Puedes listar los pods disponibles en tu clúster de Kubernetes con el comando:

#bash
$ kubectl get pod
Terminal que muestra el comando kubectl get pod y un pod kaniko-demo con 0/1 listos, estado Completed y cero reinicios.

Esto muestra los pods disponibles, su estado y su antigüedad. Ten en cuenta que podrías recibir un error si kaniko usa credenciales incorrectas o intenta subir la imagen al repositorio equivocado.

Si quieres, usa el comando kubectl delete pod <pod-name> para eliminar los pods existentes.

Para obtener información detallada sobre el pod que acabas de implementar, usa el comando:

#bash
$ kubectl describe pod
Terminal que muestra comandos de kubectl para aplicar un manifiesto de pod y describir el pod kaniko-demo completado.

También puedes consultar el registro de compilación con el comando:

#bash
$ kubectl logs kaniko-demo -f
Terminal que muestra los registros de kubectl de un pod kaniko-demo completado, incluidos los resultados de la creación de una imagen de Docker y su envío a Docker Hub.

Consulta la hoja de referencia de kubectl para conocer otros comandos que puedes usar para explorar y solucionar problemas, y obtener más información sobre tu clúster.

Después, ve a Docker Hub para confirmar que todo haya funcionado y que hayas implementado correctamente tus imágenes en Docker.

Página del repositorio agavitalis/kaniko-demo en Docker Hub que muestra la configuración del repositorio, el comando Docker push, las etiquetas y los análisis, y las compilaciones automatizadas

¡Creamos e implementamos correctamente nuestra imagen de Docker desde un clúster de Kubernetes con kaniko!

Snyk para la seguridad de contenedores

kaniko ofrece una forma segura de crear imágenes de Docker en clústeres de Kubernetes. Obtiene el Dockerfile del contexto de compilación definido, crea la imagen y sube el resultado a un registro de imágenes. Su potente sistema de caché permite crear imágenes más rápido.

Aunque no uses un método inseguro para crear tus imágenes de Docker en Kubernetes, podrías seguir expuesto a vulnerabilidades de seguridad de Kubernetes. Snyk Container ofrece una solución confiable de seguridad de contenedores para detectar y corregir vulnerabilidades en aplicaciones nativas de la nube. Snyk se integra sin problemas con Docker, GitHub, Kubernetes, Jenkins y otras herramientas para proteger tu aplicación y tu infraestructura.

Seguridad de contenedores centrada en los desarrolladores

Snyk encuentra y corrige automáticamente vulnerabilidades en imágenes de contenedores y cargas de trabajo de Kubernetes.

Leer más

feature insights context
Blog

Los ataques autónomos ya están aquí. La defensa debe estar a su altura.

Los atacantes autónomos están reduciendo el tiempo disponible para defenderse. Descubre cómo el descubrimiento, la corrección, la validación y la prevención continuos pueden ayudar a los equipos de seguridad a seguirles el ritmo.

Blog

Evo ADS Govern Agent Behavior ya está disponible: controla el uso de MCP

Evo ADS Govern Agent Behavior ya está disponible, comenzando con MCP Governance. Descubre, aprueba, monitorea, registra y bloquea el uso de servidores MCP en los principales agentes de programación con IA.

illustration hero ai
Blog

¿Qué es Agentic AppSec?

Descubre cómo Agentic AppSec usa agentes de IA con contexto, límites definidos y verificación independiente para ejecutar el ciclo de seguridad de aplicaciones.