Publicar uma imagem de aplicação no ECR

AWSBeginner
Pratique Agora

Introdução

Sua equipe está pronta para entregar uma pequena aplicação HTTP. Empacote o código fornecido em uma imagem de contêiner, armazene-a no Amazon Elastic Container Registry (ECR) e demonstre que aquela versão exata inicia e responde a uma solicitação. Preserve o repositório de referência separado e remova os recursos que criar.

Conclua primeiro AWS Foundations e os fundamentos de políticas de identidade do IAM. Os conceitos de Docker são apresentados aqui; você não precisa escrever o aplicativo nem ter uma conta pessoal da AWS. Esta VM independente oferece AWS CLI configurada, Docker, Dockerfile e código-fonte. Use AWS View, acima, para observar os repositórios e testar o aplicativo, e Terminal, abaixo, para os comandos. Ambos leem o mesmo estado dos recursos.

Relação com a certificação

Certificação Tarefa do exame Prática
Developer – Associate (DVA-C02) Tarefa 3.1, habilidade 3.1.1 Empacotar o código e o ambiente de execução de uma aplicação em uma imagem de contêiner para implantação.

Visão geral do laboratório

Diagrama conceitual: criar a aplicação, publicar sua imagem no ECR e obter o digest exato para executar um contêiner Docker que responde a HTTP.

Criar um repositório de imagens imutável

Nesta etapa, crie o repositório que armazenará a versão da aplicação.

Uma imagem empacota os arquivos e o ambiente de execução. Um contêiner é uma instância em execução da imagem. Um registro armazena e distribui imagens; um repositório ECR agrupa as de uma aplicação. Armazenar a imagem não inicia o aplicativo.

Acesse o diretório preparado e examine o Dockerfile. cat exibe um arquivo de texto:

cd /home/labex/project
cat application/Dockerfile

FROM escolhe a imagem base de Python, COPY adiciona o aplicativo, USER escolhe um usuário sem privilégios e CMD define o comando de inicialização. A referência base sha256 fixa o conteúdo da imagem base, não o da sua nova imagem.

Crie ct-demo. Uma tag é um nome legível, como release-1. IMMUTABLE impede substituir uma tag existente por conteúdo diferente e mantém os nomes de versões confiáveis:

aws ecr create-repository \
  --repository-name ct-demo \
  --image-tag-mutability IMMUTABLE

A resposta inclui repositoryUri, o endereço usado pelo Docker, e imageTagMutability: IMMUTABLE. Salve a URI em uma variável do shell. $(...) captura a saída, --query seleciona um campo e --output text remove as aspas JSON:

REPOSITORY_URI=$(aws ecr describe-repositories \
  --repository-names ct-demo \
  --query 'repositories[0].repositoryUri' \
  --output text)
echo "$REPOSITORY_URI"

Mantenha esta sessão do Terminal aberta para preservar as variáveis. Em AWS View, acima, ct-demo aparece com zero imagens ao lado de ct-reference. O repositório de referência pertence a outro aplicativo e está fora do seu escopo de limpeza.

Criar e publicar a versão

Nesta etapa, crie o aplicativo fornecido e envie sua imagem para o ECR.

