Docker para ciberseguridad – Parte 1: Instalación e imágenes

por Alberto Jódar
0 comentario 14 minutos lectura

Posiblemente como analistas de seguridad os haya tocado trabajar con Docker. Y si no, os va a tocar. Así que en esta serie de entradas vamos a repasar esta tecnología, yendo desde lo más básico hasta usos más avanzados que podemos hacer como analistas de ciberseguridad.

Para situarnos debemos saber que Docker es una plataforma de código abierto que nos permite ejecutar aplicaciones dentro de contenedores. Un contenedor podemos decir que es un entorno aislado que permite ejecutar la aplicación sin que esta tenga ningún acceso al sistema operativo original donde se está ejecutando Docker. Es como cuando virtualizamos sistemas operativos con VirtualBox, pero para virtualizar aplicaciones.

A container is an isolated environment for your code. This means that a container has no knowledge of your operating system, or your files

Docker nos va a proveer todas las funciones necesarias para gestionar estos contendores, lanzarlos, definir que hay dentro del contenedor, qué aspectos del contenedor deben perdurar entre ejecuciones, conexiones de red entre contenedores…

Instalación

Para este ejemplo, yo voy a usar un sistema operativo Ubuntu. Pero los contenedores están pensados para ser portables, luego Docker se puede instalar prácticamente en cualquier sitio. Y vamos a instalar la Docker Community Edition, que es la versión gratuita y de código abierto.

Abrimos la terminal y ejecutamos los siguientes pasos.

# Actualizamos los paquetes del sistema
$> sudo apt update

# Instalamos paquetes para que apt pueda funcionar sobre HTTPS
$> sudo apt-get install apt-transport-https ca-certificates curl software-properties-common

# Añadimos la clave GPG del repositorio de Docker
$> curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

# Añadimos el repositorio de Docker
$> sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

# Actualizamos de nuevo los paquetes del sistema
$> sudo apt update

# Instalamos Docker CE
$> sudo apt-get install docker-ce

# Probamos que la instalación es correcta ejecutando el contenedor de prueba "hello-world"
$> sudo docker run hello-world

# Añadimos el usuario actual al grupo de docker para no tener que ejecutar docker con sudo
$> sudo usermod -aG docker $USER

# (OPCIONAL) Si queremos que Docker se ejecute al inicio del sistema
$> sudo systemctl enable docker

Imágenes y DockerHub

Ya hemos visto que Docker gestiona contenedores, que son entornos aislados para la ejecución de una aplicación. Pues una imagen es la plantilla para generar ese contenedor. Una imagen contiene todo lo necesario para ejecutar una aplicación. Esto incluye el código, las bibliotecas, las dependencias, las herramientas y los archivos de configuración.

Estas imágenes se suelen guardar en repositorios de imágenes. El repositorio oficial de imágenes de Docker es DockerHub. Pero también es frecuente encontrar repositorios públicos o privados en sistemas como Amazon ECR o Google Container Registry.

Vamos a usar de ejemplo la aplicación Apache, uno de los servidores web más conocidos y usados. Si buscamos el nombre de la aplicación en el DockerHub vemos que nos aparece como el nombre del servicio, «httpd».

Accedemos y ya vemos que nos indica como hacernos con esta imagen para nuestro Docker, Además hay una sección de etiquetas. Aunque lo veremos a continuación, estas nos van a servir para traernos versiones específicas de la imagen. En este caso ya podemos intuir que las etiquetas hacen referencia a diferentes versiones de Apache.

En las siguientes secciones vamos a ver qué podemos hacer con esta imagen.

docker pull: Descargar una imagen

El comando «docker pull» nos permite descargar imágenes del DockerHub. En este podemos indicar la versión (etiqueta) que queramos. Si no indicamos qué etiqueta descargar, se va a descargar la más reciente, que está siempre representada por la etiqueta «latest«.

# Descargamos la imagen de Apache con la última versión, “latest”
$> docker pull httpd

# Descargamos la imagen de Apache con la etiqueta 
$> docker pull httpd:2.4.59

# Descargamos la imagen con TODAS las etiquetas de Apache con la etiqueta 
$> docker pull -a httpd

docker history: Capas de una imagen

Una imagen está formada por una serie de capas. Estas capas definen cómo se conforma el entorno de la aplicación. Y lo más importante, son capas de solo lectura. Para ver las capas que conforman una imagen tenemos el comando “docker history”.

# Vemos las capas de la imagen httpd
$> docker history httpd

# Si queremos ver la salida completa, no truncada
$> docker history httpd –no-trunc

Lo que vemos como salida a este comando son efectivamente todas las capas que conforman esta imagen. No vamos a entrar en detalle ahora mismo. Solo tenéis que saber que las capas que definen una imagen se definen en un fichero denominado Dockerfile y que veremos en detalle en entradas de esta serie.

docker image: Gestión de imágenes

