¿Por qué estás aquí?
Quieres saber la respuesta real a dos preguntas sobre la seguridad de Docker:
¿Es seguro Docker para su uso en producción?
Síy no. Docker utiliza un modelo de seguridad que se basa en espacios de nombres y aislamiento de recursos, por lo que los procesos dentro de más seguro de ataques específicos que la ejecución de sus aplicaciones directamente desde una nube VM o sistema de metal desnudo.A pesar de esa capa, todavía hay un montón de maneras para que los atacantes accedan a su contenedor, lo que les permite leer información confidencial, ejecutar ataques de denegación de servicio (DoS), o incluso obtener acceso root al sistema host.
¿Cómo puedo mejorar mi seguridad en Docker (de una forma no terriblemente dolorosa)?
Teguiaremos a través de las vulnerabilidades más comunes y graves de Docker, saltándonos las recomendaciones básicas que encontrarás por todo Google, como usar imágenes oficiales y mantener tu host actualizado.En su lugar, te llevaremos directamente a nuevas opciones de Docker y líneas de Dockerfile que harán que tu nuevo despliegue de contenedores Docker por defecto sea mucho más seguro que nunca.

La lista de comprobación de seguridad Docker no BS
Hacer que los sistemas de archivos dentro del contenedor sean de sólo lectura
¿Qué ganas?
Evita que un atacante edite el entorno de ejecución de su contenedor Docker, lo que podría permitirle recopilar información útil sobre su infraestructura, recopilar datos de usuarios o realizar directamente un ataque DOS o ransomware.
¿Cómo se fija?
Tiene dos opciones, en tiempo de ejecución o dentro de la configuración de Docker Compose.
En tiempo de ejecución: docker run --read-only tu-app:v1.0.1
En su archivo Docker Compose:
servicios:
webapp:
image: your-app:v1.0.1read_only: true
...
Escalada de privilegios de bloqueo
¿Qué ganas?
Evita que tu contenedor Docker -o un atacante que esté jugando dentro de dicho contenedor- habilite nuevos privilegios, incluso de nivel raíz, con setuid o setgid. Con un acceso más permisivo a tu contenedor, un atacante podría acceder a credenciales en forma de contraseñas o claves de partes conectadas de tu despliegue, como una base de datos.
¿Cómo se fija?
Una vez más, en tiempo de ejecución o dentro de la configuración de Docker Compose.
En tiempo de ejecución: docker run --security-opt=no-new-privileges tu-app:v1.0.1
En su archivo Docker Compose:
servicios:
webapp:
image: your-app:v1.0.1
security_opt:
- no-new-privileges:true
...
Aísle sus redes de contenedor a contenedor
¿Qué ganas?
Por defecto, Docker permite que todos los contenedores se comuniquen a través de la red docker0, lo que podría permitir a un atacante moverse lateralmente de un contenedor comprometido a otro. Si tienes servicios discretos A
y B
en contenedores Y
y Z
y no necesitan comunicarse directamente, aislar sus redes proporciona la misma experiencia al usuario final al tiempo que evita el movimiento lateral para mejorar la seguridad de Docker.
¿Cómo se fija?
Puedes especificar redes Docker en tiempo de ejecución o dentro de tu configuración Docker Compose. Sin embargo, primero debe crear la red:
docker network create tu-red-aislada
En tiempo de ejecución, añada el --opción de red
n: docker run --network tu-red-aislada tu-app:v1.0.1
O la opción equivalente en su archivo Docker Compose:
servicios:
webapp:
image: your-app:v1.0.1
networks:
- tu-red-aislada
...
Establecer un usuario no root adecuado
¿Qué ganas?
El usuario por defecto dentro de un contenedor es raíz
con un uid de 0
. Al especificar un usuario distinto, evitas que un atacante escale sus privilegios a otro usuario que pueda realizar acciones sin restricciones, como root, lo que anularía cualquier otra medida de seguridad de Docker que te hayas esforzado en implementar.
¿Cómo se fija?
Crea tu usuario durante el proceso de compilación o en tiempo de ejecución. En tiempo de ejecución, puede crear el usuario por primera vez o anular la opción USUARIO
que ya configuraste al construir.
Durante el proceso de compilación, en su Dockerfile
:
...
RUN groupadd -r tu-usuario
RUN useradd -r -g tu-usuario tu-usuario
USUARIO myuser
...
En tiempo de ejecución: docker run -u tu-usuario tu-app:v1.0.1
Reducir las capacidades del núcleo Linux
¿Qué ganas?
Por defecto, los contenedores Docker pueden utilizar un conjunto restringido de capacidades del kernel de Linux. Podrías pensar que la gente de Docker creó ese conjunto restringido para ser completamente seguros, pero muchas capacidades existen por compatibilidad y simplicidad. Por ejemplo, los contenedores predeterminados pueden cambiar arbitrariamente la propiedad de los archivos, cambiar su directorio raíz, manipular los UID de los procesos y leer sockets. Al eliminar algunas o todas estas capacidades, se minimiza el número de vectores de ataque.
¿Cómo se fija?
Puedes eliminar capacidades y establecer otras nuevas en tiempo de ejecución. Por ejemplo, puedes eliminar todas las capacidades del kernel y permitir a tu contenedor sólo la capacidad de cambiar la propiedad de los archivos existentes.
docker run --cap-drop ALL --cap-add CHOWN tu-app:v1.0.1
O para Docker Compose:
servicios:
webapp:
image: your-app:v1.0.1
cap_drop:
- ALL
cap_add:
- CHOWN
...
Evitar las bombas de tenedor
¿Qué ganas?
Las bombas de bifurcación son un tipo de ataque DoS que replica infinitamente un proceso existente. En primer lugar, reducen el rendimiento y restringen los recursos, lo que inevitablemente aumenta los costes y, en última instancia, puede colapsar tus contenedores o el sistema anfitrión. Una vez que una bomba de bifurcación se ha iniciado, no hay otra forma de detenerla que reiniciando el contenedor o el host.
¿Cómo se fija?
En tiempo de ejecución, puedes limitar el número de procesos (PIDs) que tu contenedor puede crear.
docker run --pids-limit 99 tu-app:v1.0.1
O con Docker Compose:
servicios:
webapp:
image: tu-app:v1.0.1
deploy
límites:
pids: 99
Mejore la seguridad de Docker supervisando sus dependencias de código abierto
¿Qué ganas?
Es probable que las aplicaciones que ha puesto en contenedores para su despliegue con Docker tengan un amplio árbol de dependencias.
¿Cómo se fija?
La forma más "no BS" es con el escaneo de dependencias de código abierto de Aikido. Nuestra monitorización continua escanea proyectos escritos en más de una docena de lenguajes basándose en la presencia de archivos de bloqueo dentro de su aplicación y ofrece una visión general instantánea de vulnerabilidades y malware. Con el triaje automático que filtra los falsos positivos, Aikido le da consejos de remediación con los que puede empezar a trabajar de inmediato... no sólo después de leer una docena de otros documentos de referencia y temas de GitHub.
En Aikido, nos encantan los proyectos de código abierto establecidos como Trivy, Syft y Grype. También sabemos por experiencia que utilizarlos de forma aislada no es una experiencia particularmente buena para los desarrolladores. Bajo el capó, Aikido mejora estos proyectos con reglas personalizadas para cerrar las brechas y revelar los fallos de seguridad que no sería capaz de encontrar de otra manera. A diferencia de encadenar varias herramientas de código abierto, Aikido te libera de tener que construir un script de escaneo o crear un trabajo personalizado en tu CI/CD.

