# Uso de Docker Build Cloud en CI


El uso de Docker Build Cloud en CI puede acelerar tus pipelines de compilación, lo
que se traduce en menos tiempo de espera y menos cambios de contexto. Controlas
tus flujos de trabajo de CI de la forma habitual y delegas la ejecución de la
compilación en Docker Build Cloud.

La compilación con Docker Build Cloud en CI implica los siguientes pasos:

1. Iniciar sesión en una cuenta de Docker.
2. Configurar Buildx y conectarse al builder.
3. Ejecutar la compilación.

Al utilizar Docker Build Cloud en CI, se recomienda subir el resultado
directamente a un registro, en lugar de cargar la imagen de manera local y luego
subirla. Subir la imagen directamente acelera las compilaciones y evita
transferencias de archivos innecesarias.

Si solo deseas compilar y descartar el resultado, exporta los resultados a la
caché de compilación o realiza la compilación sin etiquetar la imagen. Al
utilizar Docker Build Cloud, Buildx carga automáticamente el resultado de la
compilación si compilas una imagen etiquetada. Consulta
[Cargar resultados de compilación](/build-cloud/usage#cargar-resultados-de-compilación)
para obtener más detalles.

> [!NOTE]
> Las compilaciones en Docker Build Cloud tienen un límite de tiempo de espera
> (timeout) de 90 minutos. Las compilaciones que se ejecuten durante más de 90
> minutos se cancelarán automáticamente.

## Configurar credenciales para CI/CD

Para permitir que tu sistema de CI/CD compile y suba imágenes utilizando Docker
Build Cloud, proporciona tanto un token de acceso como un nombre de usuario.
El tipo de token y el nombre de usuario utilizados dependen del tipo de cuenta y
de los permisos.

- Si eres administrador de la organización o tienes permiso para crear
  [tokens de acceso de la organización (OAT)](/enterprise/security/access-tokens/),
  utiliza un OAT y establece `DOCKER_ACCOUNT` con el nombre de tu organización
  de Docker Hub.
- Si no tienes permiso para crear OATs o utilizas una cuenta personal, utiliza
  un [token de acceso personal (PAT)](/security/access-tokens/) y establece
  `DOCKER_ACCOUNT` con tu nombre de usuario de Docker Hub.

### Crear tokens de acceso

#### Para cuentas de organización

Si eres administrador de la organización:

- Crea un [token de acceso de la organización (OAT)](/enterprise/security/access-tokens/).
  El token debe tener estos permisos:
  1. Alcance (scope) **cloud-connect**
  2. Permiso **Leer repositorios públicos** (Read public repositories)
  3. **Acceso al repositorio** (Repository access) con permiso **Subir imagen** (Image push)
     para el repositorio de destino:
     - Despliega el menú **Repositorio** (Repository).
     - Selecciona **Añadir repositorio** (Add repository) y elige el repositorio de destino.
     - Establece el permiso **Subir imagen** (Image push) para el repositorio.

Si no eres administrador de la organización:

- Solicita al administrador de tu organización un token de acceso con los
  permisos enumerados anteriormente, o utiliza un token de acceso personal.

#### Para cuentas personales

- Crea un [token de acceso personal (PAT)](/security/access-tokens/) con los
  siguientes permisos:
  1.  Acceso de **Lectura y escritura** (Read & write).
      - Nota: Compilar con Docker Build Cloud solo requiere acceso de lectura,
        pero necesitas acceso de escritura para subir imágenes a un repositorio de Docker Hub.

## Ejemplos de plataformas de CI

> [!NOTE]
> En la configuración de tu CI/CD, establece las siguientes variables/secretos:
>
> - `DOCKER_ACCESS_TOKEN` — tu token de acceso (PAT u OAT). Utiliza un secreto para almacenar el token.
> - `DOCKER_ACCOUNT` — el nombre de tu organización de Docker Hub (para OAT) o nombre de usuario (para PAT)
> - `CLOUD_BUILDER_NAME` — el nombre del builder en la nube que creaste en el [Panel de control de Docker Build Cloud](https://app.docker.com/build/)
>
> Esto garantiza que las compilaciones se autentiquen correctamente con Docker Build Cloud.

### GitHub Actions

```yaml
name: ci

on:
  push:
    branches:
      - "main"

jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      - name: Login to Docker Hub
        uses: docker/login-action@v4
        with:
          username: ${{ vars.DOCKER_ACCOUNT }}
          password: ${{ secrets.DOCKER_ACCESS_TOKEN }}

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4
        with:
          driver: cloud
          endpoint: "${{ vars.DOCKER_ACCOUNT }}/${{ vars.CLOUD_BUILDER_NAME }}" # por ejemplo, "acme/default"

      - name: Build and push
        uses: docker/build-push-action@v7
        with:
          tags: "<IMAGE>" # por ejemplo, "acme/my-image:latest"
          # Para pull requests, exportar los resultados a la caché de compilación.
          # De lo contrario, subir a un registro.
          outputs: ${{ github.event_name == 'pull_request' && 'type=cacheonly' || 'type=registry' }}
```

El ejemplo anterior utiliza `docker/build-push-action`, que utiliza
automáticamente el builder configurado por `setup-buildx-action`. Si en su
lugar necesitas utilizar el comando `docker build` de forma directa, tienes dos
opciones:

- Utilizar `docker buildx build` en lugar de `docker build`
- Establecer la variable de entorno `BUILDX_BUILDER` para utilizar el builder en
  la nube:

  ```yaml
  - name: Set up Docker Buildx
    id: builder
    uses: docker/setup-buildx-action@v4
    with:
      driver: cloud
      endpoint: "${{ vars.DOCKER_ACCOUNT }}/${{ vars.CLOUD_BUILDER_NAME }}"

  - name: Build
    run: |
      docker build .
    env:
      BUILDX_BUILDER: ${{ steps.builder.outputs.name }}
  ```

Para obtener más información sobre la variable de entorno `BUILDX_BUILDER`,
consulta [Variables de compilación](/build/building/variables/#buildx_builder).

### GitLab

```yaml
default:
  image: docker:24-dind
  services:
    - docker:24-dind
  before_script:
    - docker info
    - echo "$DOCKER_ACCESS_TOKEN" | docker login --username "$DOCKER_ACCOUNT" --password-stdin
    - |
      apk add curl jq
      ARCH=${CI_RUNNER_EXECUTABLE_ARCH#*/}
      BUILDX_URL=$(curl -s https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/buildx-lab-releases.json | jq -r ".latest.assets[] | select(endswith(\"linux-$ARCH\"))")
      mkdir -vp ~/.docker/cli-plugins/
      curl --silent -L --output ~/.docker/cli-plugins/docker-buildx $BUILDX_URL
      chmod a+x ~/.docker/cli-plugins/docker-buildx
    - docker buildx create --use --driver cloud ${DOCKER_ACCOUNT}/${CLOUD_BUILDER_NAME}

variables:
  IMAGE_NAME: <IMAGE>
  DOCKER_ACCOUNT: <DOCKER_ACCOUNT> # el nombre de tu organización de Docker Hub (o usuario al usar cuenta personal)
  CLOUD_BUILDER_NAME: <CLOUD_BUILDER_NAME> # el nombre del builder en la nube que creaste en el [Panel de control de Docker Build Cloud](https://app.docker.com/build/)

# Compilar una imagen multiplataforma y subirla a un registro
build_push:
  stage: build
  script:
    - |
      docker buildx build \
        --platform linux/amd64,linux/arm64 \
        --tag "${IMAGE_NAME}:${CI_COMMIT_SHORT_SHA}" \
        --push .

# Compilar una imagen y descartar el resultado
build_cache:
  stage: build
  script:
    - |
      docker buildx build \
        --platform linux/amd64,linux/arm64 \
        --tag "${IMAGE_NAME}:${CI_COMMIT_SHORT_SHA}" \
        --output type=cacheonly \
        .
```

### Circle CI

```yaml
version: 2.1

jobs:
  # Compilar una imagen multiplataforma y subirla a un registro
  build_push:
    machine:
      image: ubuntu-2204:current
    steps:
      - checkout

      - run: |
          mkdir -vp ~/.docker/cli-plugins/
          ARCH=amd64
          BUILDX_URL=$(curl -s https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/buildx-lab-releases.json | jq -r ".latest.assets[] | select(endswith(\"linux-$ARCH\"))")
          curl --silent -L --output ~/.docker/cli-plugins/docker-buildx $BUILDX_URL
          chmod a+x ~/.docker/cli-plugins/docker-buildx

      - run: echo "$DOCKER_ACCESS_TOKEN" | docker login --username $DOCKER_ --password-stdin
      - run: docker buildx create --use --driver cloud "${DOCKER_ACCOUNT}/${CLOUD_BUILDER_NAME}"

      - run: |
          docker buildx build \
          --platform linux/amd64,linux/arm64 \
          --push \
          --tag "<IMAGE>" .

  # Compilar una imagen y descartar el resultado
  build_cache:
    machine:
      image: ubuntu-2204:current
    steps:
      - checkout

      - run: |
          mkdir -vp ~/.docker/cli-plugins/
          ARCH=amd64
          BUILDX_URL=$(curl -s https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/buildx-lab-releases.json | jq -r ".latest.assets[] | select(endswith(\"linux-$ARCH\"))")
          curl --silent -L --output ~/.docker/cli-plugins/docker-buildx $BUILDX_URL
          chmod a+x ~/.docker/cli-plugins/docker-buildx

      - run: echo "$DOCKER_ACCESS_TOKEN" | docker login --username $DOCKER_ --password-stdin
      - run: docker buildx create --use --driver cloud "${DOCKER_ACCOUNT}/${CLOUD_BUILDER_NAME}"

      - run: |
          docker buildx build \
          --tag temp \
          --output type=cacheonly \
          .

workflows:
  pull_request:
    jobs:
      - build_cache
  release:
    jobs:
      - build_push
```

### Buildkite

El siguiente ejemplo configura una pipeline de Buildkite utilizando Docker Build
Cloud. El ejemplo asume que el nombre de la pipeline es `build-push-docker` y
que gestionas el token de acceso de Docker utilizando hooks de entorno, pero
siéntete libre de adaptarlo a tus necesidades.

Añade el siguiente hook `environment` al directorio de hooks de tu agente:

```bash
#!/bin/bash
set -euo pipefail

if [[ "$BUILDKITE_PIPELINE_NAME" == "build-push-docker" ]]; then
 export DOCKER_ACCESS_TOKEN="<DOCKER_ACCESS_TOKEN>"
fi
```

Crea un archivo `pipeline.yml` que utilice el plugin `docker-login`:

```yaml
env:
  DOCKER_ACCOUNT: <DOCKER_ACCOUNT> # el nombre de tu organización de Docker Hub (o usuario al usar cuenta personal)
  CLOUD_BUILDER_NAME: <CLOUD_BUILDER_NAME> # el nombre del builder en la nube que creaste en el [Panel de control de Docker Build Cloud](https://app.docker.com/build/)
  IMAGE_NAME: <IMAGE>

steps:
  - command: ./build.sh
    key: build-push
    plugins:
      - docker-login#v2.1.0:
          username: DOCKER_ACCOUNT
          password-env: DOCKER_ACCESS_TOKEN # el nombre de la variable en el hook de entorno
```

Crea el script `build.sh`:

```bash
DOCKER_DIR=/usr/libexec/docker

# Obtener el enlace de descarga del binario de buildx más reciente.
# Establece $ARCH a la arquitectura de CPU (ej. amd64, arm64)
UNAME_ARCH=`uname -m`
case $UNAME_ARCH in
  aarch64)
    ARCH="arm64";
    ;;
  amd64)
    ARCH="amd64";
    ;;
  *)
    ARCH="amd64";
    ;;
esac
BUILDX_URL=$(curl -s https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/buildx-lab-releases.json | jq -r ".latest.assets[] | select(endswith(\"linux-$ARCH\"))")

# Descargar docker buildx con soporte para Build Cloud
curl --silent -L --output $DOCKER_DIR/cli-plugins/docker-buildx $BUILDX_URL
chmod a+x ~/.docker/cli-plugins/docker-buildx

# Conectarte a tu builder y establecerlo como builder predeterminado
docker buildx create --use --driver cloud "${DOCKER_ACCOUNT}/${CLOUD_BUILDER_NAME}"

# Compilación de imagen solo en caché
docker buildx build \
    --platform linux/amd64,linux/arm64 \
    --tag "$IMAGE_NAME:$BUILDKITE_COMMIT" \
    --output type=cacheonly \
    .

# Compilar, etiquetar y subir una imagen docker multiarquitectura
docker buildx build \
    --platform linux/amd64,linux/arm64 \
    --push \
    --tag "$IMAGE_NAME:$BUILDKITE_COMMIT" \
    .
```

### Jenkins

```groovy
pipeline {
  agent any

  environment {
    ARCH = 'amd64'
    DOCKER_ACCESS_TOKEN = credentials('docker-access-token')
    DOCKER_ACCOUNT = credentials('docker-account')
    CLOUD_BUILDER_NAME = '<CLOUD_BUILDER_NAME>'
    IMAGE_NAME = '<IMAGE>'
  }

  stages {
    stage('Build') {
      environment {
        BUILDX_URL = sh (returnStdout: true, script: 'curl -s https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/buildx-lab-releases.json | jq -r ".latest.assets[] | select(endswith(\\"linux-$ARCH\\"))"').trim()
      }
      steps {
        sh 'mkdir -vp ~/.docker/cli-plugins/'
        sh 'curl --silent -L --output ~/.docker/cli-plugins/docker-buildx $BUILDX_URL'
        sh 'chmod a+x ~/.docker/cli-plugins/docker-buildx'
        sh 'echo "$DOCKER_ACCESS_TOKEN" | docker login --username $DOCKER_ACCOUNT --password-stdin'
        sh 'docker buildx create --use --driver cloud "${DOCKER_ACCOUNT}/${CLOUD_BUILDER_NAME}"'
        // Compilación solo en caché
        sh 'docker buildx build --platform linux/amd64,linux/arm64 --tag "$IMAGE_NAME" --output type=cacheonly .'
        // Compilar y subir una imagen multiplataforma
        sh 'docker buildx build --platform linux/amd64,linux/arm64 --push --tag "$IMAGE_NAME" .'
      }
    }
  }
}
```

### Travis CI

```yaml
language: minimal
dist: jammy

services:
  - docker

env:
  global:
    - IMAGE_NAME=<IMAGE> # por ejemplo, "acme/my-image:latest"

before_install: |
  echo "$DOCKER_ACCESS_TOKEN" | docker login --username "$DOCKER_ACCOUNT" --password-stdin

install: |
  set -e 
  BUILDX_URL=$(curl -s https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/buildx-lab-releases.json | jq -r ".latest.assets[] | select(endswith(\"linux-$TRAVIS_CPU_ARCH\"))")
  mkdir -vp ~/.docker/cli-plugins/
  curl --silent -L --output ~/.docker/cli-plugins/docker-buildx $BUILDX_URL
  chmod a+x ~/.docker/cli-plugins/docker-buildx
  docker buildx create --use --driver cloud "${DOCKER_ACCOUNT}/${CLOUD_BUILDER_NAME}"

script: |
  docker buildx build \
  --platform linux/amd64,linux/arm64 \
  --push \
  --tag "$IMAGE_NAME" .
```

### BitBucket Pipelines

```yaml
# Requisitos previos: configurar $DOCKER_ACCOUNT, $CLOUD_BUILDER_NAME, $DOCKER_ACCESS_TOKEN como variables de despliegue
# Esta pipeline asume $BITBUCKET_REPO_SLUG como nombre de la imagen

image: atlassian/default-image:3

pipelines:
  default:
    - step:
        name: Build multi-platform image
        script:
          - mkdir -vp ~/.docker/cli-plugins/
          - ARCH=amd64
          - BUILDX_URL=$(curl -s https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/buildx-lab-releases.json | jq -r ".latest.assets[] | select(endswith(\"linux-$ARCH\"))")
          - curl --silent -L --output ~/.docker/cli-plugins/docker-buildx $BUILDX_URL
          - chmod a+x ~/.docker/cli-plugins/docker-buildx
          - echo "$DOCKER_ACCESS_TOKEN" | docker login --username $DOCKER_ACCOUNT --password-stdin
          - docker buildx create --use --driver cloud "${DOCKER_ACCOUNT}/${CLOUD_BUILDER_NAME}"
          - IMAGE_NAME=$BITBUCKET_REPO_SLUG
          - docker buildx build
            --platform linux/amd64,linux/arm64
            --push
            --tag "$IMAGE_NAME" .
        services:
          - docker
```

### Script de shell

```bash
#!/bin/bash

# Obtener enlace de descarga de la versión de buildx más reciente. Establece $ARCH a la arquitectura de CPU (ej. amd64, arm64)
ARCH=amd64
BUILDX_URL=$(curl -s https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/buildx-lab-releases.json | jq -r ".latest.assets[] | select(endswith(\"linux-$ARCH\"))")

# Descargar docker buildx con soporte para Build Cloud
mkdir -vp ~/.docker/cli-plugins/
curl --silent -L --output ~/.docker/cli-plugins/docker-buildx $BUILDX_URL
chmod a+x ~/.docker/cli-plugins/docker-buildx

# Iniciar sesión en Docker Hub con un token de acceso. Consulta https://docs-docker.esdocu.com/build-cloud/ci/#crear-tokens-de-acceso
echo "$DOCKER_ACCESS_TOKEN" | docker login --username $DOCKER_ACCOUNT --password-stdin

# Conectarte a tu builder y establecerlo como builder predeterminado
docker buildx create --use --driver cloud "${DOCKER_ACCOUNT}/${CLOUD_BUILDER_NAME}"

# Compilación de imagen solo en caché
docker buildx build \
    --tag temp \
    --output type=cacheonly \
    .

# Compilar, etiquetar y subir una imagen docker multiarquitectura
docker buildx build \
    --platform linux/amd64,linux/arm64 \
    --push \
    --tag "<IMAGE>" \
    .
```

### Docker Compose

Utiliza esta implementación si deseas utilizar `docker compose build` con
Docker Build Cloud en CI.

```bash
#!/bin/bash

# Obtener enlace de descarga de la versión de buildx más reciente. Establece $ARCH a la arquitectura de CPU (ej. amd64, arm64)
ARCH=amd64
BUILDX_URL=$(curl -s https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/buildx-lab-releases.json | jq -r ".latest.assets[] | select(endswith(\"linux-$ARCH\"))")
COMPOSE_URL=$(curl -sL \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer <GITHUB_TOKEN>" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  https://api.github.com/repos/docker/compose-desktop/releases \
  | jq "[ .[] | select(.prerelease==false and .draft==false) ] | .[0].assets.[] | select(.name | endswith(\"linux-${ARCH}\")) | .browser_download_url")

# Descargar docker buildx con soporte para Build Cloud
mkdir -vp ~/.docker/cli-plugins/
curl --silent -L --output ~/.docker/cli-plugins/docker-buildx $BUILDX_URL
curl --silent -L --output ~/.docker/cli-plugins/docker-compose $COMPOSE_URL
chmod a+x ~/.docker/cli-plugins/docker-buildx
chmod a+x ~/.docker/cli-plugins/docker-compose

# Iniciar sesión en Docker Hub con un token de acceso. Consulta https://docs-docker.esdocu.com/build-cloud/ci/#crear-tokens-de-acceso
echo "$DOCKER_ACCESS_TOKEN" | docker login --username $DOCKER_ACCOUNT --password-stdin

# Conectarte a tu builder y establecerlo como builder predeterminado
docker buildx create --use --driver cloud "${DOCKER_ACCOUNT}/${CLOUD_BUILDER_NAME}"

# Ejecutar la compilación de la imagen
docker compose build
```

