Cómo empezar con Docker: Guía paso a paso para principiantes

Saber desplegar aplicaciones con Docker es una habilidad muy demandada hoy en día, y este artículo te ayudará (y a mí también) a pasar de cero a defenderte y trabajar con Docker con soltura.
Los puntos clave de esta guía son:
- Instalar y ejecutar Docker.
- Crear y compilar imágenes.
- Montar volúmenes.
- Crear redes entre contenedores.
- Publicar imágenes en Docker Hub.
- Usar Docker Compose.
Al leer la documentación oficial de Docker, entendí que Docker nos da la libertad de ejecutar nuestras aplicaciones en cualquier entorno, sin importar el lenguaje ni el framework, ofreciendo ventajas clave:
- Una forma sencilla de distribuir y desplegar una aplicación.
- Facilidad para crear entornos de prueba (sandboxes) para desarrollo.
- Cero conflictos de versiones y total consistencia entre entornos.
- Claridad total sobre las dependencias y los requisitos de nuestras apps.
A continuación, vemos cómo instalar y configurar Docker en tu sistema.
Instalar y ejecutar Docker
Docker ofrece un instalador visual para Windows y Mac. En Linux necesitas ejecutar algunos comandos en la terminal. Puedes revisar todos los pasos en la web oficial de Docker (https://docs.docker.com/engine/install/ubuntu/) o utilizar el siguiente script de instalación:
Funciona en Ubuntu 20 o superior.
sudo apt install apt-transport-https ca-certificates curl software-properties-common -y
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable" -y
sudo apt update
sudo apt install docker-ce -y
sudo usermod -aG docker ${USER}
su - ${USER}
id -nG
sudo curl -L "https://github.com/docker/compose/releases/download/1.28.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
docker psSi todo se instaló bien, prueba tu instalación ejecutando el comando docker run hello-world en la terminal:
docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:37a0b92b08d4919615c3ee023f7ddb068d12b8387475d64c622ac30f45c29c51
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.El comando descarga la imagen y la ejecuta. Si ves este mensaje en tu pantalla, ya estás listo para el siguiente paso: entender cómo funcionan las imágenes de Docker.
Imágenes de Docker
Una imagen de Docker es como una caja o plantilla empaquetada. Puede contener uno o varios servicios: aplicaciones, bases de datos, servidores web, sistemas de caché, etc.
Por ejemplo, si necesitas un servidor web como Nginx, Docker descarga y ejecuta una imagen con Nginx listo para usar. Así no tienes que instalar Linux desde cero, compilar Nginx manualmente ni configurar dependencias complejas en tu sistema operativo.
Si ya has trabajado con Git, la idea te resultará muy familiar: cuando ejecutas docker pull nginx, Docker busca la imagen primero en tu máquina local. Si no la encuentra, la descarga directamente desde Docker Hub.
Docker Hub es el equivalente a GitHub, pero para imágenes de Docker.
dany@dany:~$ docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
Digest: sha256:644a70516a26004c97d0d85c7fe1d0c3a67ea8ab7ddf4aff193d9f301670cf36
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latestDocker incluye más comandos útiles para administrar imágenes. Por ejemplo, docker images lista todas las imágenes guardadas localmente en tu equipo:
dany@dany:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 87a94228f133 2 weeks ago 133MBPara eliminar imágenes que ya no necesitamos, usamos docker rmi pasando el ID de la imagen o su nombre:
dany@dany:~$ docker rmi nginx
Untagged: nginx:latest
Untagged: nginx@sha256:644a70516a26004c97d0d85c7fe1d0c3a67ea8ab7ddf4aff193d9f301670cf36
Deleted: sha256:87a94228f133e2da99cb16d653cd1373c5b4e8689956386c1c12b60a20421a02A veces la imagen está vinculada a un contenedor existente, por lo que tendrás que usar la opción
-fpara forzar su eliminación.
Con la imagen descargada en nuestro sistema, el siguiente paso es ponerla en marcha ejecutando un contenedor.
Ejecutar contenedores
Ahora que tenemos la imagen de Nginx en nuestra máquina, Docker nos permite iniciar Nginx y acceder al puerto que expone. En pocas palabras, es como decirle a Docker:
Oye Docker, por favor ejecuta Nginx usando el puerto X de mi máquina y redirige ese puerto al puerto Y de Nginx dentro del contenedor. El comando exacto es docker run -p 8080:80 nginx.
El contenedor arranca y muestra los registros de actividad en la terminal:
docker run -p 8080:80 nginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6Listo. Abre tu navegador y entra a http://localhost:8080. El siguiente paso es aprender a crear nuestra propia imagen personalizada con un Dockerfile.
El Dockerfile
Construir una imagen propia en Docker requiere un archivo específico: el Dockerfile. Este archivo contiene todas las instrucciones que Docker ejecutará secuencialmente para construir la imagen final.
El Dockerfile es un archivo de texto con un conjunto de instrucciones directas. Estas son las más utilizadas:
FROM: La imagen base desde donde partimos (por ejemplo,FROM node:alpine).LABEL: Añade metadatos o información adicional (por ejemplo,LABEL author="Dany").ENV: Declara variables de entorno (por ejemplo,ENV NODE_ENV=production).WORKDIR: Define el directorio de trabajo dentro del contenedor (por ejemplo,WORKDIR /var/www).COPY: Copia archivos de nuestra máquina al contenedor (por ejemplo,COPY index.html /var/www).RUN: Ejecuta un comando dentro del contenedor durante la construcción (por ejemplo,RUN npm install).EXPOSE: Indica el puerto de red que abrirá el contenedor (por ejemplo,EXPOSE 8080).ENTRYPOINT: El comando principal que se ejecuta al iniciar el contenedor (por ejemplo,ENTRYPOINT ["./app.sh"]).
Ahora que conocemos las instrucciones clave, pasemos al siguiente paso: escribir el archivo y compilar la imagen con los siguientes requisitos:
- Partir de una imagen base
node:alpine(que ya incluye Node.js). - Definir nuestro nombre como autor.
- Declarar una variable de entorno.
- Instalar el paquete npm
http-server. - Definir el directorio de trabajo.
- Copiar un archivo
index.htmlal contenedor. - Definir el comando de arranque con
http-server.
Compilar nuestra imagen
Crea un archivo llamado app.dockerfile:
FROM node:alpine
LABEL author="Dany Paredes"
ENV production=false
WORKDIR /var/www
COPY index.html .
RUN npm install http-server -g
EXPOSE 8080
ENTRYPOINT ["http-server"]En el mismo directorio donde guardaste app.dockerfile, crea un archivo index.html con un mensaje simple:
<h1>Hello! from docker!!</h1>Compila la imagen usando el comando docker build. Usa la bandera -t para indicar el nombre o etiqueta de la imagen, y -f para especificar qué archivo Dockerfile utilizar:
Puedes omitir
-fsi tu archivo se llama exactamenteDockerfile.
docker build -t webdockerize -f app.dockerfile .
Sending build context to Docker daemon 3.072kB
Step 1/8 : FROM node:alpine..
Successfully built 437881e62fa2
Successfully tagged blog:latest
---> c0fc1c9c473bDocker compiló la imagen con éxito. Ahora listamos las imágenes disponibles y veremos webdockerize en la lista:
dany@dany:~/Documents/dockriz$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
webdockerize latest 437881e62fa2 5 minutes ago 176MBTodo está listo para ejecutar la imagen con el comando docker run mapeando el puerto 8080:
docker run -p 8088:8080 webdockerize
Starting up http-server, serving ./
http-server version: 14.0.0
Available on:
http://127.0.0.1:8080
http://172.17.0.2:8080
Hit CTRL-C to stop the serverNuestro servidor web ya está funcionando. Entra a http://localhost:8088 en tu navegador y verás la página con el saludo desde Docker. Ahora veamos cómo compartir archivos de nuestra máquina con el contenedor sin reconstruir la imagen cada vez.
Contenedores con volúmenes
Si quieres que el contenedor acceda a un directorio local de tu máquina sin tener que copiar los archivos dentro de la imagen en cada cambio, puedes usar volúmenes.
La opción -v le indica a Docker que monte una carpeta de tu sistema anfitrión dentro del contenedor. Funciona de manera similar al mapeo de puertos: -v ruta_externa:ruta_interna.
docker run -p 8088:8080 -v /home/dany/Documents/dockriz/app:/var/www danywalls/webdockerizePuedes usar
${PWD}si quieres apuntar al directorio actual de forma dinámica.
Con el volumen montado, ya podemos modificar archivos en tiempo real. Ahora veamos qué herramientas tenemos para inspeccionar y gestionar contenedores en ejecución.
Interactuar con los contenedores
Una vez que el contenedor está activo, a menudo necesitamos saber qué contenedores están corriendo, ingresar a la terminal interna de alguno de ellos o revisar los registros de salida (logs). Docker ofrece soluciones sencillas para cada situación.
Para listar todos los contenedores (tanto activos como detenidos), usamos docker ps -a:
docker ps -a
ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8a21256f7f3f nginx "/docker-entrypoint.…" 5 seconds ago Exited dazzling_gangulyPara ingresar a la terminal interactiva del contenedor, ejecuta docker exec -it <container_id> sh (o bash según la imagen). Esto te dará acceso directo a su sistema de archivos interno:
docker exec -it 34bb0840ddb5 sh
/var/www # ls
index.htmlPara consultar los logs generados por el contenedor, usa docker logs pasando el ID o nombre del contenedor:
docker logs 8a21256f7f3f
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.shPuedes revisar todos los comandos disponibles ejecutando docker --help o visitando las guías oficiales en https://docs.docker.com/go/guides/. Ahora que sabemos manipular contenedores individuales, veamos cómo conectarlos entre sí mediante redes.
Redes en Docker
En proyectos reales casi siempre necesitamos ejecutar varios contenedores que se comuniquen entre sí, por ejemplo una aplicación web conectada a una base de datos o a una API.
Para permitir que los contenedores hablen entre ellos usamos una red tipo puente (bridge network), gestionada con el comando docker network.
Para crear una red nueva usamos docker network create, indicando el driver correspondiente. En este ejemplo uso el driver bridge, pensado para comunicar contenedores dentro de la misma máquina:
docker network create --drive bridge danynetworkOtros comandos muy útiles para redes son:
docker network ls: Muestra la lista de redes creadas.docker network rm <nombre>: Elimina una red específica.
Puedes leer más sobre los controladores de red en https://docs.docker.com/network/#network-drivers
Para iniciar un contenedor conectado a una red específica, usamos la bandera --net junto con el nombre de la red:
docker run -d --net=danynetwork -p 3050:3000 danywalls/webdockerizeCon la red configurada, los contenedores pueden comunicarse de forma aislada. El siguiente paso es compartir nuestras imágenes personalizadas con otros desarrolladores en Docker Hub.
Docker Hub
Docker Hub funciona como GitHub, pero para almacenar y compartir nuestras imágenes de Docker. Si creas una cuenta en https://hub.docker.com/, puedes iniciar sesión desde tu terminal ejecutando docker login. Ingresas tus credenciales y tu entorno quedará listo para subir imágenes.
Vuelve a compilar la imagen usando la opción -t con el formato tu_usuario/nombre_imagen:
docker build -t danywalls/webdockerize -f app.dockerfile .Luego, sube la imagen con docker push, usando la etiqueta asociada a tu cuenta:
dany@dany:~/Documents/dockriz$ docker push danywalls/webdockerize:latest
The push refers to repository [docker.io/danywalls/webdockerize]
2d6ed4627650: Pushed
e9522abed4c4: Pushed
a40075dcb1c2: Pushed
bdfe600c60fd: Mounted from library/node
e9b39456535c: Mounted from library/node
d61ddabe4e93: Mounted from library/node
e2eb06d8af82: Mounted from library/node
latest: digest: sha256:e6fbc3dbf6bba15cf312d12ee6600bd4f27a2f49e05f105dc1a54c05550a68c5 size: 1783Podemos borrar la imagen local usando docker rmi para comprobar la descarga:
docker rmi danywalls/webdockerize:latest
Untagged: danywalls/webdockerize:latest
Untagged: danywalls/webdockerize@sha256:e6fbc3dbf6bba15cf312d12ee6600bd4f27a2f49e05f105dc1a54c05550a68c5Y ahora descargamos la imagen directamente desde Docker Hub con el comando docker pull:
docker pull danywalls/webdockerize:latest
latest: Pulling from danywalls/webdockerize
Digest: sha256:e6fbc3dbf6bba15cf312d12ee6600bd4f27a2f49e05f105dc1a54c05550a68c5
Status: Downloaded newer image for danywalls/webdockerize:latest
docker.io/danywalls/webdockerize:latestAhora que sabemos compilar, subir y descargar imágenes, podemos simplificar todo este flujo con múltiples contenedores usando Docker Compose.
Docker Compose
Podemos simplificar todos los pasos anteriores utilizando Docker Compose.
Docker Compose nos permite definir varios servicios mediante un archivo YAML: compilar múltiples imágenes, iniciar y detener contenedores, y mantener toda la configuración en un solo lugar.
Comandos básicos de Docker Compose:
docker-compose build: Toma todos los servicios del archivo y compila sus imágenes.docker-compose up: Inicia todos los contenedores definidos.docker-compose down: Detiene y elimina los contenedores y redes creados.
Puedes leer más sobre Docker Compose en https://docs.docker.com/compose/
Para organizar estos comandos en un solo lugar, necesitamos definir la estructura del archivo docker-compose.yml.
El archivo docker-compose.yml
Las secciones principales de este archivo son:
version: Especifica la versión del formato (por ejemplo,'3.0').services: La definición de cada contenedor que formará parte de la aplicación.networks: Define la red compartida entre los contenedores.depends_on: Establece el orden de inicio o dependencia entre contenedores.
Crea un archivo llamado docker-compose.yml y define dos servicios: web y api.
image: Indica de dónde se obtiene la imagen (local o Docker Hub).ports: Configura el mapeo de puertos hacia el host.networks: Asigna el contenedor a una red.depends_on: Indica si un contenedor necesita que otro inicie primero.
El archivo docker-compose.yml queda de la siguiente manera:
version: '3.0'
services:
web:
image: danywalls/webdockerize
ports:
- '8080:8080'
networks:
- danynetwork
depends_on:
- api
api:
image: danywalls/apijson
ports:
- '3000:8080'
networks:
- danynetwork
networks:
danynetwork:
driver: bridgeAhora iniciamos los contenedores ejecutando docker-compose up:
docker-compose up
Building with the native build. Learn about the native build in Compose here: https://docs.docker.com/go/compose-native-build/
Creating dockriz_api_1 ... done
Creating dockriz_web_1 ... doneTanto el servicio web como la API estarán corriendo. Si necesitas detener los contenedores y mantener su estado, ejecuta docker-compose stop:
docker-compose stop¡Eso es todo! Espero que esta guía te sirva para dar tus primeros pasos con Docker: ejecutar contenedores, compilar imágenes, configurar redes y simplificar flujos con Docker Compose.
Si te sirvió este artículo, ¡compártelo!
Enlaces útiles:
- https://typeofnan.dev/how-to-stop-all-docker-containers/
- https://www.docker.com/sites/default/files/d8/2019-09/docker-cheat-sheet.pdf
Foto por Sebastian Pena Lambarri en Unsplash
Explora más guías prácticas y arquitecturas reales en la serie Cloud.
Artículos Relacionados
Compartir este artículo
Si esta guía te resultó útil, compártela con tu equipo o con otros desarrolladores.
Software real. Lecciones reales.
Comparto las lecciones que aprendí por las malas, para que puedas evitarlas o estar preparado cuando ocurran.
Únete a 13,800+ desarrolladores y lectores.
Cero spam. Cancela tu suscripción en cualquier momento.