Como desenvolver contêineres com Dockerfiles

1. Visão geral

O Docker é uma plataforma aberta para desenvolvimento, envio e execução de aplicativos. Com ele, você pode separar os aplicativos da sua infraestrutura e tratá-la como um aplicativo gerenciado. A plataforma agiliza o envio de códigos, os testes e as implantações, além de encurtar o ciclo entre a criação e a execução do código.

Para isso, o Docker combina recursos de conteinerização do kernel com fluxos de trabalho e ferramentas que ajudam no gerenciamento e na implantação dos seus aplicativos.

Os contêineres do Docker podem ser usados diretamente no Kubernetes, o que facilita a execução no Kubernetes Engine. Depois de aprender os conceitos básicos do Docker, você terá as habilidades necessárias para começar a desenvolver aplicativos conteinerizados e no Kubernetes.

Conteúdo deste laboratório

Você vai aprender a:

  • Criar um Dockerfile para um aplicativo de amostra
  • Criar uma imagem
  • Executar a imagem como um contêiner no local
  • Alterar o comportamento do contêiner
  • Envie a imagem para o Artifact Registry

Pré-requisitos

Este é um laboratório de nível introdutório. Ele não exige experiência com o Docker e contêineres. Conhecer o Cloud Shell e a linha de comando é recomendável, mas não obrigatório.

Configuração de ambiente personalizada

  1. Faça login no Console do Google Cloud e crie um novo projeto ou reutilize um existente. Crie uma conta do Gmail ou do Google Workspace, se ainda não tiver uma.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • O Nome do projeto é o nome de exibição para os participantes do projeto. Ele é uma string de caracteres que não é usada pelas APIs do Google e pode ser atualizada a qualquer momento.
  • O ID do projeto precisa ser exclusivo em todos os projetos do Google Cloud e não pode ser alterado após a definição. O Console do Cloud gera automaticamente uma string única, geralmente não importa o que seja. Na maioria dos codelabs, você precisará fazer referência ao ID do projeto, que geralmente é identificado como PROJECT_ID. Então, se você não gostar dele, gere outro ID aleatório ou crie um próprio e veja se ele está disponível. Em seguida, ele fica "congelado" depois que o projeto é criado.
  • Há um terceiro valor, um Número de projeto, que algumas APIs usam. Saiba mais sobre esses três valores na documentação.
  1. Em seguida, você precisará ativar o faturamento no Console do Cloud para usar os recursos/APIs do Cloud. A execução deste codelab não será muito cara, se tiver algum custo. Para encerrar os recursos e não gerar cobranças além deste tutorial, siga as instruções de "limpeza" encontradas no final do codelab. Novos usuários do Google Cloud estão qualificados para o programa de US$ 300 de avaliação sem custos.

2. Aplicativo de amostra

Um aplicativo de exemplo foi fornecido para facilitar este laboratório. Nesta seção, você vai recuperar o código-fonte e criar o aplicativo na forma nativa antes de seguir para o processo de conteinerização.

Código-fonte

O código-fonte deste laboratório está disponível no repositório GoogleCloudPlatform/container-developer-workshop com a documentação do aplicativo de amostra.

Configurar o Git

git config --global user.name ${USER}
git config --global user.email ${USER}@qwiklabs.net

Clonar o aplicativo de amostra Cloud Source Repository

gcloud source repos clone sample-app ${HOME}/sample-app &&
cd ${HOME}/sample-app &&
git checkout main

Saída

Cloning into '/home/student_03_49720296e995/sample-app'...
remote: Finding sources: 100% (16/16)
remote: Total 16 (delta 0), reused 16 (delta 0)
Receiving objects: 100% (16/16), 47.23 KiB | 681.00 KiB/s, done.
warning: remote HEAD refers to nonexistent ref, unable to checkout.

Project [qwiklabs-gcp-02-4327c4e03d82] repository [sample-app] was cloned to [/home/student_03_49720296e995/sample-app].
Branch 'main' set up to track remote branch 'main' from 'origin'.
Switched to a new branch 'main'

