Docker: Instalación y primeros comandos

Avatar de Apuntes Hacking

Introducción

En el post anterior te conté por qué Docker le da mil vueltas a las VMs para servicios de laboratorio. Hoy pasamos a la acción: instalamos Docker, aprendemos los 5 comandos que vas a usar el 90% del tiempo, y entendemos el comando básico de docker run -d -p 8080:80 --rm.

Al final de este post serás capaz de levantar cualquier aplicación vulnerable con un solo comando y saber exactamente qué está pasando por debajo.

1. Instalar Docker en Linux

1.1 Instalar dependencias

sudo apt update
sudo apt install -y ca-certificates curl
Bash

1.2 Añadir la clave GPG oficial de Docker

sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
Bash

1.3 Añadir el repositorio oficial

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu noble stable" | sudo tee /etc/apt/sources.list.d/docker.list
### OJO!! NECESITARÁS CAMBIAR LA URL https://download.docker.com/linux/ubuntu noble stable SEGÚN TU LINUX, EN MICASO VOY A USAR LINUX MINT 22 QUE ESTA BASADO EN UBUNTU 24.04 NOBLE NUMBAT ###

### PODRÍAMOS INSTALAR DOCKER DESDE LOS REPOSITORIOS PROPIOS DE MINT PERO CASI SEGURO NO OBTENDRÍAMOS LA ÚLTIMA VERSIÓN ###
Bash

1.4 Instalar Docker Engine

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Bash

1.5 Verificar que Docker funciona

sudo docker run hello-world
Bash

Deberías ver algo como esto:

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
Bash

2. Evitar sudo en cada comando (opcional pero cómodo)

Por defecto necesitas sudo para lanzar Docker. Para no teclearlo 40 veces al día:

sudo groupadd docker 2>/dev/null
sudo usermod -aG docker $USER
newgrp docker
Bash

Cierra la sesión y vuelve a entrar (o reinicia la terminal). A partir de ahora docker run sin sudo debería funcionar.

3. Los 5 comandos que usarás siempre

Antes de desmenuzar docker run, necesitas un mapa mental de lo básico. Estos comandos son tu kit de supervivencia:

3.1 docker ps — ver qué está corriendo

docker ps
Bash

Muestra los contenedores activos ahora mismo. Si no tienes nada corriendo, verás solo la cabecera de la tabla. Añade -a para ver también los que están parados:

docker ps -a
Bash

La salida te da, para cada contenedor: su ID, la imagen que usa, el comando que ejecutó, cuándo se creó, su estado y los puertos mapeados. Ejemplo de salida:

apuntes@hacking:~$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

apuntes@hacking:~$ docker ps -a
CONTAINER ID   IMAGE         COMMAND    CREATED         STATUS                     PORTS     NAMES
65f182055985   hello-world   "/hello"   2 minutes ago   Exited (0) 2 minutes ago             elegant_dewdney
f9a5c81cfa2f   hello-world   "/hello"   9 minutes ago   Exited (0) 9 minutes ago             flamboyant_jepsen
Bash

3.2 docker images — ver qué imágenes tienes descargadas

docker images
Bash

Una imagen es una plantilla de solo lectura a partir de la cual se crean los contenedores. Cuando haces docker run nginx, Docker busca la imagen nginx en local y, si no la tiene, la descarga automáticamente de Docker Hub.

3.3 docker stop y docker rm — parar y borrar contenedores

docker stop <nombre_o_ID>
docker rm <nombre_o_ID>
Bash

stop envía una señal de apagado educada; rm lo elimina definitivamente. Puedes encadenarlos:

docker stop <nombre_o_ID> && docker rm <nombre_o_ID>
Bash

3.4 docker pull — descargar una imagen sin ejecutarla

docker pull nginx
Bash

Descarga la imagen y la guarda en tu disco. Útil si quieres tenerla lista para cuando la necesites, sin arrancar nada todavía.

3.5 docker exec — ejecutar un comando dentro de un contenedor que ya está corriendo

docker exec -it <nombre_o_ID> bash
Bash

Esto es oro para pentesting: te abre una shell dentro del contenedor como si estuvieras dentro de la máquina víctima. Verás su sistema de archivos, sus procesos, sus usuarios… Ideal para entender cómo está configurado el servicio vulnerable por dentro.

4. El comando estrella — docker run

Ahora sí, el plato fuerte. docker run crea y arranca un contenedor nuevo desde una imagen. Su sintaxis más común:

docker run [opciones] <imagen> [comando]
Bash

Un ejemplo fucional:

docker run -d -p 8080:80 --rm nginx
Bash

Vamos a destriparlo:

4.1 -d — modo detached (segundo plano)

Sin -d:

docker run -p 8080:80 nginx
Bash

El terminal se queda «enganchado» mostrando los logs del servidor. Si pulsas Ctrl+C, matas el contenedor. Esto es útil a veces para depurar en tiempo real, pero normalmente quieres tu terminal libre para seguir trabajando.

Con -d:

docker run -d -p 8080:80 nginx
Bash

El contenedor se va al fondo (detached). Tu terminal queda libre inmediatamente y el contenedor sigue corriendo hasta que lo pares con docker stop.

⚠️
NOTA
Si estás depurando un exploit y quieres ver en vivo qué pide la aplicación vulnerable, quita el -d. Verás las peticiones HTTP llegando al servidor conforme las envías.

4.2 -p 8080:80 — mapeo de puertos (host:contenedor)

Esta opción es fundamental y se lleva mal al principio, así que pon atención.