Ya tenemos una imagen en nuestro Docker. El comando para gestionarlas es «docker image«. Os muestro a través de la terminal las opciones que más vais a tener que usar:

# Listar todas las imagenes que tenemos en nuestro Docker 
$> docker image ls

# Borrar una imagen 
$> docker image rm httpd:2.4.59

# Ver todos los detalles de una imagen
$> docker image inspect httpd

Antes vimos que con «docker history» podíamos ver todas las capas que conforman la imagen. Con «docker image inspect» vamos a ver los metadatos de la misma. Fecha, autor, puertos que expone, volúmenes…

docker image prune: image dangling

Es importante entender qué es lo que se conoce como image dangling. Aunque es un proceso que vamos a ver más en la gestión de imágenes que construyamos nosotros mismos, se puede dar también con las imágenes que traemos del DockerHub. Imaginemos que tenemos una imagen llamada «dfirpills» con la etiqueta «latest», ya que nos hemos traído la última versión de la misma.

¿Qué ocurre si ahora hay una nueva versión latest? Pues que tendremos una nueva imagen «latest», y que la antigua se quedará huérfana, sin etiqueta. Esto es lo que se conoce como «image dangling«.

Podemos ver el listado de imágenes dangling con:

# Lista imágenes dangling
$> docker images -f "dangling=true"

Hay una forma sencilla que nos permite eliminar todas las imágenes dangling en un solo comando:

# Elimina todas las imagenes dangling
$> docker image prune 

# Igual, pero para que no pida confirmación
$> docker image prune -f

# O sumando lo que ya hemos visto, podemos pasar el listado de imagenes dangling al comando docker image rmi
$> docker images -f dangling=true -q | xargs docker rmi

Pero «docker image prune» no solo sirve para eliminar el image dangling. Nos va a servir también para eliminar las imágenes en base a unos filtros. O en el caso más drástico, para eliminar todas las imágenes.

# Eliminar todas las imagenes creadas hace mas de 24h
$> docker image prune -a --filter "until=24h"

# Eliminar todas las imagenes
$> docker image prune -a

Podéis ver todas las opciones para los filtros en la documentación oficial .

docker run: Ejecución de contenedores a partir de imágenes

¡Al meollo! Queremos las imágenes para levantar contenedores que nos permitan disponer de las aplicaciones. En este caso de un servidor web Apache. El comando para levantar contenedores a partir de la imagen es «docker run».

# Ejecutamos un contendor en base a lo definido en la imagen httpd
$> docker run httpd

Esto se ejecuta, levanta un contenedor con un Apache dentro y termina. Y me diréis, ¿dónde está la gracia? Pues la gracia está en que debemos indicar algunas opciones para que este contenedor se comporte como nosotros queremos.

En la página de DockerHub de httpd ya nos indica como debemos de ejecutarlo «sin Dockerfile». La opción con Dockerfile la veremos en las próximas entradas.

Vemos las opciones:

-d = "detached" se ejecuta el contenedor, pero libera la linea de comandos para que podamos seguir usándola

-it = interactivo + tty. Abre la entrada estandar y asigna una terminal tty por si queremos abrir una consola 

--name = proporciona un nombre al contenedor

-p 8080:80 = mapea el puerto 8080 de la máquina contra el puerto 80 del contenedor  

-v "$PWD":/usr/local/apache2/htdocs/ = monta el directorio actual donde se esta ejecutando el contenedor "$PWD" en la capreta htdocs dentro del contenedor 

$> docker run -dit --name my-apache-app -p 8080:80 -v "$PWD":/usr/local/apache2/htdocs/ httpd

# Aunque ampliaremos detalle de contenedores en otra sección, podemos ver contenedores en ejecución con
$> docker ps

Ejecutamos:

Si vamos al navegador de nuestra máquina y accedemos a «localhost:8080» vemos:

Esto es el contenido del directorio donde estamos a la hora de ejecutar el contenedor, que es lo que hemos indicado con la opción -v, copiando el directorio actual a la ruta donde Apache expone sus recursos.

docker –help

Por último, deberíais de usar «docker help». Sirve para cualquier comando de Docker y os muestra la ayuda para ese comando.

# Ayuda general de docker
$> docker --help

# Ayuda de la gestión de imagenes con docker image
$> docker image --help

# Ayuda de la opcion prune dentro de docker image 
$> docker image prune --help

Conclusiones

Ya sabemos qué es Docker. Que se basa en la ejecución de contenedores que contienen aplicaciones y que se ejecutan con todo lo que necesita de forma aislada a la máquina. Y que estos contenedores y sus dependencias se definen en imágenes.

Nos vemos en el siguiente.

Artículos relacionados

Deja un comentario

* Al utilizar este formulario usted acepta el almacenamiento y tratamiento de sus datos por parte de este sitio web.

Este sitio web utiliza cookies para mejorar su experiencia Aceptar Leer más