Utilice sólo imágenes de confianza para la seguridad de Docker
¿Qué ganas?
Docker Content Trust (DCT) es un sistema para firmar y validar el contenido y la integridad de las imágenes oficiales que se extraen de registros de Docker como Docker Hub. Si solo extrae imágenes firmadas por el autor, tendrá más garantías de que no han sido manipuladas para crear vulnerabilidades en su despliegue.
¿Cómo se fija?
La forma más sencilla es establecer la variable de entorno en su shell, lo que impide que usted o cualquier otra persona trabaje con imágenes no fiables.
exportDOCKER_CONTENT_TRUST=1
docker run ...
O bien, puede establecer la variable de entorno cada vez que ejecute Docker:
DOCKER_CONTENT_TRUST=1 docker run ...
Actualizar los tiempos de ejecución al final de su vida útil (EOL)
¿Qué ganas?
Una recomendación común para la seguridad de los contenedores Docker es fijar imágenes y dependencias a una versión específica en lugar de última
. En teoría, eso evita que utilices sin saberlo nuevas imágenes, incluso manipuladas, que introducen nuevas vulnerabilidades.
¿Cómo se fija?
Tienes a tu disposición algunos proyectos de código abierto que te ayudarán a descubrir las fechas de caducidad y a prepararte mejor. El proyecto endoflife. date(repositorio GitHub) realiza un seguimiento de más de 300 productos agregando datos de múltiples fuentes y poniéndolos a disposición a través de una API pública. Con endoflife.date y proyectos similares tienes varias opciones:
- Compruebe manualmente en el proyecto las actualizaciones de las dependencias de las que dependen sus aplicaciones y cree tickets o incidencias para las actualizaciones necesarias.
- Escribe un script (Bash, Python, etc.) para obtener las fechas EOL de las dependencias de la API y ejecútalo regularmente, como una tarea cron.
- Incorpore la API pública, o esa secuencia de comandos personalizada, en su plataforma CI para que no se produzcan compilaciones que utilicen un proyecto que esté a punto de alcanzar el fin de su vida útil o lo haya alcanzado.
Como desarrollador, entendemos que su tiempo es valioso y a menudo limitado. Aquí es donde Aikido puede proporcionar una sensación de seguridad: nuestra función de escaneo EOL rastrea su código y contenedores, priorizando los tiempos de ejecución con mayor impacto y exposición, como Node.js o un servidor web Nginx. Como de costumbre, no sólo automatizamos la recopilación de información, sino que emitimos alertas con la gravedad adecuada para informarle, no para abrumarle.

