1. Visão geral
Este laboratório demonstra recursos e funcionalidades projetados para simplificar o fluxo de trabalho de desenvolvimento de engenheiros de software encarregados de desenvolver aplicativos NodeJS em um ambiente conteinerizado. O desenvolvimento típico de contêineres exige que o usuário entenda os detalhes dos contêineres e do processo de build deles. Além disso, os desenvolvedores geralmente precisam interromper o fluxo de trabalho, saindo do ambiente de desenvolvimento integrado para testar e depurar os aplicativos em ambientes remotos. Com as ferramentas e tecnologias mencionadas neste tutorial, os desenvolvedores podem trabalhar de forma eficaz com aplicativos contêinerizados sem sair do ambiente de desenvolvimento integrado.
O que você vai aprender
Neste laboratório, você vai aprender métodos para desenvolver com contêineres no Google Cloud, incluindo:
- Como criar um aplicativo Node.js inicial
- Como configurar um aplicativo Node.js para desenvolvimento de contêineres
- Como programar um serviço REST CRUD simples
- Como implantar no GKE
- Depuração de um estado de erro
- Usar pontos de interrupção / registros
- Implantação dinâmica de mudanças de volta para o GKE
- Opcional: integrar o CloudSQL para persistência de back-end

2. Configuração e requisitos
Configuração de ambiente personalizada
- 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.



- O Nome do projeto é o nome de exibição para os participantes do projeto. É uma string de caracteres não usada pelas APIs do Google É possível atualizar o local a qualquer momento.
- O ID do projeto precisa ser exclusivo em todos os projetos do Google Cloud e não pode ser mudado após a definição. O console do Cloud gera automaticamente uma string exclusiva. Em geral, não importa o que seja. Na maioria dos codelabs, é necessário fazer referência ao ID do projeto, normalmente identificado como
PROJECT_ID. Se você não gostar do ID gerado, crie outro aleatório. Se preferir, teste o seu e confira se ele está disponível. Ele não pode ser mudado após essa etapa e permanece durante o projeto. - Para sua informação, há um terceiro valor, um Número do projeto, que algumas APIs usam. Saiba mais sobre esses três valores na documentação.
- Em seguida, ative 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 desligar os recursos e evitar cobranças além deste tutorial, exclua os recursos criados ou o projeto inteiro. Novos usuários do Google Cloud estão qualificados para o programa de US$ 300 de avaliação sem custos.
Iniciar o editor do Cloud Shell
Este laboratório foi projetado e testado para uso com o editor do Google Cloud Shell. Para acessar o editor,
- Acesse seu projeto do Google em https://console.cloud.google.com.
- No canto superior direito, clique no ícone do editor do Cloud Shell.

- Um novo painel será aberto na parte de baixo da janela
- Clique no botão "Abrir editor".

- O editor será aberto com um explorador à direita e o editor na área central.
- Um painel de terminal também vai estar disponível na parte de baixo da tela.
- Se o terminal NÃO estiver aberto, use a combinação de teclas "ctrl+`" para abrir uma nova janela do terminal.
Configurar a gcloud
No Cloud Shell, defina o ID do projeto e a região em que você quer implantar o aplicativo. Salve-as como variáveis PROJECT_ID e REGION.
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
Provisionar a infraestrutura usada neste laboratório
Neste laboratório, você vai implantar código no GKE e acessar dados armazenados em um banco de dados do Cloud SQL. O script de configuração abaixo prepara essa infraestrutura para você.
- Faça o download do script de configuração e torne-o executável.
wget https://raw.githubusercontent.com/GoogleCloudPlatform/container-developer-workshop/main/labs/nodejs/setup_with_cw.sh
chmod +x setup_with_cw.sh
- Abra o arquivo
setup_with_cw.she edite os valores das senhas que estão definidas como CHANGEME. - Execute o script de configuração para criar um cluster do GKE e um banco de dados do Cloud SQL que você vai usar neste laboratório.
./setup_with_cw.sh &
Cluster do Cloud Workstations
- Abra o Cloud Workstations no Console do Cloud. Aguarde até que o cluster esteja no status
READY.
Criar configuração de estações de trabalho
- Se a sessão do Cloud Shell foi desconectada, clique em "Reconectar" e execute o comando da CLI gcloud para definir o ID do projeto. Substitua o ID do projeto de exemplo abaixo pelo ID do seu projeto do Qwiklabs antes de executar o comando.
gcloud config set project qwiklabs-gcp-project-id
- Faça o download e execute o script abaixo no terminal para criar a configuração do Cloud Workstations.
wget https://raw.githubusercontent.com/GoogleCloudPlatform/container-developer-workshop/main/labs/nodejs/workstation_config_setup.sh
chmod +x workstation_config_setup.sh
./workstation_config_setup.sh
- Verifique os resultados na seção "Configurações". A transição para o status READY leva 2 minutos.

- Abra o Cloud Workstations no console e crie uma nova instância.

- Mude o nome para
my-workstatione selecione a configuração atual:codeoss-js.

- Verifique os resultados na seção "Estações de trabalho".

Iniciar estação de trabalho
- Inicie e abra a estação de trabalho. A inicialização da estação de trabalho leva alguns minutos.

- Para permitir cookies de terceiros, clique no ícone na barra de endereço.


- Clique em "Site indisponível?".

- Clique em "Permitir cookies".

- Quando a estação de trabalho for iniciada, o ambiente de desenvolvimento integrado do Code OSS vai aparecer. Clique em "Marcar como concluído" na página "Como começar" do ambiente de desenvolvimento integrado da estação de trabalho.

3. Como criar um novo aplicativo inicial do Node.js
Nesta seção, você vai criar um novo aplicativo Node.js.
- Abra um novo terminal.

- No Cloud Shell, crie um diretório chamado
mynodejsapp.
mkdir mynodejsapp
Clique no botão "Permitir" se essa mensagem aparecer para poder copiar e colar na estação de trabalho.

- Mude para esse diretório e abra-o como um espaço de trabalho. Isso vai recarregar o editor criando uma configuração de espaço de trabalho na pasta recém-criada.
cd mynodejsapp && code-oss-cloud-workstations -r --folder-uri="$PWD"
- Abra um novo terminal novamente. Instale o Node e o NPM usando o NVM.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash
# This loads nvm bash_completion
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
nvm install stable
nvm alias default stable
4. Criar um novo aplicativo inicial
- Inicializar o aplicativo
Crie um arquivo package.json executando o seguinte comando:
npm init
Choose the `entry point: (index.js) src/index.js` and leave default values for the rest of the parameters. This will create the `package.json` file with following contents
{
"name": "mynodejsapp",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
- Adicionar um ponto de entrada
Abra e edite o arquivo package.json no ambiente de desenvolvimento integrado para incluir o comando de início no script "start": "node src/index.js",. Depois da mudança, os scripts vão ficar parecidos com o snippet de código abaixo:
"scripts": {
"start": "node src/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
- Adicionar a dependência do Express
O código que vamos adicionar também usa express. Portanto, vamos adicionar essa dependência ao arquivo package.json. Depois de todas as mudanças, o arquivo package.json vai ficar assim:
{
"name": "mynodejsapp",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.3"
}
}
- Criar o arquivo index.js
Crie um diretório de origem chamado "src" selecionando "Nova pasta" na visualização do explorador.

Crie o arquivo src/index.js

com o código a seguir
const express = require('express');
const app = express();
const PORT = 8080;
app.get('/', (req, res) => {
var message="Greetings from Node";
res.send({ message: message });
});
app.listen(PORT, () => {
console.log(`Server running at: http://localhost:${PORT}/`);
});
Observe que a PORTA está definida como o valor 8080.
Gerar manifestos
O Skaffold oferece ferramentas integradas para simplificar o desenvolvimento de contêineres. Nesta etapa, você vai inicializar o Skaffold, que vai criar automaticamente arquivos YAML básicos do Kubernetes. Execute o comando abaixo para iniciar o processo.
Execute o comando a seguir no terminal:
skaffold init --generate-manifests
Quando solicitado:
- Insira 8080 para a porta
- Digite y para salvar a configuração.
Dois arquivos são adicionados à visualização do espaço de trabalho: skaffold.yaml e deployment.yaml.
Atualizar nome do app
Os valores padrão incluídos na configuração não correspondem ao nome do seu aplicativo. Atualize os arquivos para fazer referência ao nome do aplicativo em vez dos valores padrão.
- Mudar entradas na configuração do Skaffold
- Abrir
skaffold.yaml - Selecione o nome da imagem definido como
package-json-image. - Clique com o botão direito do mouse e escolha "Mudar todas as ocorrências".
- Digite o novo nome como
mynodejsapp
- Mudar entradas na configuração do Kubernetes
- Abrir arquivo
deployment.yaml - Selecione o nome da imagem definido como
package-json-image. - Clique com o botão direito do mouse e escolha "Mudar todas as ocorrências".
- Digite o novo nome como
mynodejsapp
No arquivo skaffold.yaml, a seção build usa buildpacks para colocar o aplicativo em contêineres. Esse código não tem Dockerfile, e o desenvolvedor não precisa de nenhum conhecimento sobre Docker para conteinerizar o aplicativo.
Além disso, a sincronização dinâmica é ativada automaticamente entre o editor e o contêiner em execução por essa configuração do Skaffold. Nenhuma configuração adicional é necessária para ativar a sincronização dinâmica.
5. Como percorrer o processo de desenvolvimento
Nesta seção, você vai seguir algumas etapas usando o plug-in Cloud Code para aprender os processos básicos e validar a configuração e a instalação do aplicativo inicial.
O Cloud Code se integra ao Skaffold para simplificar seu processo de desenvolvimento. Ao implantar no GKE nas etapas a seguir, o Cloud Code e o Skaffold vão criar automaticamente a imagem do contêiner, enviá-la para um Container Registry e implantar o aplicativo no GKE. Isso acontece nos bastidores, abstraindo os detalhes do fluxo do desenvolvedor. O Cloud Code também melhora seu processo de desenvolvimento ao oferecer recursos tradicionais de depuração e hotsync para desenvolvimento baseado em contêineres.
Faça login no Google Cloud
- Clique no ícone do Cloud Code e selecione "Fazer login no Google Cloud":

- Clique em "Prosseguir com login".

- Confira a saída no terminal e abra o link:

- Faça login com as credenciais de estudante do Qwiklabs.

- Selecione "Permitir":

- Copie o código de verificação e volte à guia "Estação de trabalho".

- Cole o código de verificação e pressione "Enter".

Adicionar cluster do Kubernetes
- Adicionar um cluster

- Selecione Google Kubernetes Engine:

- Selecione o projeto.

- Selecione "mycluster", que foi criado na configuração inicial.

- O cluster agora aparece na lista de clusters do Kubernetes em "Cloud Code". Navegue e explore o cluster aqui.

Definir o ID do projeto atual usando a CLI gcloud
- Copie o ID do projeto deste laboratório na página do Qwiklabs.

- No terminal, execute o comando da CLI gcloud para definir o ID do projeto. Substitua o ID do projeto de exemplo antes de executar o comando. SUBSTITUA o ID do projeto antes de executar o comando abaixo.
gcloud config set project qwiklabs-gcp-project-id
Implantar no Kubernetes
- No painel na parte de baixo do editor do Cloud Shell, selecione Cloud Code 

- No painel que aparece na parte de cima em "SESSÕES DE DESENVOLVIMENTO", selecione Executar no Kubernetes. Se solicitado, selecione "Sim" para usar o contexto atual do Kubernetes.

- Na primeira vez que você executar o comando, uma solicitação vai aparecer na parte de cima da tela perguntando se você quer o contexto atual do Kubernetes. Selecione "Sim" para aceitar e usar o contexto atual.

- Em seguida, uma solicitação vai aparecer perguntando qual registro de contêiner usar. Pressione "Enter" para aceitar o valor padrão fornecido.

- Selecione a guia "Saída" no painel inferior e Kubernetes: Run/Debug no menu suspenso para ver o progresso e as notificações.

- Selecione "Kubernetes: Run/Debug - Detailed" no menu suspenso do canal à direita para conferir mais detalhes e registros transmitidos ao vivo dos contêineres.

- Para voltar à visualização simplificada, selecione "Kubernetes: Run/Debug" no menu suspenso.
- Quando o build e os testes forem concluídos, a guia "Saída" vai mostrar:
Resource deployment/mynodejsapp status completed successfully, e um URL será listado: "URL encaminhado do app de demonstração do serviço: http://localhost:8080" - No terminal do Cloud Code, passe o cursor sobre o URL na saída (http://localhost:8080) e, na dica de ferramenta que aparece, selecione "Seguir link".
A resposta será:
{"message":"Greetings from Node"}
Recarga automática
- Navegue para
src/index.js. Edite o código da mensagem de saudação para'Hello from Node'
Na janela Output, na visualização Kubernetes: Run/Debug, o observador sincroniza os arquivos atualizados com o contêiner no Kubernetes.
Update initiated File sync started for 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a File sync succeeded for 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a Update succeeded
- Se você mudar para a visualização
Kubernetes: Run/Debug - Detailed, vai notar que ela reconhece as mudanças no arquivo e reinicia o nó.
files modified: [src/index.js] Copying files:map[src/index.js:[/workspace/src/index.js]]togcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a Syncing 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a Watching for changes... [mynodejsapp] [mynodejsapp]> mynodejsapp@1.0.0 start /workspace [mynodejsapp]> node src/index.js [mynodejsapp] [mynodejsapp]Server running at: http://localhost:8080/
- Atualize o navegador para ver os resultados atualizados.
Depuração
- Acesse a visualização de depuração e pare a linha de execução atual
. - Clique em
Cloud Codeno menu da parte de baixo e selecioneDebug on Kubernetespara executar o aplicativo no mododebug.

- Na visualização
Kubernetes Run/Debug - Detailedda janelaOutput, observe que o Skaffold vai implantar esse aplicativo no modo de depuração. - A criação e a implantação do aplicativo levam alguns minutos. Você vai notar um depurador anexado desta vez.
Port forwarding pod/mynodejsapp-6bbcf847cd-vqr6v in namespace default, remote port 9229 -> http://127.0.0.1:9229 [mynodejsapp]Debugger attached.
- A barra de status na parte de baixo muda de azul para laranja, indicando que está no modo de depuração.

- Na visualização
Kubernetes Run/Debug, observe que um contêiner depurável é iniciado.
**************URLs***************** Forwarded URL from service mynodejsapp-service: http://localhost:8080 Debuggable container started pod/mynodejsapp-deployment-6bc7598798-xl9kj:mynodejsapp (default) Update succeeded ***********************************
Usar pontos de interrupção
- Abra o
src/index.js - Localize a instrução que diz
var message="Hello from Node";. - Adicione um ponto de interrupção a essa linha clicando no espaço em branco à esquerda do número da linha. Um indicador vermelho vai aparecer para mostrar que o ponto de interrupção foi definido.
- Recarregue o navegador e observe que o depurador interrompe o processo no ponto de interrupção e permite investigar as variáveis e o estado do aplicativo que está sendo executado remotamente no GKE.
- Clique na seção de variáveis até encontrar a variável
"message". - Execute a linha pressionando "Step over"
. - Observe o valor atual da variável
"message"mudar para"Hello from Node". - Clique duas vezes no nome da variável "target" e, no pop-up, mude o valor para algo diferente, como
"Hi from Node". - Clique no botão "Continuar" no painel de controle de depuração.
- Revise a resposta no navegador, que agora mostra o valor atualizado que você acabou de inserir.
- Pare o modo "Debug" pressionando o botão de parada
e remova o ponto de interrupção clicando nele novamente.
6. Como desenvolver um serviço REST CRUD simples
Neste ponto, seu aplicativo está totalmente configurado para desenvolvimento em contêineres, e você já passou pelo fluxo de trabalho de desenvolvimento básico com o Cloud Code. Nas seções a seguir, você vai praticar o que aprendeu adicionando endpoints de serviço REST que se conectam a um banco de dados gerenciado no Google Cloud.
Configurar dependências
O código do aplicativo usa um banco de dados para manter os dados do serviço REST. Adicione o seguinte ao arquivo package.json para garantir que as dependências estejam disponíveis:
- Adicione mais duas dependências,
pgesequelize, ao arquivopackage.jsonpara criar um aplicativo CRUD do Postgres. Depois de publicar as alterações, a seção de dependências ficaria assim:
"dependencies": {
"express": "^4.17.3",
"pg": "^8.8.0",
"sequelize": "^6.25.7"
}
Codificar o serviço REST
- Adicione o código do aplicativo CRUD a ele.
wget -O app.zip https://github.com/GoogleCloudPlatform/container-developer-workshop/raw/main/labs/nodejs/app.zip
unzip app.zip
Esse código tem
- Pasta models com o modelo de entidade para
item - Pasta controllers com o código que faz operações CRUD
- Pasta routes que roteia padrões de URL específicos para diferentes chamadas
- Pasta config com detalhes de conectividade do banco de dados
- Observe que a configuração do banco de dados no arquivo
db.config.jsse refere às variáveis de ambiente que precisam ser fornecidas para se conectar ao banco de dados. Você também precisa analisar a solicitação recebida para codificação de URL. - Adicione o snippet de código a seguir em
src/index.jspara se conectar ao código CRUD do seu arquivo JavaScript principal logo antes da última seção que começa comapp.listen(PORT, () => {.
const bodyParser = require('body-parser')
app.use(bodyParser.json())
app.use(
bodyParser.urlencoded({
extended: true,
})
)
const db = require("../app/models");
db.sequelize.sync();
require("../app/routes/item.routes")(app);
- Edite a implantação no arquivo
deployment.yamlpara adicionar as variáveis de ambiente e fornecer as informações de conectividade do banco de dados.
Atualize a entrada de especificação no final do arquivo para corresponder à seguinte definição:
spec:
containers:
- name: mynodejsapp
image: mynodejsapp
env:
- name: DB_HOST
value: ${DB_INSTANCE_IP}
- name: DB_PORT
value: "5432"
- name: DB_USER
valueFrom:
secretKeyRef:
name: gke-cloud-sql-secrets
key: username
- name: DB_PASS
valueFrom:
secretKeyRef:
name: gke-cloud-sql-secrets
key: password
- name: DB_NAME
valueFrom:
secretKeyRef:
name: gke-cloud-sql-secrets
key: database
- Substitua o valor DB_HOST pelo endereço do seu banco de dados.
export DB_INSTANCE_IP=$(gcloud sql instances describe mytest-instance \
--format=json | jq \
--raw-output ".ipAddresses[].ipAddress")
envsubst < deployment.yaml > deployment.new && mv deployment.new deployment.yaml
Implantar e validar o aplicativo
- No painel na parte de baixo do editor do Cloud Shell, selecione
Cloud Codee depoisDebug on Kubernetesna parte de cima da tela. - Quando o build e os testes forem concluídos, a guia "Saída" vai mostrar:
Resource deployment/mynodejsapp status completed successfully, e um URL será listado: "URL encaminhado do serviço mynodejsapp: http://localhost:8080" - Adicione alguns itens.
No terminal do Cloud Shell, execute os comandos abaixo:
URL=localhost:8080
curl -X POST $URL/items -d '{"itemName":"Body Spray", "itemPrice":3.2}' -H "Content-Type: application/json"
curl -X POST $URL/items -d '{"itemName":"Nail Cutter", "itemPrice":2.5}' -H "Content-Type: application/json"
- Teste o GET executando $URL/items no navegador. Também é possível executar o curl na linha de comando
curl -X GET $URL/items
- Teste de exclusão: agora tente excluir um item executando o comando abaixo. Mude o valor de item-id, se necessário.
curl -X DELETE $URL/items/1
This throws an error message
{"message":"Could not delete Item with id=[object Object]"}
Identificar e corrigir o problema
- O aplicativo está sendo executado no modo de depuração. Use pontos de interrupção para encontrar o problema. Veja algumas dicas:
- Sabemos que há algo errado com o DELETE, já que ele não está retornando o resultado desejado. Portanto, você definiria o ponto de interrupção no método
itemcontroller.js->exports.delete. - Execute a execução passo a passo e observe as variáveis em cada passo para ver os valores das variáveis locais na janela à esquerda.
- Para observar valores específicos, como
request.params, adicione essa variável à janela "Watch".
- O valor atribuído a
idéundefined. Mude o código para corrigir o problema.
O snippet de código corrigido ficaria assim.
// Delete a Item with the specified id in the request
exports.delete = (req, res) => {
const id = req.params.id;
- Depois que o aplicativo for reiniciado, tente excluir de novo.
- Clique no quadrado vermelho na barra de ferramentas de depuração
para interromper a sessão.
7. Limpeza
Parabéns! Neste laboratório, você criou um novo aplicativo Node.js do zero e o configurou para funcionar no modo de implantação dinâmica com contêineres. Em seguida, você implantou e depurou o aplicativo em um cluster do GKE remoto seguindo o mesmo fluxo de desenvolvedor encontrado em stacks de aplicativos tradicionais.
Para fazer a limpeza depois de concluir o laboratório:
- Excluir os arquivos usados no laboratório
cd ~ && rm -rf mynodejsapp && rm -f setup.sh
- Exclua o projeto para remover toda a infraestrutura e os recursos relacionados.