Criar o aplicativo de amostra

cd ${HOME}/sample-app
./mvnw compile

Saída

[INFO] Scanning for projects...
...
[INFO] Compiling 1 source file to /home/student_03_49720296e995/sample-app/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  10.080 s
[INFO] Finished at: 2022-02-23T17:14:30Z
[INFO] ------------------------------------------------------------------------

Executar o aplicativo de amostra

cd ${HOME}/sample-app
./mvnw exec:java

Saída

[INFO] Scanning for projects...
...
Listening at http://localhost:8080

Visualizar o aplicativo em execução

  • Clique no botão "Visualização da Web" do Cloud Shell.
  • Clique em Visualizar na porta 8080

Após a configuração

  • Pressione CTRL + C no Cloud Shell para interromper o aplicativo em execução.

3. Dockerfile

Como conteinerizar o aplicativo com um Dockerfile

Um método para empacotar um aplicativo em um contêiner é com o uso de um Dockerfile. O Dockerfile é semelhante a um script que instrui o daemon sobre como montar a imagem do contêiner. Consulte a documentação de referência do Dockerfile) para mais informações.

Crie um Dockerfile vazio no repositório do aplicativo de amostra.

touch ${HOME}/sample-app/Dockerfile

Abra o Dockerfile no editor de sua preferência.

vi ${HOME}/sample-app/Dockerfile

Escolha uma imagem inicial

Usar o método Dockerfile para criar um contêiner requer conhecimento direto sobre o aplicativo para montar o contêiner. A primeira etapa para criar um Dockerfile é selecionar uma imagem que será usada como base.Ela deve ser uma imagem principal ou de base mantida e publicada por uma fonte confiável, geralmente sua empresa.

A instrução FROM inicializa um novo estágio de build e define a imagem de base para os comandos sequenciais subsequentes. Assim, a instrução FROM geralmente é a primeira instrução em um Dockerfile e só pode ser precedida por uma instrução ARG opcional para oferecer suporte a variáveis.

Sintaxe: FROM <image>[:<tag> | @<digest>] [AS <name>]

O formato de uma imagem é <image>:<tag> ou <image>@<digest>. Se uma tag ou um resumo não for especificado, o padrão será a tag :latest. O formato de <image> varia de acordo com o registro usado para armazenar a imagem. Para o Artifact Registry, o formato <image> é <region>-docker.pkg.dev/<project ID>/<repository name>/<image name>:<image tag>.

Neste laboratório, usamos a imagem pública openjdk:11.0-jdk. Adicione a seguinte linha ao seu Dockerfile

FROM openjdk:11.0-jdk

Definir o diretório de trabalho

A instrução WORKDIR define o diretório de trabalho para todas as instruções sequenciais que seguem no Dockerfile. Para mais informações, consulte a seção WORKDIR da documentação de referência do Dockerfile.

Sintaxe: WORKDIR <path>

Neste laboratório, usamos o diretório /app como WORKDIR. Adicione a seguinte linha na parte inferior do Dockerfile

WORKDIR /app

Copie os arquivos do aplicativo

A instrução COPY copia diretórios ou arquivos do local <source> para o caminho <destination> do sistema de arquivos de imagens. Vários recursos <source> podem ser especificados e todos são relativos ao contexto do build. O contexto do build será discutido em mais detalhes na seção "Build". Para mais informações, consulte a seção "COPIAR" da documentação de referência do Dockerfile.

Sintaxe: COPY <source>... <destination>

Neste laboratório, copiaremos todos os arquivos do repositório para o sistema de arquivos de imagens. Adicione a seguinte linha à parte inferior do Dockerfile

COPY . /app

Compilar o aplicativo

A instrução RUN executa comandos em uma nova camada de imagem sobre a imagem atual e confirma os resultados. A imagem confirmada resultante será usada para etapas sequenciais no Dockerfile. Para mais informações, consulte a seção EXECUTAR da documentação de referência do Dockerfile.

Sintaxe: RUN <command>

Neste laboratório, vamos usar o Maven para compilar o aplicativo em um arquivo JAR. Na parte inferior do Dockerfile, adicione a seguinte linha:

RUN ./mvnw compile assembly:single

Inicie o aplicativo

A instrução CMD fornece o comando padrão para um contêiner em execução. Só pode haver uma instrução CMD em um Dockerfile. Se mais de um CMD for especificado, apenas o último CMD vai entrar em vigor. Há funcionalidades mais avançadas disponíveis que usam as instruções CMD e ENTRYPOINT, mas isso não será abordado neste laboratório. Para mais informações, consulte a seção CMD da documentação de referência do Dockerfile.

Sintaxe: CMD ["executable","param1","param2"]

Neste laboratório, executamos o arquivo JAR que compilamos. Adicione a seguinte linha na parte inferior do Dockerfile

CMD ["java","-jar","/app/target/sample-app-1.0.0-jar-with-dependencies.jar"]

Dockerfile final

O Dockerfile final será

FROM openjdk:11.0-jdk
WORKDIR /app
COPY . /app
RUN ./mvnw compile assembly:single
CMD ["java","-jar","/app/target/sample-app-1.0.0-jar-with-dependencies.jar"]

Fazer commit do Dockerfile localmente

cd ${HOME}/sample-app
git add Dockerfile
git commit -m "Added Dockerfile"

4. Criar

Agora, criaremos a imagem do Dockerfile usando o comando docker build. Esse comando instrui o daemon do Docker a criar a imagem usando as instruções do nosso Dockerfile. Consulte a documentação de referência de criação do Docker para mais informações.

Criar a imagem

cd ${HOME}/sample-app
export IMAGE_TAG=$(git rev-parse --short HEAD)
docker build --tag sample-app:${IMAGE_TAG} .

Saída

Sending build context to Docker daemon  221.2kB
Step 1/4 : FROM openjdk:11.0-jdk
11.0-jdk: Pulling from library/openjdk
0c6b8ff8c37e: Pull complete
412caad352a3: Pull complete
e6d3e61f7a50: Pull complete
461bb1d8c517: Pull complete
e442ee9d8dd9: Pull complete
542c9fe4a7ba: Pull complete
41de18d1833d: Pull complete
Digest: sha256:d72b1b9e94e07278649d91c635e34737ae8f181c191b771bde6816f9bb4bd08a
Status: Downloaded newer image for openjdk:11.0-jdk
---> 2924126f1829
Step 2/4 : WORKDIR /app
---> Running in ea037abb273d
Removing intermediate container ea037abb273d
---> bd9b6d078082
Step 3/4 : COPY . /app
---> b9aec2b5de51
Step 4/4 : RUN ./mvnw compile jar:jar
---> Running in 3f5ff737b7fd
[INFO] Scanning for projects...
...
[INFO] Building jar: /app/target/sample-app-1.0.0.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  22.952 s
[INFO] Finished at: 2022-02-23T18:09:08Z
[INFO] ------------------------------------------------------------------------
Removing intermediate container 331443caebd3
---> 152f65cc441e
Step 5/5 : CMD ["java", "-jar", "/app/target/sample-app-1.0.0.jar"]
---> Running in 3d595a72231c
Removing intermediate container 3d595a72231c
---> 0e40d7548cab
Successfully built 0e40d7548cab
Successfully tagged sample-app:aaa8895

5. Executar

Após a criação da imagem do contêiner, podemos executar o aplicativo e verificar se ele se comporta como esperado usando o comando "docker run". Esse comando iniciará o contêiner em primeiro plano no prompt de comando para teste ou depuração. Consulte a documentação de referência de execução do Docker para mais informações.

Executar um contêiner usando a imagem

cd ${HOME}/sample-app
export IMAGE_TAG=$(git rev-parse --short HEAD)
docker run \
  --rm \
  -p 8080:8080 \
  sample-app:${IMAGE_TAG}

Saída

Listening at http://localhost:8080

Visualizar o aplicativo em execução em um contêiner

  • Clique no botão "Visualização da Web" do Cloud Shell.
  • Clique em Visualizar na porta 8080
  • Pressione CTRL + C no Cloud Shell para interromper os contêineres

Como alterar o comportamento do contêiner

A execução do Docker Run usa a configuração padrão no Dockerfile. Instruções e parâmetros adicionais podem ser adicionados para modificar esse comportamento.

Ativar registro TRACE

cd ${HOME}/sample-app
export IMAGE_TAG=$(git rev-parse --short HEAD)
docker run \
  --rm \
  -p 8080:8080 \
  sample-app:${IMAGE_TAG} \
  java -Dorg.slf4j.simpleLogger.defaultLogLevel=trace -jar /app/target/sample-app-1.0.0-jar-with-dependencies.jar

Visualizar o aplicativo em execução em um contêiner

  • Clique no botão "Visualização da Web" do Cloud Shell.
  • Clique em Visualizar na porta 8080
  • Acesse a guia do Cloud Shell e verifique se a geração de registros
  • Pressione CTRL + C no Cloud Shell para interromper o contêiner.

Alterar porta

cd ${HOME}/sample-app
export IMAGE_TAG=$(git rev-parse --short HEAD)
docker run \
--rm \
-e PORT=8081 \
-p 8081:8081 \
sample-app:${IMAGE_TAG}

Visualizar o aplicativo em execução em um contêiner

  • Clique no botão "Visualização da Web" do Cloud Shell.
  • Clique em Alterar porta
  • Insira 8081
  • Clique em Alterar e visualizar
  • Pressione CTRL + C no Cloud Shell para interromper o contêiner.

6. Push

Quando tivermos certeza de que a imagem do contêiner está sendo executada corretamente e se quisermos disponibilizar esse contêiner para execução em outros ambientes e/ou por outros usuários, será necessário enviar a imagem para um repositório compartilhado. Isso deve acontecer como parte de um pipeline de build automatizado. No entanto, no ambiente de teste, já temos um repositório configurado e podemos enviar a imagem manualmente.

Envie a confirmação do Dockerfile para o repositório do app de amostra

cd ${HOME}/sample-app
export IMAGE_TAG=$(git rev-parse --short HEAD)
git push

Marcar a imagem do Artifact Registry

docker tag sample-app:${IMAGE_TAG} \
    us-central1-docker.pkg.dev/${GOOGLE_CLOUD_PROJECT}/apps/sample-app:${IMAGE_TAG}

Configure suas credenciais para o Artifact Registry

gcloud auth configure-docker us-central1-docker.pkg.dev

Quando solicitado, Do you want to continue (Y/n)?, responda y e pressione Enter.

Envie a imagem para o Artifact Registry

docker push us-central1-docker.pkg.dev/${GOOGLE_CLOUD_PROJECT}/apps/sample-app:${IMAGE_TAG}

Saída

 The push refers to repository [us-central1-docker.pkg.dev/qwiklabs-gcp-04-b47ced695a3c/apps/sample-app]
  453b97f86449: Pushed
  e86791aa0382: Pushed
  d404c7ee0850: Pushed
  fe4f44af763d: Pushed
  7c072cee6a29: Pushed
  1e5fdc3d671c: Pushed
  613ab28cf833: Pushed
  bed676ceab7a: Pushed
  6398d5cccd2c: Pushed
  0b0f2f2f5279: Pushed
  aaa8895: digest: sha256:459de00f86f159cc63f98687f7c9563fd65a2eb9bcc71c23dda3351baf13607a size: 2424

7. Parabéns!

Parabéns, você concluiu o codelab.

Conteúdo abordado

  • Criou um Dockerfile para um aplicativo de amostra
  • Criar uma imagem
  • executou a imagem como um contêiner localmente;
  • Comportamento do contêiner alterado
  • enviou a imagem para o Artifact Registry