Limitar el uso de recursos del contenedor
¿Qué ganas?
Por defecto, los contenedores no tienen restricciones de recursos y utilizarán tanta memoria o CPU como el programador del host. Limitar el uso de recursos de un contenedor específico puede minimizar el impacto de un ataque DoS. En lugar de colapsar su contenedor o sistema anfitrión debido a una Excepción de Memoria Agotada, el ataque DoS en curso "sólo" impactará negativamente en la experiencia del usuario final.
¿Cómo se fija?
En tiempo de ejecución, puede utilizar la función --memoria
y --cpus
para establecer límites de uso de memoria y CPU, respectivamente. La opción de memoria toma números con g para gigabytes y m para megabytes, mientras que la opción de CPU refleja el límite de CPUs dedicadas disponibles para el contenedor y sus procesos.
docker run --memory="1g" --cpus="2" tu-app:v1.0.1
Esto también funciona con Docker Compose:
servicios:
webapp:
image: your-app:v1.0.1
deploy:
limits:
cpus: '2'
memoria: 1G
...
Su comando final y las opciones de Compose para la seguridad de Docker
Por ahora has visto bastantes consejos de seguridad de Docker y las opciones CLI relevantes o la configuración para ir junto con ellos, lo que significa que estás bastante entusiasmado para ponerlos en práctica o abrumado con la forma de juntarlos todos. A continuación, hemos reunido todas las recomendaciones en un único comando o plantilla de configuración, que te ayudará a empezar a desplegar contenedores Docker más seguros de inmediato.
Obviamente, querrás cambiar algunas de las opciones -como el nombre de usuario no root, las capacidades del kernel, los límites de recursos- en función de las necesidades de tu aplicación.
exportDOCKER_CONTENT_TRUST=1
docker run \
--read-only \
--security-opt=no-new-privileges\
--network your-isolated-network \
--cap-drop ALL
--cap-add CHOWN \
--pids-limit99
--memory="1g" --cpus="2" \
--user=su-usuario \
... # OTRAS OPCIONES
tu-app:v1.0.1
Puede que incluso quieras crear un alias drun con el shell de tu host que puedas invocar sin tener que recordar todos esos detalles.
function drun {
docker run
--read-only \
--security-opt=no-new-privileges\
--network your-isolated-network \
--cap-drop ALL
--cap-add CHOWN \
--pids-limit99
--memory="1g" --cpus="2" \
--user=su-usuario
$1 \
$2
}
A continuación, ejecuta tu alias de la siguiente manera, con tus opciones y el nombre de la imagen: drun -it tu-app:v1.0.1
Si eres de los que utilizan Docker Compose, puedes adaptar todas las mismas opciones en una nueva plantilla básica de Docker Compose con la que podrás trabajar en el futuro:
servicios:
webapp:
image: your-app:v1.0.1
read_only: true
security_opt:
- no-new-privileges:true
networks:
- your-isolated-network
cap_drop:
- ALL
cap_add:
- CHOWN
deploy:
limits:
pids: 9
cpus: '2'
memoria: 1G
... # OTRAS OPCIONES VAN AQUÍ
Bonificación: Ejecute Docker con contenedores sin raíz
Cuando instalas Docker en cualquier sistema, su demonio opera con privilegios de nivel raíz. Incluso si activas todas las opciones anteriores y evitas la escalada de privilegios dentro de un contenedor Docker, el resto del tiempo de ejecución del contenedor en tu sistema anfitrión sigue teniendo privilegios de root. Eso inevitablemente amplía tu superficie de ataque.
La solución son los contenedores sin raíz, que un usuario sin privilegios puede crear y gestionar. La ausencia de privilegios de root implica muchos menos problemas de seguridad para el sistema anfitrión.
Nos gustaría poder ayudarte a utilizar contenedores sin raíz con una sola opción o comando, pero no es tan sencillo. Puedes encontrar instrucciones detalladas en el sitio web de Rootless Containers, incluida una guía práctica para Docker.
¿Qué sigue para la seguridad de Docker?
Si has aprendido algo de esta experiencia, es que la seguridad de los contenedores es una operación a largo plazo. Siempre hay más listas de comprobación y artículos de profundización que leer sobre cómo bloquear los contenedores en Docker o en su primo más antiguo y a menudo incomprendido, Kubernetes. No es posible aspirar a una seguridad de los contenedores impecable, pero dedicar tiempo en su apretado calendario de desarrollo a abordar la seguridad y, a continuación, realizar mejoras graduales basadas en el impacto y la gravedad, dará sus frutos con el paso del tiempo.
Para ayudarle a maximizar ese proceso continuo y priorizar las correcciones que mejorarán significativamente la seguridad de su aplicación, existe Aikido. Acabamos de recaudar 17 millones de dólares para nuestra plataforma de seguridad para desarrolladores "no BS", y nos encantaría que te unieras a nosotros.