🇺🇸 EN
Cloud
·12 min read·↗·🇺🇸 EN

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

Portada principal del artículo: 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 ps

Si 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:latest

Docker 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     133MB

Para 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:87a94228f133e2da99cb16d653cd1373c5b4e8689956386c1c12b60a20421a02

A veces la imagen está vinculada a un contenedor existente, por lo que tendrás que usar la opción -f para 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 IPv6

Listo. 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.html al 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 -f si tu archivo se llama exactamente Dockerfile.

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
 ---> c0fc1c9c473b

Docker 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   176MB

Todo 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 server

Nuestro 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/webdockerize

Puedes 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_ganguly

Para 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.html

Para 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.sh

Puedes 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 danynetwork

Otros 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/webdockerize

Con 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: 1783

Podemos borrar la imagen local usando docker rmi para comprobar la descarga:

docker rmi danywalls/webdockerize:latest 
Untagged: danywalls/webdockerize:latest
Untagged: danywalls/webdockerize@sha256:e6fbc3dbf6bba15cf312d12ee6600bd4f27a2f49e05f105dc1a54c05550a68c5

Y 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:latest

Ahora 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: bridge

Ahora 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 ... done

Tanto 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:

Foto por Sebastian Pena Lambarri en Unsplash

Parte de la serie Cloud

Explora más guías prácticas y arquitecturas reales en la serie Cloud.

Ver serie completa

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.

User avatar
User avatar
User avatar
User avatar
+13K

Únete a 13,800+ desarrolladores y lectores.

Cero spam. Cancela tu suscripción en cualquier momento.