Seguridad en Contenedores : Docker 101 Fundamentos
En el objetivo de esta serie de articulos relacionados a contenedores es abordar de manera general la tecnologia con el objetivo de profundizar desde el punto de vista de ciberseguridad.
No encontraras definiciones formales, todo esto esta escrito bajo mis propias palabras.
Que es Docker?
Docker es una tecnología que permite la ejecución de código de una manera estandarizada a través del uso de contenedores.
¿Cómo funciona Docker?
La tecnología de Docker utiliza el kernel de Linux y sus características para dividir los procesos y servicios, con el objetivo de ejecutarlos de manera aislada e independiente.
Docker funciona bajo un modelo de imágenes; esto permite desplegar, compartir y utilizar los servicios sin pensar en la dependencia de bibliotecas o versiones específicas de tecnología como bases de datos, frameworks frontend o backend.
¿Cuál es la diferencia entre Imágenes y Contenedores de Dockers?
La imagen de Docker contiene los recursos necesarios para la ejecución de un servicio o aplicación, por ejemplo la versión del intérprete que se debe utilizar para ejecutar una aplicación desarrollada en Python, los archivos necesarios del proyecto, los puertos que serán utilizados.
# Usa la imagen base oficial de Python
FROM python:3.9
# Establece el directorio de trabajo en /mi_app
WORKDIR /mi_app
# Copia el archivo de requisitos al directorio de trabajo
COPY requirements.txt .
# Instala las dependencias de Python
RUN pip install -r requirements.txt
# Copia el resto de los archivos de la aplicación al directorio de trabajo
COPY . .
# Expone el puerto 5000 en el contenedor
EXPOSE 5000
# Define la variable de entorno para la base de datos de MongoDB
ENV MONGO_URI mongodb://mongo_db_host:27017/mi_base_de_datos
# Ejecuta la aplicación cuando se inicie el contenedor
CMD ["python", "app.py"]
Con toda la información necesaria, se procede a la construcción de la imagen :
docker build -t mi_app .
Si la imagen fue creada de manera correcta, esta podrá ser ejecutada en un contenedor.
docker run -d -p 5000:5000 --name mi_contenedor mi_app
Instalación
A continuación se detalla el paso a paso la instalación y ejecución de docker
Añadimos el repositorio al sistema operativo para la instalar docker.
Se instala docker-ce(Community Edition) docker-ce-cli(Command Line) y containerd.io (servicio para la ejecución de contenedores)
Para conocer la versión de docker instalada se debe ejecutar :
Para ejecutar docker sin necesidad de usar sudo, se puede agregar el usuario actual al grupo “docker”
sudo usermod -a -G docker ubuntu
El componente encargado de administrar como se almacena y gestiona la información de las capas de imagenes y volumenes de datos dentro los contenedores es “Storage driver”, por defecto y en relación al sistema operativo se utiliza overlay2
Para ver cual es el usado, puedes ejecutar docker info.
Si quisieramos cambiar el driver por defecto deberiamos crear/modificar el archivo /etc/docker/daemon.json
Se debe reiniciar el servicio de docker para que los cambios sean aplicados de manera correcta.
Ejecutar un contenedor
Ahora vamos a entrar a “groso modo” sobre la gestión de contenedores.
Para ejecutar un contenedor en particular es necesario utilizar el parametro run, la imagen y el tag nginx[imagen]:(1.15.11)[TAG]
En este caso ejecutamos un contenedor con la imagen de busybox y ejecutamos un comando dentro del contenedor.
Ahora si quisieramos ejecutar en segundo plano solo se debe agregar el argumento -d
Para ver los contenedores que se estan ejecutando en el sistema podemos utilzar ps
Cuando hablamos de la gestion de contenedores es necesario dar un orden, establecer nombres con base en nomeclaturas, publicar los puertos que seran utilizado para el servicio, la opcion de reinicio y algunas otras opciones como la memoria.
iaraoz@linux:$ docker run -d --name nginx --restart unless-stopped -p 8080:80 --memory 500M --memory-reservation 256M nginx
docker run
: Es el comando principal de Docker utilizado para crear y ejecutar contenedores.-d
: Esta opción indica a Docker que se ejecute el contenedor en segundo plano, es decir, en modo "detached".--name nginx
: Aquí se establece el nombre del contenedor como "nginx". Esto asigna un nombre específico al contenedor en lugar de que Docker le asigne uno automáticamente.--restart unless-stopped
: Esta opción indica a Docker que el contenedor se reinicie automáticamente a menos que se detenga explícitamente por el usuario. Esto significa que si el contenedor se detiene por algún motivo, Docker intentará reiniciarlo automáticamente a menos que se detenga manualmente con el comandodocker stop
.-p 8080:80
: Esta opción mapea el puerto 8080 del host al puerto 80 dentro del contenedor. Esto permite acceder al servidor web Nginx que se ejecuta dentro del contenedor a través del puerto 8080 del host.--memory 500M
: Aquí se establece el límite máximo de memoria RAM que puede utilizar el contenedor en 500 megabytes.--memory-reservation 256M
: Esto establece una reserva de memoria mínima de 256 megabytes para el contenedor. Esto garantiza que el contenedor siempre tenga al menos esta cantidad de memoria disponible.nginx
: Este es el nombre de la imagen de Docker que se utilizará para crear el contenedor. En este caso, se está utilizando la imagen de Nginx, un servidor web.
Sobre--restart [opciones]
existen las siguientes opciones:
no
: Esta política indica que Docker no debe intentar reiniciar automáticamente el contenedor si se detiene por algún motivo. Es decir, el contenedor no se reiniciará automáticamente bajo ninguna circunstancia.always
: Esta política indica que Docker debe intentar reiniciar el contenedor siempre que se detenga, independientemente de la causa de la detención. Docker intentará reiniciar el contenedor automáticamente tantas veces como sea necesario.on-failure
: Esta política indica que Docker debe intentar reiniciar el contenedor solo si se detiene debido a un error (específicamente, un código de salida diferente de cero). Si el contenedor se detiene por cualquier otra razón, como una detención manual o un fallo del sistema, Docker no intentará reiniciar automáticamente el contenedor.
Despues de ejecutar el comando completo, podemos ver el contenedor ejecutandose con las configuraciones previamente establecidas.
Para ver todos los contenedores (en ejecucion y no ejecutados), se debe agregar el parametro -a
En el caso de querer eliminar un contenedor
$ docker container rm nginx
Desde el punto de vista de seguridad el tener los logs del servicio y de los contenedores, nos permite ganar visibilidad sobre los contenedores y detectar actores de amenazas y actividades sospechosas.
Para saber cual tenemos actualmente podemos ejecutar el comando docker info y fitlrar por Logging.
docker run --log-driver syslog nginx
docker run
: Es el comando principal de Docker utilizado para crear y ejecutar contenedores.--log-driver syslog
: Esta opción indica a Docker que utilice el controlador de registro syslog para manejar los registros generados por el contenedor. El syslog es un protocolo estándar para el envío de registros del sistema a un servidor de registro centralizado, que puede ser útil para la gestión centralizada de registros en entornos de producción.nginx
: Este es el nombre de la imagen de Docker que se utilizará para crear el contenedor. En este caso, se está utilizando la imagen de Nginx, un servidor web.
Hasta aquí llegamos, nos vemos en el siguiente articulo.