- Docker para ciberseguridad – Parte 1: Instalación e imágenes
- Docker para ciberseguridad – Parte 2: Crear imágenes. Dockerfile
- Docker para ciberseguridad – Parte 3: Gestión de contenedores
- Docker para ciberseguridad – Parte 4: docker volume y docker network
- Docker para ciberseguridad – Parte 5: Docker Compose (1)
En las entradas anteriores hemos visto como crear contenedores a partir de una plantilla. Eso que hemos llamado imagen. Que estas se pueden descargar del DockerHub y que podemos construir nuestras imágenes personalizadas. Creamos una imagen personalizada en la entrada 2 y lanzamos un contenedor para probar su funcionalidad.
En esta entrada vamos a ver cómo podemos gestionar todos esos contenedores. Podemos lanzarlos, pararlos, comprobar su estado, su flujo de ejecución, eliminarlos… Vamos a ello.
docker run
Ya hemos visto este comando en las entradas anteriores, cuando en la entrada 1 lanzamos un contenedor de la imagen de httpd que descargamos del DockerHub. O en la entrada 2 cuando lanzamos un contenedor de nuestra imagen personalizada.
Recordad que para ver todas las opciones disponibles de cada comando disponemos de la opción «–help».
$> docker run --help
Las opciones más interesantes:
- «-d» (detached): Ejecuta el contenedor en segundo plano. Lo que no bloquea la terminal donde estamos ejecutando el comando.
- «-p» (port mapping): Sirve para mapear puertos. Se le indica qué puertos de la máquina host se mapean contra qué puertos del contenedor. El formato es «-p puerto_host:puerto_contenedor«.
- «-v» (volume mapping): Mapea directorios del host hacia el contenedor, de forma que todo lo que se almacene en el contenedor en dicha carpeta se guarda en el host y no se pierde. De otra forma, todo dato que generemos en el contenedor en su ejecución se perderá al terminal la ejecución. El formato es indicando la ruta del hot y del contenedor separadas por dos puntos: «-v /path/to/host:/path/to/container«
- «–name»: Da un nombre al contenedor. Es importante nombrar las imágenes y contenedores, de forma que luego sea más sencillo referirnos a ellas. Si no indicamos esta opción, Docker añadirá al contenedor un nombre autogenerado. Formato: «–name micontenedor«.
- «–env» o «-e» (variables de entorno): Sirve para definir y dar un valor a variables de entorno. El formato es: «-e VARIABLE=valor«
- «–rm» (remove container on exit): Elimina automáticamente el contenedor una vez que su ejecución finaliza. Muy útil para cuando hacemos pruebas, ya que cada nueva ejecución de docker run creará un contenedor, dejando un rastro de contenedores detenidos importantes.
- A mí me sirve en la fase de pruebas, ya que si no eliminamos los contenedores, no nos permite levantar varios con el mismo nombre. Obligándome a cambiar de nombre con cada nueva ejecución.
- «-it» (interactive + terminal): El contenedor se ejecuta y dispone una terminal a la cual nos podemos conectar para ejecutar comandos dentro del contenedor. Esto nos conecta automáticamente. El formato es, siendo por ejemplo Ubuntu la imagen: «-it ubuntu /bin/bash«. Para salir basta con desconectar la sesión con el comando «exit«.
- «–network»: Conecta el contenedor a una red específica. Cómo crear y usar redes lo veremos en entradas posteriores. El formato es «–network my-network«
- «–cpus» / «–memory» / «–gpus«: Define las características en cuanto a capacidad del contenedor que estamos levantando. Determina número de cpus, cantidad de RAM asignada y de gpus respectivamente. Los formatos son: «–memory=»512m» –gpus all –cpus=»1.5″»
Para usar todas las opciones importantes y que veáis cuál es la sintaxis, lanzamos un contenedor a partir de la imagen personaliza de apache que creamos en la entrada 2 usando todas las opciones:
$> docker run -it --rm \
--name apachecustomcontainer \
-p 8080:80 \
-e "direcIP=8.8.8.8" \
-v /tmp/dockerApacheCustomVol/:/tmp/mounted/ \
--cpus 4 \
--memory="2g" \
apachecustom \
/bin/bash
IMPORTANTE: Después de la imagen hemos indicado una acción, «/bin/bash«. Esto va a sobrescribir la orden CMD, con lo que cuando ingresemos a la máquina, el script de nmap.sh que indicamos en la sentencia CMD se habrá copiado al contenedor, pero no se habrá ejecutado.
Vamos a probar el volumen montado. Si copiamos un fichero a la carpeta «/tmp/dockerApacheCustomVol/» del host, estará disponible en el contenedor en la carpeta «/tmp/mounted/».
Gestión de contenedores
Una vez que tenemos ya el contenedor creado y lanzado, ¿cómo podemos gestionarlo?
docker ps
El comando «docker ps» nos permite listar los contenedores disponibles.
# Sin argumentos muestra la lista de contenedores en ejecución
$> docker ps
# Muestra todos los contenedores existentes
$> docker ps -a
# Obtiene el listado de los contenedores pero extrae solo los IDs.
# Esta opción es la que usaremos para hacer pipe con otros comandos como docker rm
$> docker ps -q
# Usa filtro para mostrar los contenedores
$> docker ps --filter "status=exited"
El detalle de los filtros posibles que usar con el argumento «–filter» lo podéis encontrar en la documentación oficial.
docker start/restart/stop/kill
De los contenedores ya existentes, podemos controlar su flujo de ejecución con los comandos «docker start«, «docker restart«, «docker stop» y «docker kill«. Os podéis imaginar qué hace cada uno.
# Lanza un contenedor que está parado
$> docker start nombrecontenedor
# Reinicia un contenedor
$> docker restart nombrecontenedor
# Reinicia un pasado un numero de tiempo. En este caso 5 segundos
$> docker restart -t 5 nombrecontenedor
# Para la ejecución de un contenedor
$> docker stop nombrecontenedor
# Para de forma brusca/forzada la ejecución de un contenedor
$> docker kill nombrecontenedor
La diferencia fundamental entre «docker stop» y «docker kill«, aunque ambos sirvan para parar la ejecución de un contenedor, radica en la forma en que realiza esta parada.
- «docker stop«: realiza una parada ordenada. Envía la señal de terminación al contenedor (SIGTERM). Espera 10 segundos. Si el contenedor no se detiene, envía la señal de fuerce de su detención (SIGKILL).
- Esta forma de cerrar permite que las aplicaciones dentro del contenedor cierren de manera ordenada, liberando recursos y guardando el estado si es necesario.
- «docker kill«: detiene el contenedor de forma inmediata. Envía directamente la señal de fuerce de su detención (SIGKILL).
docker rm
El comando «docker rm» se utiliza para eliminar contenedores Docker.
# Elimina un contenedor
$> docker rm nombrecontenedor
# Fuerza su borrado
$> docker rm -f nombrecontenedor
# Elimina todos los contenedores
$> docker ps -a -q | xargs docker rm -f
docker container prune
Al igual que con las imágenes, podemos usar la opción «prune» para los contenedores. Pero en este caso no existen contenedores dangling. «docker container prune» se utiliza para eliminar todos los contenedores detenidos en Docker.
$> docker container prune
Otras opciones
docker stats
Con el comando «docker stats» podemos ver el uso de recursos de los contenedores en ejecución. Nos va a dar datos sobre el consumo de CPU, memoria, I/O de red y de disco de cada contenedor.
$> docker stats nombrecontenedor
docker exec
Este comando lo vais a usar mucho. «docker exec» se utiliza para ejecutar comandos dentro de un contenedor Docker en ejecución. Cuando hemos visto el comando «docker run», hemos visto que invocar una orden «/bin/bash» provocaba que no se ejecutara la orden CMD del Dockerfile.
Con «docker exec» podemos realizar lo siguiente. Primero lanzamos el contenedor y dejamos que la orden CMD se ejecute. Y luego nos conectamos a él.
$> docker exec -it nombrecontenedor /bin/bash
Si no os queréis conectar con una terminal y simplemente ejecutar un comando:
$> docker exec nombrecontenedor whoami
docker cp
Sin necesidad de establecer volúmenes en entre el host y el contenedor, el comando «docker cp» nos va a permitir mover ficheros entre ambos.
# para copiar un archivo desde el contenedor a tu máquina local
$> docker cp nombrecontenedor:/path/to/file /local/path
# para copiar un archivo desde tu máquina local a un contenedor
$> docker cp /local/path nombrecontenedor:/path/to/file
Conclusiones
Ya hemos visto todo lo básico. Ya sabemos qué es Docker, una imagen y un contenedor. Gestionar las imágenes, crear imágenes personalizadas. Lanzar contenedores a partir de estas imágenes y gestionarlos. Como diría mi madre: «¿Qué más quieres Baldomero?».
En próximas entradas vamos a empezar a ver funcionalidades que nos permitan subir el nivel.
Hasta la próxima.