O Docker precisa entrar no registro antes do envio. O endereço do registro é a parte da URI antes da primeira barra. ${REPOSITORY_URI%%/*} remove essa barra e tudo depois dela:

REGISTRY=${REPOSITORY_URI%%/*}
echo "$REGISTRY"

Solicite à AWS CLI uma senha temporária do ECR e passe-a diretamente ao Docker. O pipe | conecta a saída ao próximo comando; --password-stdin evita expor a senha nos argumentos ou na saída do Terminal. Não a imprima nem a salve por conta própria:

aws ecr get-login-password | docker login \
  --username AWS \
  --password-stdin "$REGISTRY"

O Docker mostra Login Succeeded. Isso permite apenas as operações autorizadas para sua identidade, não acesso a todos os repositórios.

Crie a imagem a partir de application. -t atribui a URI e a tag de versão ao resultado. O último argumento é o contexto de build, o diretório cujos arquivos podem ser usados por COPY:

docker build -t "${REPOSITORY_URI}:release-1" application

Envie a imagem. O Docker carrega as camadas do sistema de arquivos e o manifest que descreve o conteúdo:

docker push "${REPOSITORY_URI}:release-1"

Ao terminar, o Docker mostra um digest sha256:.... Um digest identifica o conteúdo exato; uma tag é um nome. Mesmo quando um repositório permite mudar tags, o digest continua ligado ao conteúdo original.

Consulte o ECR para confirmar a versão armazenada:

aws ecr describe-images \
  --repository-name ct-demo \
  --image-ids imageTag=release-1 \
  --query 'imageDetails[0].{Tags:imageTags,Digest:imageDigest}'

Salve também seu digest em uma variável:

IMAGE_DIGEST=$(aws ecr describe-images \
  --repository-name ct-demo \
  --image-ids imageTag=release-1 \
  --query 'imageDetails[0].imageDigest' \
  --output text)

O digest do ECR deve corresponder ao de docker push. Em AWS View, acima, ct-demo contém release-1 e seu digest. A aplicação ainda não está executando; você a iniciará no próximo passo.

Executar a imagem exata publicada

Nesta etapa, obtenha a imagem por digest e teste um contêiner real da aplicação.

Primeiro remova a imagem criada localmente. docker image rm remove uma referência local, não a imagem armazenada no ECR. O próximo pull recuperará a versão publicada:

docker image rm "${REPOSITORY_URI}:release-1"

Combine URI e digest com @ para escolher o conteúdo exato:

docker pull "${REPOSITORY_URI}@${IMAGE_DIGEST}"

O Docker informa o mesmo digest e o download bem-sucedido. Inicie-o como ct01-app. --detach executa em segundo plano; --publish 127.0.0.1:8081:8000 conecta a porta 8081 do host à porta 8000 do aplicativo. O endereço de loopback limita o acesso direto a esta VM. A imagem já escolhe um usuário sem privilégios; --read-only torna a raiz somente leitura, --cap-drop ALL remove as capabilities do Linux e no-new-privileges impede obter privilégios adicionais:

docker run --detach \
  --name ct01-app \
  --read-only \
  --cap-drop ALL \
  --security-opt no-new-privileges \
  --memory 256m \
  --publish 127.0.0.1:8081:8000 \
  "${REPOSITORY_URI}@${IMAGE_DIGEST}"

O ID do contêiner indica que o Docker aceitou a inicialização, mas não comprova a saúde do aplicativo. Teste HTTP: curl --fail falha em erros HTTP; --retry-all-errors repete erros de conexão durante o início, incluindo uma breve redefinição da conexão:

curl --fail --silent --show-error \
  --retry 5 --retry-all-errors --retry-delay 1 \
  http://127.0.0.1:8081/

Espere JSON com "release": "release-1" e o hostname do contêiner. Examine os logs para confirmar a solicitação real:

docker logs ct01-app

Deve aparecer served application request. Hostname e horários variam. Em AWS View, acima, selecione Request application. A resposta também deve informar release-1; o botão envia uma solicitação HTTP real ao contêiner.

Estado real de AWS View: o ECR contém release-1 e seu digest, enquanto o aplicativo Docker responde com a mesma versão. Digest e hostname são valores de exemplo desta execução.

Remover seus recursos

Nesta etapa, pare o aplicativo e remova sua imagem local e seu repositório ECR, preservando o repositório de referência.

Primeiro pare o contêiner:

docker stop ct01-app

Depois remova-o. Remover um contêiner não remove sua imagem:

docker rm ct01-app

Sem contêineres em execução utilizando-a, remova a referência local por digest:

docker image rm "${REPOSITORY_URI}@${IMAGE_DIGEST}"

Exclua a imagem do ECR por digest. imageDigest seleciona o conteúdo exato sem depender de uma tag:

aws ecr batch-delete-image \
  --repository-name ct-demo \
  --image-ids imageDigest="$IMAGE_DIGEST"

A resposta deve listar a imagem removida em imageIds com uma lista failures vazia. Exclua o repositório da aplicação, agora vazio:

aws ecr delete-repository --repository-name ct-demo

Confirme que o repositório de referência permanece:

aws ecr describe-repositories \
  --query 'repositories[].repositoryName'

Espere apenas ct-reference. Por fim, remova o login do registro salvo pelo Docker:

docker logout "$REGISTRY"

Em AWS View, acima, ct-demo e o contêiner devem desaparecer, enquanto o repositório de referência permanece. Um erro HTTP sozinho não provaria a limpeza: você também verificou o inventário e removeu o contêiner e a imagem reais.

Resumo

Você criou um repositório ECR imutável, criou e publicou uma imagem, comparou seu digest e executou exatamente aquela versão. Você testou HTTP e logs reais e removeu seu contêiner, sua imagem local e seu repositório, preservando o de outra aplicação. O próximo laboratório usa uma definição de tarefa ECS para selecionar e executar uma imagem.

Para aprofundar o tema, consulte a documentação da AWS: Autenticação do registro e envio de imagens; Evitar a substituição de tags de imagens.