# Uso del SDK de Compose





El paquete `docker/compose` se puede utilizar como una biblioteca de Go por aplicaciones de terceros para gestionar programáticamente aplicaciones contenedorizadas definidas en archivos de Compose. Este SDK proporciona una API completa que te permite integrar la funcionalidad de Compose directamente en tus aplicaciones, de modo que puedas cargar, validar y gestionar entornos de múltiples contenedores sin depender de la CLI de Compose.

Ya sea que necesites orquestar contenedores como parte de un pipeline de despliegue, crear herramientas de gestión personalizadas o integrar la orquestación de contenedores en tu aplicación, el SDK de Compose ofrece las mismas capacidades potentes que impulsan la herramienta de línea de comandos de Docker Compose.

## Configurar el SDK

Para comenzar, crea una instancia del SDK utilizando la función `NewComposeService()`, la cual inicializa un servicio con la configuración necesaria para interactuar con el demonio de Docker y gestionar proyectos de Compose. Esta instancia de servicio proporciona métodos para todas las operaciones principales de Compose, incluyendo la creación, inicio, parada y eliminación de contenedores, así como la carga y validación de archivos de Compose. El servicio gestiona las interacciones subyacentes con la API de Docker y la administración de recursos, lo que te permite concentrarte en la lógica de tu aplicación.

### Requisitos

Antes de utilizar el SDK, asegúrate de estar usando una versión compatible de la CLI de Docker.

```go
require (
    github.com/docker/cli v28.5.2+incompatible
)
```

La versión 29.0.0 y posteriores de Docker CLI dependen del módulo `github.com/moby/moby`, mientras que Docker Compose v5 depende de `github.com/docker/docker`. Esto significa que necesitas fijar `docker/cli v28.5.2+incompatible` para garantizar la compatibilidad y evitar errores de compilación.

### Ejemplo de uso

A continuación, se muestra un ejemplo básico que demuestra cómo cargar un proyecto de Compose e iniciar los servicios:

```go
package main

import (
    "context"
    "log"

	"github.com/docker/cli/cli/command"
	"github.com/docker/cli/cli/flags"
    "github.com/docker/compose/v5/pkg/api"
    "github.com/docker/compose/v5/pkg/compose"
)

func main() {
    ctx := context.Background()

	dockerCLI, err := command.NewDockerCli()
	if err != nil {
		log.Fatalf("Failed to create docker CLI: %v", err)
	}
	err = dockerCLI.Initialize(&flags.ClientOptions{})
	if err != nil {
		log.Fatalf("Failed to initialize docker CLI: %v", err)
	}

    // Crear una nueva instancia del servicio Compose
    service, err := compose.NewComposeService(dockerCLI)
    if err != nil {
        log.Fatalf("Failed to create compose service: %v", err)
    }

    // Cargar el proyecto Compose desde un archivo de Compose
    project, err := service.LoadProject(ctx, api.ProjectLoadOptions{
        ConfigPaths: []string{"compose.yaml"},
        ProjectName: "my-app",
    })
    if err != nil {
        log.Fatalf("Failed to load project: %v", err)
    }

    // Iniciar los servicios definidos en el archivo de Compose
    err = service.Up(ctx, project, api.UpOptions{
        Create: api.CreateOptions{},
        Start:  api.StartOptions{},
    })
    if err != nil {
        log.Fatalf("Failed to start services: %v", err)
    }

    log.Printf("Successfully started project: %s", project.Name)
}
```

Este ejemplo muestra el flujo de trabajo principal: crear una instancia de servicio, cargar un proyecto desde un archivo de Compose e iniciar los servicios. El SDK proporciona muchas operaciones adicionales para gestionar el ciclo de vida de tu aplicación contenedorizada.

## Personalizar el SDK

La función `NewComposeService()` acepta parámetros opcionales de tipo `compose.Option` para personalizar el comportamiento del SDK. Estas opciones te permiten configurar flujos de entrada/salida (I/O streams), límites de concurrencia, modo de prueba (dry-run) y otras características avanzadas.

