Cómo usar el comando docker compose push para subir imágenes de servicio

DockerDockerBeginner
Practicar Ahora

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En este laboratorio, aprenderás a utilizar el comando docker compose push para enviar imágenes de servicio definidas en un archivo docker-compose.yaml a un registro (registry). Comenzarás preparando un archivo docker-compose.yaml con imágenes de servicio, luego construirás estas imágenes. Finalmente, practicarás el envío de estas imágenes de servicio a un registro, incluyendo cómo manejar posibles fallos durante el proceso de push.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ImageOperationsGroup(["Image Operations"]) docker(("Docker")) -.-> docker/DockerfileGroup(["Dockerfile"]) docker/ImageOperationsGroup -.-> docker/pull("Pull Image from Repository") docker/ImageOperationsGroup -.-> docker/tag("Tag an Image") docker/ImageOperationsGroup -.-> docker/push("Push Image to Repository") docker/ImageOperationsGroup -.-> docker/images("List Images") docker/DockerfileGroup -.-> docker/build("Build Image from Dockerfile") subgraph Lab Skills docker/pull -.-> lab-555088{{"Cómo usar el comando docker compose push para subir imágenes de servicio"}} docker/tag -.-> lab-555088{{"Cómo usar el comando docker compose push para subir imágenes de servicio"}} docker/push -.-> lab-555088{{"Cómo usar el comando docker compose push para subir imágenes de servicio"}} docker/images -.-> lab-555088{{"Cómo usar el comando docker compose push para subir imágenes de servicio"}} docker/build -.-> lab-555088{{"Cómo usar el comando docker compose push para subir imágenes de servicio"}} end

Preparar un archivo docker-compose.yaml con imágenes de servicio

En este paso, aprenderás cómo crear un archivo docker-compose.yaml para definir y gestionar aplicaciones multi-contenedor en Docker. Docker Compose es una herramienta que te permite definir y ejecutar aplicaciones Docker con múltiples contenedores. Con Compose, utilizas un archivo YAML para configurar los servicios de tu aplicación. Luego, con un solo comando, creas e inicias todos los servicios desde tu configuración.

Primero, navega al directorio del proyecto:

cd ~/project

Ahora, creemos un archivo docker-compose.yaml usando el editor nano. Este archivo definirá dos servicios: un servicio web y un servicio de base de datos.

nano docker-compose.yaml

Pega el siguiente contenido en el archivo docker-compose.yaml:

version: "3.8"
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
  db:
    image: postgres:latest
    environment:
      POSTGRES_PASSWORD: mysecretpassword

Analicemos este archivo:

  • version: '3.8' especifica la versión del formato del archivo Docker Compose.
  • services: define los diferentes servicios que componen tu aplicación.
  • web: define un servicio llamado web.
  • image: nginx:latest especifica que el servicio web usará la imagen Docker nginx:latest. Si la imagen no está disponible localmente, Docker la descargará de Docker Hub.
  • ports: mapea el puerto 80 de la máquina host al puerto 80 del contenedor.
  • db: define un servicio llamado db.
  • image: postgres:latest especifica que el servicio db usará la imagen Docker postgres:latest.
  • environment: establece variables de entorno dentro del contenedor. Aquí, configuramos la contraseña POSTGRES_PASSWORD para la base de datos PostgreSQL.

Guarda el archivo presionando Ctrl + X, luego Y, y Enter.

Puedes ver el contenido del archivo creado usando el comando cat:

cat docker-compose.yaml

Este comando mostrará el contenido del archivo docker-compose.yaml que acabas de crear, permitiéndote verificar su contenido.

Construir las imágenes de servicio

En el paso anterior, definiste tus servicios utilizando imágenes Docker existentes en el archivo docker-compose.yaml. En este paso, aprenderás cómo construir imágenes Docker personalizadas para tus servicios usando Dockerfiles y luego integrarlas en tu archivo docker-compose.yaml.

Primero, creemos un directorio simple para nuestro servicio web y un Dockerfile dentro de él. Navega al directorio del proyecto si no estás ya allí:

cd ~/project

Crea un directorio llamado web y accede a él:

mkdir web
cd web

Ahora, crea un Dockerfile llamado Dockerfile dentro del directorio web usando el editor nano:

nano Dockerfile

Pega el siguiente contenido en el Dockerfile:

FROM ubuntu:latest
RUN apt-get update && apt-get install -y nginx
COPY index.html /var/www/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Este Dockerfile realiza lo siguiente:

  • FROM ubuntu:latest: Parte de la imagen base más reciente de Ubuntu.
  • RUN apt-get update && apt-get install -y nginx: Actualiza la lista de paquetes e instala Nginx.
  • COPY index.html /var/www/html/: Copia un archivo index.html (que crearemos a continuación) en el directorio raíz web de Nginx.
  • EXPOSE 80: Expone el puerto 80 en el contenedor.
  • CMD ["nginx", "-g", "daemon off;"]: Especifica el comando a ejecutar cuando el contenedor inicia, que es iniciar Nginx en primer plano.

Guarda el Dockerfile presionando Ctrl + X, luego Y, y Enter.

Ahora, creemos el archivo index.html que copia el Dockerfile. Permanece en el directorio ~/project/web y crea el archivo:

nano index.html

Pega el siguiente contenido HTML simple en index.html:

<!doctype html>
<html>
  <head>
    <title>Hello from Docker!</title>
  </head>
  <body>
    <h1>Welcome to my Dockerized Nginx!</h1>
    <p>This page is served from a custom Docker image.</p>
  </body>
</html>

Guarda el archivo index.html presionando Ctrl + X, luego Y, y Enter.

Ahora, regresa al directorio raíz del proyecto donde se encuentra tu archivo docker-compose.yaml:

cd ~/project

Necesitamos modificar el archivo docker-compose.yaml para construir el servicio web desde el Dockerfile que acabamos de crear, en lugar de usar una imagen preconstruida. Abre el archivo docker-compose.yaml para editarlo:

nano docker-compose.yaml

Modifica la definición del servicio web para usar la instrucción build en lugar de image:

version: "3.8"
services:
  web:
    build: ./web
    ports:
      - "80:80"
  db:
    image: postgres:latest
    environment:
      POSTGRES_PASSWORD: mysecretpassword

Aquí, build: ./web le indica a Docker Compose que construya la imagen para el servicio web usando el Dockerfile ubicado en el directorio ./web relativo al archivo docker-compose.yaml.

Guarda el archivo docker-compose.yaml modificado presionando Ctrl + X, luego Y, y Enter.

Ahora, puedes construir las imágenes definidas en tu archivo docker-compose.yaml usando el comando docker-compose build. Como Docker Compose no viene preinstalado, primero debes instalarlo.

sudo apt-get update
sudo apt-get install docker-compose-plugin -y

Después de instalar el plugin de Docker Compose, puedes usar el comando docker compose (nota el espacio en lugar del guion en versiones más nuevas).

docker compose build

Este comando leerá tu archivo docker-compose.yaml y construirá la imagen para el servicio web basada en el Dockerfile en el directorio ./web. También descargará la imagen postgres:latest para el servicio db si no está presente. Verás una salida que indica el proceso de construcción para la imagen web.

Una vez completada la construcción, puedes listar las imágenes Docker en tu sistema para ver la imagen recién construida.

docker images

Deberías ver una imagen con un nombre relacionado a tu directorio de proyecto y el nombre del servicio (ej. project-web) y la imagen postgres.

Subir imágenes de servicio a un registro

En el paso anterior, construiste una imagen Docker personalizada para tu servicio web. Ahora aprenderás cómo subir estas imágenes a un registro Docker. Un registro Docker es un sistema de almacenamiento y distribución para imágenes Docker. Docker Hub es un registro público, pero también puedes ejecutar registros privados. Subir imágenes a un registro te permite compartirlas con otros o desplegarlas en diferentes máquinas.

Antes de subir, normalmente necesitas etiquetar tus imágenes con la dirección del registro, tu nombre de usuario y el nombre de la imagen. Para este laboratorio, simularemos la subida a un registro local o a un registro que no requiera autenticación por simplicidad. En un escenario real, primero deberías iniciar sesión en el registro usando docker login.

Primero, listemos las imágenes que tienes para identificar la imagen que construiste para el servicio web. Navega al directorio del proyecto si no estás ya allí:

cd ~/project

Lista las imágenes Docker:

docker images

Deberías ver una imagen con un nombre como project-web. El nombre exacto puede variar ligeramente dependiendo del nombre de tu directorio de proyecto.

Ahora, etiquetemos la imagen project-web para poder subirla a un registro. Usaremos una dirección de registro hipotética your-registry.example.com. Reemplaza your-registry.example.com con la dirección real del registro si estuvieras subiendo a un registro real. Para este ejercicio, usaremos localhost:5000 para simular un registro local.

docker tag project-web localhost:5000/my-web-app:latest

Este comando etiqueta la imagen project-web con el nombre localhost:5000/my-web-app:latest. localhost:5000 es la dirección del registro, my-web-app es el nombre del repositorio, y latest es la etiqueta.

Puedes verificar la nueva etiqueta listando las imágenes nuevamente:

