Migre para contentores OCI

Esta página descreve a infraestrutura de compilação necessária para reproduzir o processo de compilação do Cloud Foundry ao gerar imagens de aplicações compatíveis com OCI. Se já tiver concluído o guia de migração do Spring Music, pode usar esta análise detalhada das configurações de migração específicas da sua aplicação.

Diagrama que descreve como criar imagens OCI com ferramentas modernas

Antes de começar

  1. Certifique-se de que configurou um novo projeto para o Cloud Run, conforme descrito na página Configuração do Cloud Run.
  2. Certifique-se de que tem um REGISTRY_URI para armazenar contentores. O Cloud Run recomenda a utilização do Artifact Registry. O Docker é usado para criar imagens intermédias para criar o projeto.

Configurar um processo de compilação compatível com o Cloud Foundry

Tem de criar dois contentores de ICO base para suportar este novo processo:

  • Uma imagem do criador que reflete o processo de compilação do Cloud Foundry e é capaz de compilar o código-fonte da aplicação em droplets do Cloud Foundry.
  • Uma imagem de tempo de execução que reflete o tempo de execução da aplicação Cloud Foundry.

Este processo tem de ser realizado, pelo menos, uma vez pelos administradores da plataforma. Assim que o processo estiver estabelecido, as imagens de compilação e execução podem ser partilhadas por todas as aplicações do Cloud Foundry que precisam de migrar para o Cloud Run.

Crie a imagem do criador

Esta secção cria uma imagem de compilação com cflinux3 como imagem base. A imagem de compilação é usada como ambiente de compilação para criar a imagem da aplicação.

  1. Crie um diretório denominado build/ e cd nele:

    mkdir build && cd build
    
  2. Na pasta build/, crie um novo ficheiro denominado Dockerfile e cole o seguinte código:

    ARG CF_LINUX_FS=cloudfoundry/cflinuxfs3
    
    FROM golang:1.20-bullseye AS builder_build
    WORKDIR /build
    RUN ["git", "clone", "--depth=1", "https://github.com/cloudfoundry/buildpackapplifecycle.git"]
    WORKDIR /build/buildpackapplifecycle
    RUN ["go", "mod", "init", "code.cloudfoundry.org/buildpackapplifecycle"]
    RUN ["go", "mod", "tidy"]
    RUN CGO_ENABLD=0 go build -o /builder ./builder/
    
    FROM $CF_LINUX_FS
    # Set up container tools related to building applications
    WORKDIR /lifecycle
    COPY --from=builder_build /builder /lifecycle/builder
    
    # Set up environment to match Cloud Foundry's build.
    # https://docs.cloudfoundry.org/devguide/deploy-apps/environment-variable.html#app-system-env
    WORKDIR /staging/app
    WORKDIR /tmp
    ENV CF_INSTANCE_ADDR=127.0.0.1:8080 \
    CF_INSTANCE_IP=127.0.0.1 \
    CF_INSTANCE_INTERNAL_IP=127.0.0.1 \
    VCAP_APP_HOST=127.0.0.1 \
    CF_INSTANCE_PORT=8080 \
    LANG=en_US.UTF-8 \
    INSTANCE_GUID=00000000-0000-0000-0000-000000000000 \
    VCAP_APPLICATION={} \
    VCAP_SERVICES={} \
    CF_STACK=cflinuxfs3
    
  3. Use o Cloud Build para criar e publicar a imagem builder

    gcloud builds \
        submit --tag "REGISTRY_URI/builder:stable"
    

    Substitua REGISTRY_URI pelo endereço do Artifact Registry onde quer publicar a imagem de compilação. Por exemplo: REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/builder:stable.

Crie a imagem do tempo de execução