Formato: -p :

  • Puerto del host (8080): el puerto de tu máquina (el anfitrión) por el que vas a acceder.
  • Puerto del contenedor (80): el puerto que la aplicación escucha dentro del contenedor.

En el ejemplo -p 8080:80:

  • Nginx escucha en el puerto 80 dentro del contenedor (comportamiento por defecto).
  • Tú quieres acceder desde tu navegador, así que mapeas ese 80 interno al 8080 de tu máquina.
  • Abres http://localhost:8080 y ¡voilà!, ves Nginx.

¿Por qué no poner -p 80:80? Porque el puerto 80 de tu host puede estar ocupado por otro servicio o requerir permisos de root. Con 8080 evitas conflictos y no necesitas sudo.

Puedes mapear varios puertos a la vez:

docker run -d -p 8080:80 -p 443:443 nginx
Bash

4.3 --rm — autodestrucción al parar

Sin --rm:

docker run -d -p 8080:80 nginx
docker stop <ID>
docker ps -a
CONTAINER ID   IMAGE         COMMAND                  CREATED          STATUS                      PORTS     NAMES
d93594dcf3cb   nginx         "/docker-entrypoint.…"   17 seconds ago   Exited (0) 3 seconds ago              busy_kepler   # <-- El contenedor sigue apareciendo como "Exited"
65f182055985   hello-world   "/hello"                 27 minutes ago   Exited (0) 27 minutes ago             elegant_dewdney
f9a5c81cfa2f   hello-world   "/hello"                 34 minutes ago   Exited (0) 34 minutes ago             flamboyant_jepsen
Bash

El contenedor parado se queda ocupando un poquito de espacio en disco (metadatos, logs…). No es grave, pero se acumula rápido cuando pruebas 20 cosas al día.

Con –rm:

docker run -d -p 8080:80 --rm nginx
docker stop <ID>
docker ps -a   # ¡Desapareció! No hay rastro.
CONTAINER ID   IMAGE         COMMAND                  CREATED          STATUS                      PORTS     NAMES
65f182055985   hello-world   "/hello"                 27 minutes ago   Exited (0) 27 minutes ago             elegant_dewdney
f9a5c81cfa2f   hello-world   "/hello"                 34 minutes ago   Exited (0) 34 minutes ago             flamboyant_jepsen
Bash

El contenedor se borra automáticamente al detenerse. Ideal para laboratorio: pruebas algo, lo rompes, lo paras y como si no hubiera pasado nada. La imagen de Nginx sigue en tu disco, así que volver a levantarlo es inmediato (no se descarga otra vez).

Resumen:

docker run -d -p 8080:80 --rm nginx
Bash
  1. docker invoca al motor de Docker.
  2. run crea un contenedor a partir de una imagen.
  3. -d lo arranca en segundo plano.
  4. -p 8080:80 conecta el puerto 8080 de tu máquina con el 80 del contenedor.
  5. --rm programa su autodestrucción cuando se pare.
  6. nginx es la imagen base que se descarga de Docker Hub si no la tienes en local.

El flujo completo de Docker es:

  1. Busca la imagen nginx en tu disco local.
  2. Si no la encuentra, la descarga (docker pull implícito).
  3. Crea un sistema de archivos aislado a partir de esa imagen.
  4. Le asigna una IP en la red virtual de Docker.
  5. Mapea los puertos según -p.
  6. Arranca el proceso que la imagen tiene definido como principal (en Nginx, el servidor web).
  7. Devuelve el control a tu terminal y el contenedor sigue vivo.

Otro ejemplo, esta vez levantamos un servidor Apache:

docker run -d -p 8080:80 --rm --name mi_apache httpd:2.4
Bash
  • –name mi_apache le da un nombre legible (en vez de un ID hexadecimal aleatorio como a3f7c2b9).
  • httpd:2.4 es la imagen oficial de Apache HTTP Server versión 2.4.

Verás el HTML de la página por defecto de Apache. Abre el navegador, ve a http://127.0.0.1:8080 y confírmalo visualmente.

¿Quieres husmear dentro del contenedor?

docker exec -it mi_apache bash
Bash

Estás dentro. Prueba:

cat /etc/os-release   # Ver qué "sistema operativo" tiene dentro
ls /usr/local/apache2/htdocs/   # Ver los archivos del sitio web
exit                  # Salir del contenedor
Bash

Limpiar la casa, no dejes basura

Comandos de limpieza:

# Parar y borrar el contenedor activo
docker stop mi_apache   # Si usaste --rm, ya se borra solo

# Ver todos los contenedores (activos e inactivos)
docker ps -a

# Borrar un contenedor específico
docker rm <ID_o_nombre>

# Borrar imágenes que ya no uses
docker rmi httpd:2.4

# Borrar TODO lo que no esté en uso (contenedores parados, imágenes sin usar, redes, caché...)
docker system prune -a
Bash
⚠️
AVISO IMPORTANTE:
docker system prune -a borra todas las imágenes que no estén siendo usadas por al menos un contenedor activo. Úsalo cuando quieras hacer limpieza general.

Chuleta

# Ver qué está corriendo
docker ps

# Ver qué imágenes tengo descargadas
docker images

# Lanzar un servicio en segundo plano, puerto 8080, autodestruible y con nombre
docker run -d -p 8080:80 --rm --nombre <nombre> <imagen>

# Meter una shell dentro del contenedor
docker exec -it <nombre> bash

# Parar y borrar
docker stop <nombre> && docker rm <nombre>
Bash


Etiquetas:

Avatar de Apuntes Hacking

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *