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, é possível separar os aplicativos da sua infraestrutura e tratá-la como um aplicativo gerenciado. Essa 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 deles 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

Neste laboratório, você vai aprender a:

  • Criar um Dockerfile para um aplicativo de amostra
  • Criar uma imagem
  • Executar a imagem como um contêiner localmente
  • Mudar 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.pnga99b7ace416376c4.pngbd84a6d3004737c5.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 amostra 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 passar para o processo de contêinerização.

Código-fonte

O código-fonte deste laboratório está disponível no repositório GoogleCloudPlatform/container-developer-workshop (em inglês), junto com a documentação do aplicativo de exemplo.

Configurar o Git

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

Clonar o Cloud Source Repository do aplicativo de exemplo

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 exemplo

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 colocar o aplicativo em contêiner com um Dockerfile

Um método de empacotar um aplicativo em um contêiner é usar 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 exemplo.

touch ${HOME}/sample-app/Dockerfile

Abra o Dockerfile no editor de sua preferência.

vi ${HOME}/sample-app/Dockerfile

Escolher uma imagem inicial

Usar o método Dockerfile para criar um contêiner exige 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.Essa imagem precisa ser uma imagem principal ou de base mantida e publicada por uma fonte confiável, geralmente sua empresa.

A instrução FROM inicializa uma nova etapa de build e define a imagem de base para comandos sequenciais subsequentes. Assim, a instrução FROM geralmente é a primeira 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>.

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

FROM openjdk:11.0-jdk

Definir o diretório de trabalho

A instrução WORKDIR define o diretório de trabalho para quaisquer instruções sequenciais que sigam 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 nosso WORKDIR. Adicione a seguinte linha à parte de baixo do Dockerfile:

WORKDIR /app

Copiar os arquivos do aplicativo

A instrução COPY copia diretórios ou arquivos do local <source> para o caminho <destination> do sistema de arquivos da imagem. É possível especificar vários recursos <source>, e todos eles são relativos ao contexto de build. O contexto de build será abordado mais adiante na seção "Build". Para mais informações, consulte a seção COPY da documentação de referência do Dockerfile.

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

Para este laboratório, vamos copiar todos os arquivos do repositório para o sistema de arquivos da imagem. Adicione a seguinte linha à parte de baixo 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 RUN 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. Adicione a seguinte linha à parte de baixo do Dockerfile:

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 uma for especificada, apenas a última vai entrar em vigor. Há funcionalidades mais avançadas disponíveis usando as instruções CMD e ENTRYPOINT, mas elas não são abordadas 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"]

Para este laboratório, vamos executar o arquivo JAR que compilamos. Adicione a seguinte linha à parte de baixo 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 vamos criar 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 do docker build 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

Depois de criar a imagem do contêiner, podemos executar o aplicativo e garantir que ele se comporte como esperado usando o comando "docker run". Esse comando vai iniciar nosso contêiner em primeiro plano no prompt de comando para teste ou depuração. Consulte a documentação de referência do docker run 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 mudar o comportamento do contêiner

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

Ativar o 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".
  • Mude para a guia do Cloud Shell e confira o registro adicional.
  • 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 quisermos disponibilizar esse contêiner para execução em outros ambientes e/ou por outros usuários, precisaremos enviar a imagem para um repositório compartilhado. Isso deve acontecer como parte de um pipeline de build automatizado, mas no nosso ambiente de teste já temos um repositório configurado e podemos enviar a imagem manualmente.

Envie o commit do Dockerfile para o repositório sample-app.

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

Marcar a imagem para o Artifact Registry

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

Configurar 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
  • Mudança no comportamento do contêiner
  • Enviou a imagem para o Artifact Registry