Esta secção cria uma imagem de execução usando cflinux3 como imagem base. A imagem de execução é usada como imagem base quando cria a imagem final da aplicação.

  1. Crie um diretório denominado run/ e cd nele:

    mkdir run && cd run
    
  2. Na pasta run/, crie um novo script de shell denominado entrypoint.bash com o seguinte código:

    #!/usr/bin/env bash
    set -e
    
    if [[ "$@" == "" ]]; then
    exec /lifecycle/launcher "/home/vcap/app" "" ""
    else
    exec /lifecycle/launcher "/home/vcap/app" "$@" ""
    fi
    
  3. Na pasta run/, crie um novo ficheiro denominado Dockerfile e cole o seguinte código:

    ARG CF_LINUX_FS=cloudfoundry/cflinuxfs3
    
    FROM golang:1.20-bullseye AS launcher_build
    WORKDIR /build
    RUN ["git", "clone", "--depth=1", "https://github.com/cloudfoundry/buildpackapplifecycle.git"]
    WORKDIR /build/buildpackapplifecycle
    RUN ["go", "mod", "init", "code.cloudfoundry.org/buildpackapplifecycle"]
    RUN ["go", "mod", "tidy"]
    RUN CGO_ENABLD=0 go build -o /launcher ./launcher/
    
    FROM $CF_LINUX_FS
    # Set up container tools related to launching the application
    WORKDIR /lifecycle
    COPY entrypoint.bash /lifecycle/entrypoint.bash
    RUN ["chmod", "+rx", "/lifecycle/entrypoint.bash"]
    COPY --from=launcher_build /launcher /lifecycle/launcher
    
    # Set up environment to match Cloud Foundry
    WORKDIR /home/vcap
    USER vcap:vcap
    ENTRYPOINT ["/lifecycle/entrypoint.bash"]
    
    # Expose 8080 to allow app to be run on Cloud Foundry,
    # and PORT so the container can be run locally.
    # These do nothing on Cloud Run.
    EXPOSE 8080/tcp
    # Set up environment variables similar to Cloud Foundry.
    ENV CF_INSTANCE_ADDR=127.0.0.1:8080 \
    CF_INSTANCE_IP=127.0.0.1 \
    INSTANCE_IP=127.0.0.1 \
    CF_INSTANCE_INTERNAL_IP=127.0.0.1 \
    VCAP_APP_HOST=127.0.0.1 \
    CF_INSTANCE_PORT=80 \
    LANG=en_US.UTF-8 \
    CF_INSTANCE_GUID=00000000-0000-0000-0000-000000000000 \
    INSTANCE_GUID=00000000-0000-0000-0000-000000000000 \
    CF_INSTANCE_INDEX=0 \
    INSTANCE_INDEX=0 \
    PORT=8080 \
    VCAP_APP_PORT=8080 \
    VCAP_APPLICATION={} \
    VCAP_SERVICES={}
    
  4. Use o Cloud Build para criar e publicar a imagem runtime:

    gcloud builds submit \
        --tag "REGISTRY_URI/runtime:stable"
    

    Substitua REGISTRY_URI pelo endereço do Artifact Registry onde quer publicar a imagem de compilação. Por exemplo: REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/runtime:stable.

Criar aplicações Cloud Foundry como imagens OCI

Cada aplicação migrada para o Cloud Run precisa do seu próprio Dockerfile que corresponda à forma como o Cloud Foundry executa as aplicações. O ficheiro Dockerfile faz o seguinte:

  • Carrega a imagem do criador.
  • Executa o ciclo de vida do buildpack v2 para criar um droplet.
  • Extrai o conteúdo da gota.
  • Carrega o conteúdo da gota na imagem de execução para criar a imagem da aplicação executável.

A imagem da aplicação final é compatível com o Cloud Foundry e o Cloud Run, para que possa fazer testes A/B da sua migração e ajudar a depurar qualquer comportamento inesperado.

Este processo tem de ser realizado pela equipa da aplicação para cada aplicação que tem de ser migrada.

Recolha informações de compilação de uma aplicação do Cloud Foundry implementada

  1. Analise a pilha de aplicações. A pilha é fornecida através da flag -s em cf push ou no campo stack do manifesto da aplicação.

    1. Se a pilha for Windows, é provável que a aplicação seja incompatível com o Cloud Run. Tem de transferir a aplicação para o Linux antes de continuar.
    2. Se a pilha estiver em branco, cflinuxfs3 ou cflinuxfs4, a aplicação pode ser migrada para o Cloud Run.
  2. Reúna a lista dos buildpacks da aplicação. Os buildpacks são fornecidos através da flag -b em cf push, do campo buildpack no manifesto da aplicação ou do campo buildpacks do manifesto da aplicação.

    1. Se não forem especificados buildpacks, significa que estão a ser detetados automaticamente. Consulte a lista de buildpacks detetados na implementação da aplicação mais recente no Cloud Foundry ou especifique-os explicitamente se souber os caminhos.
    2. Se os buildpacks forem URLs, anote os URLs e avance para o passo seguinte.
    3. Para qualquer pacote de compilação que use um nome abreviado, use a tabela seguinte para mapeá-los para URLs:

      Diminutivo URL
      staticfile_buildpack https://github.com/cloudfoundry/staticfile-buildpack
      java_buildpack https://github.com/cloudfoundry/java-buildpack
      ruby_buildpack https://github.com/cloudfoundry/ruby-buildpack
      dotnet_core_buildpack https://github.com/cloudfoundry/dotnet-core-buildpack
      nodejs_buildpack https://github.com/cloudfoundry/nodejs-buildpack
      go_buildpack https://github.com/cloudfoundry/go-buildpack
      python_buildpack https://github.com/cloudfoundry/python-buildpack
      php_buildpack https://github.com/cloudfoundry/php-buildpack
      binary_buildpack https://github.com/cloudfoundry/binary-buildpack
      nginx_buildpack https://github.com/cloudfoundry/nginx-buildpack

      Pode encontrar a origem dos buildpacks menos comuns na organização do GitHub do Cloud Foundry.

  3. Reúna a localização do código-fonte da imagem. A origem é fornecida através do atributo path do manifesto da aplicação ou da flag -p do comando cf push. Se a origem não estiver definida, refere-se ao diretório atual.

  4. Determine se existe um ficheiro .cfignore no diretório do código-fonte. Se estiver lá, mova-o para um ficheiro com o nome .gcloudignore.