```go
    // Crear un búfer de salida personalizado para capturar los logs
    var outputBuffer bytes.Buffer

    // Crear un servicio Compose con opciones personalizadas
    service, err := compose.NewComposeService(dockerCLI,
        compose.WithOutputStream(&outputBuffer),          // Redirigir la salida a un escritor (writer) personalizado
        compose.WithErrorStream(os.Stderr),               // Usar stderr para errores
        compose.WithMaxConcurrency(4),                    // Limitar las operaciones concurrentes
        compose.WithPrompt(compose.AlwaysOkPrompt()),     // Confirmar automáticamente todas las solicitudes (prompts)
    )
```

### Opciones disponibles

- `WithOutputStream(io.Writer)`: Redirige la salida estándar a un escritor personalizado.
- `WithErrorStream(io.Writer)`: Redirige la salida de errores a un escritor personalizado.
- `WithInputStream(io.Reader)`: Proporciona un flujo de entrada personalizado para solicitudes interactivas.
- `WithStreams(out, err, in)`: Establece todos los flujos de I/O a la vez.
- `WithMaxConcurrency(int)`: Limita la cantidad de operaciones concurrentes contra la API de Docker.
- `WithPrompt(Prompt)`: Personaliza el comportamiento de confirmación del usuario (utiliza `AlwaysOkPrompt()` para el modo no interactivo).
- `WithDryRun`: Ejecuta operaciones en modo de prueba sin aplicar cambios reales.
- `WithContextInfo(api.ContextInfo)`: Establece información personalizada del contexto de Docker.
- `WithProxyConfig(map[string]string)`: Configura los ajustes del proxy HTTP para las compilaciones.
- `WithEventProcessor(progress.EventProcessor)`: Recibe eventos de progreso y notificaciones de operaciones.

Estas opciones proporcionan un control detallado sobre el comportamiento del SDK, lo que lo hace adecuado para diversos escenarios de integración, incluyendo herramientas de CLI, servicios web, scripts de automatización y entornos de prueba.

## Monitorear operaciones con `EventProcessor`

La interfaz `EventProcessor` te permite monitorear las operaciones de Compose en tiempo real al recibir eventos sobre los cambios aplicados a los recursos de Docker, como imágenes, contenedores, volúmenes y redes. Esto es especialmente útil para construir interfaces de usuario, sistemas de registro (logging) o herramientas de monitoreo que necesiten seguir el progreso de las operaciones de Compose.

### Entender `EventProcessor`

Una operación de Compose, como `up`, `down` o `build`, realiza una serie de cambios en los recursos de Docker. El `EventProcessor` recibe notificaciones sobre estos cambios a través de tres métodos clave:

- `Start(ctx, operation)`: Se llama cuando comienza una operación de Compose, por ejemplo `up`.
- `On(events...)`: Se llama con eventos de progreso para cambios de recursos individuales, por ejemplo, el inicio de un contenedor o la descarga de una imagen.
- `Done(operation, success)`: Se llama cuando se completa la operación, indicando éxito o fallo.

Cada evento contiene información sobre el recurso que se está modificando, su estado actual e indicadores de progreso cuando corresponda (como el progreso de descarga para las imágenes obtenidas).

### Tipos de estado de eventos

Los eventos reportan cambios de recursos con los siguientes tipos de estado:

- Working: La operación está en curso, por ejemplo, creando, iniciando o descargando.
- Done: La operación se completó con éxito.
- Warning: La operación se completó con advertencias.
- Error: La operación falló.

Los valores comunes de texto de estado incluyen: `Creating`, `Created`, `Starting`, `Started`, `Running`, `Stopping`, `Stopped`, `Removing`, `Removed`, `Building`, `Built`, `Pulling`, `Pulled`, entre otros.

### Implementaciones integradas de `EventProcessor`

El SDK proporciona tres implementaciones de `EventProcessor` listas para usar:

- `progress.NewTTYWriter(io.Writer)`: Renderiza una interfaz de usuario de terminal interactiva con barras de progreso y listas de tareas (similar a la salida de la CLI de Docker Compose).
- `progress.NewPlainWriter(io.Writer)`: Genera mensajes de progreso simples basados en texto, adecuados para entornos no interactivos o archivos de registro.
- `progress.NewJSONWriter()`: Renderiza eventos como objetos JSON.
- `progress.NewQuietWriter()`: (Predeterminado) Procesa eventos de forma silenciosa sin generar ninguna salida.

Mediante el uso de `EventProcessor`, se puede conectar una interfaz de usuario personalizada a `docker/compose`.