docker images

Ahora deberías ver la imagen project-web listada con dos etiquetas: la original y localhost:5000/my-web-app:latest.

Ahora, subamos la imagen etiquetada al registro local simulado.

docker push localhost:5000/my-web-app:latest

Como estamos simulando un registro local que no está realmente en ejecución, este comando probablemente fallará con un error de conexión. Esto es esperado en este paso ya que nos estamos enfocando en el comando docker push en sí. En el siguiente paso, exploraremos cómo manejar estos fallos.

En un escenario real con un registro en funcionamiento, este comando subiría las capas de la imagen al registro.

Subir imágenes de servicio ignorando fallos

En el paso anterior, intentaste subir tu imagen personalizada del servicio web a un registro simulado, lo que probablemente falló porque el registro no estaba en ejecución. En algunos escenarios, podrías querer intentar subir múltiples imágenes y continuar incluso si una de las subidas falla. Esto puede ser útil en scripts de automatización o al subir a múltiples registros.

Docker Compose proporciona una forma de subir todas las imágenes de servicio definidas en tu archivo docker-compose.yaml. Por defecto, si la subida de una imagen falla, el comando completo se detendrá. Sin embargo, puedes usar la bandera --ignore-pull-failures con el comando docker compose push. Aunque el nombre sugiere ignorar fallos de descarga, en el contexto de docker compose push, también afecta cómo se manejan los fallos de subida dependiendo de la versión de Compose y el contexto. Una forma más directa de manejar fallos individuales de subida en un script es iterar a través de los servicios e intentar subir cada uno, manejando errores para cada subida.

Primero, listemos los servicios definidos en tu archivo docker-compose.yaml. Navega al directorio del proyecto si no estás ya allí:

cd ~/project

Puedes ver los nombres de los servicios (web y db) en tu archivo docker-compose.yaml.

cat docker-compose.yaml

Ahora, intentemos subir todos los servicios definidos en el archivo docker-compose.yaml. Recuerda que el servicio db usa la imagen postgres:latest de Docker Hub, y el servicio web está construido localmente y etiquetado para localhost:5000.

docker compose push

Este comando intentará subir tanto la imagen web (a localhost:5000) como la imagen postgres (a Docker Hub). La subida a localhost:5000 probablemente fallará como antes. La subida a Docker Hub para postgres podría tener éxito si tienes acceso a internet y la imagen no está ya presente en el registro al que estás subiendo (aunque típicamente no subirías imágenes oficiales como postgres a tu propio registro). El comando probablemente reportará un fallo debido a la incapacidad de conectar con localhost:5000.

Para demostrar cómo ignorar fallos, consideremos un escenario donde podrías tener múltiples servicios y quieres subirlos independientemente, continuando incluso si uno falla. Aunque docker compose push no tiene una bandera directa de "ignorar fallos de subida" para todos los servicios de una vez de la misma forma que maneja fallos de descarga, puedes lograr un comportamiento similar en un script iterando a través de los servicios e intentando subir cada uno.

Por ejemplo, podrías escribir un script que intente subir cada servicio individualmente y continúe ante errores. Sin embargo, para el propósito de este laboratorio y demostrar el concepto de manejar posibles fallos durante operaciones de subida, nos enfocaremos en el resultado del comando docker compose push que resaltará el fallo cuando el registro destino sea inalcanzable.

La conclusión clave aquí es entender que subir imágenes es un paso crítico en el pipeline de CI/CD, y manejar posibles fallos (como problemas de red o de autenticación) es importante. Aunque docker compose push podría detenerse en el primer error por defecto, en scripting o escenarios más avanzados, implementarías lógica para manejar resultados individuales de subida.

Confirmemos que el comando docker compose push fue ejecutado.

grep "docker compose push" ~/.zsh_history

Esto confirma que intentaste subir las imágenes usando Docker Compose. La salida del comando en sí mostraría el fallo para la subida del servicio web.

Resumen

En este laboratorio, aprendiste cómo preparar un archivo docker-compose.yaml para definir aplicaciones multi-contenedor en Docker, configurando específicamente servicios como un servidor web (nginx) y una base de datos (PostgreSQL) con sus respectivas imágenes, puertos y variables de entorno. Luego practicaste la construcción de estas imágenes de servicio basadas en las definiciones del archivo docker-compose.yaml.

Además, exploraste cómo subir estas imágenes construidas a un registro Docker usando el comando docker compose push. También aprendiste a manejar posibles fallos durante el proceso de subida utilizando la bandera --ignore-push-failures, permitiendo que la operación de subida continúe incluso si algunas imágenes fallan al cargarse.