Crie a aplicação Cloud Foundry

Neste passo, organiza os elementos de compilação na seguinte estrutura de pastas:

.
├── cloudbuild.yaml
├── Dockerfile
├── .gcloudignore
└── src
    ├── go.mod
    └── main.go
  • cloudbuild.yaml fornece ao Cloud Build instruções de compilação específicas
  • Dockerfile vai usar as imagens de compilação e execução dos passos anteriores para criar a imagem da aplicação
  • src/ contém o código-fonte da sua aplicação
  1. Crie um ficheiro denominado Dockerfile no diretório com o seguinte conteúdo:

    ARG BUILD_IMAGE
    ARG RUN_IMAGE
    FROM $BUILD_IMAGE as build
    
    COPY src /staging/app
    COPY src /tmp/app
    
    ARG BUILDPACKS
    RUN /lifecycle/builder \
    -buildArtifactsCacheDir=/tmp/cache \
    -buildDir=/tmp/app \
    -buildpacksDir=/tmp/buildpacks \
    -outputBuildArtifactsCache=/tmp/output-cache \
    -outputDroplet=/tmp/droplet \
    -outputMetadata=/tmp/result.json \
    "-buildpackOrder=${BUILDPACKS}" \
    "-skipDetect=true"
    
    FROM $RUN_IMAGE
    COPY --from=build /tmp/droplet droplet
    RUN tar -xzf droplet && rm droplet
    
  2. Crie um ficheiro denominado cloudbuild.yaml no diretório com o seguinte conteúdo:

    steps:
    - name: gcr.io/cloud-builders/docker
      args:
      - 'build'
      - '--network'
      - 'cloudbuild'
      - '--tag'
      - '${_TAG}'
      - '--build-arg'
      - 'BUILD_IMAGE=${_BUILD_IMAGE}'
      - '--build-arg'
      - 'RUN_IMAGE=${_RUN_IMAGE}'
      - '--build-arg'
      - 'BUILDPACKS=${_BUILDPACKS}'
      - '.'
    images:
    - "${_TAG}"
    options:
      # Substitute build environment variables as an array of KEY=VALUE formatted strings here.
      env: []
    substitutions:
      _BUILD_IMAGE: BUILD_IMAGE_URI
      _RUN_IMAGE:  RUN_IMAGE_URI
      _BUILDPACKS: BUILDPACK_URL
      _TAG: APP_ARTIFACT_REGISTRY/APP_NAME:latest
    
    • Substitua BUILD_IMAGE_URI pelo URI da imagem de compilação criada nos passos anteriores.
    • Substitua RUN_IMAGE_URI pelo URI da imagem de execução criada nos passos anteriores.
    • Substitua BUILDPACK_URL pelos URLs dos buildpacks usados pela sua aplicação. Pode ser uma lista separada por vírgulas com vários buildpacks.
  3. Se tiver um ficheiro .cfignore, copie-o para o diretório com o nome .gcloudignore.

  4. Crie um diretório denominado src no diretório.

  5. Copie o conteúdo da sua candidatura para src:

    1. Se a origem for um ficheiro ZIP (incluindo ficheiros .jar), descomprima o conteúdo para src.
    2. Se o código-fonte for um diretório, copie o conteúdo para src.
  6. Execute gcloud builds submit . para criar a sua aplicação.

Incompatibilidades conhecidas

  • Os buildpacks que dependem de variáveis de ambiente injetadas do Cloud Foundry, como VCAP_SERVICES, não funcionam. Em alternativa, deve declarar explicitamente uma dependência do que injetam através do sistema de gestão do seu idioma.
  • Para aplicar patches às imagens produzidas desta forma, tem de reconstruir a imagem com uma versão mais recente da imagem de compilação e execução. As imagens de aplicações não são corrigidas automaticamente através da atualização das stemcells do BOSH se as executar no Cloud Foundry.
  • As compilações ocorrem num ambiente de rede diferente do seu cluster do Cloud Foundry. Pode ter de configurar pools do Cloud Build personalizados com acesso aos seus espelhos de pacotes internos.

O que se segue