{"id":38804,"date":"2026-07-08T13:05:10","date_gmt":"2026-07-08T16:05:10","guid":{"rendered":"https:\/\/www.locaweb.com.br\/ajuda\/?post_type=ht_kb&#038;p=38804"},"modified":"2026-07-08T13:16:07","modified_gmt":"2026-07-08T16:16:07","slug":"como-fazer-deploy-de-uma-api-rest-express-fastify-com-docker-no-locaweb-cloud","status":"publish","type":"ht_kb","link":"https:\/\/www.locaweb.com.br\/ajuda\/wiki\/como-fazer-deploy-de-uma-api-rest-express-fastify-com-docker-no-locaweb-cloud\/","title":{"rendered":"Como fazer deploy de uma API REST (Express\/Fastify) com Docker no Locaweb Cloud"},"content":{"rendered":"<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">    \t\t<div class=\"hts-messages hts-messages--info  hts-messages--withtitle hts-messages--withicon \"   >\r\n    \t\t\t<span class=\"hts-messages__title\">Informa\u00e7\u00e3o!<\/span>    \t\t\t    \t\t\t\t<p>\r\n    \t\t\t\t\tAo final deste tutorial, voc\u00ea ser\u00e1 capaz de encapsular sua API REST em containers Docker e automatizar o deploy no Locaweb Cloud.    \t\t\t\t<\/p>\r\n    \t\t\t    \t\t\t\r\n    \t\t<\/div><!-- \/.ht-shortcodes-messages -->\r\n    \t\t<\/span><\/p>\n<p><span style=\"font-weight: 400;\">O uso de containers Docker no Locaweb Cloud profissionaliza sua infraestrutura, substituindo configura\u00e7\u00f5es manuais por imagens imut\u00e1veis que encapsulam toda a aplica\u00e7\u00e3o e depend\u00eancias.<\/span><\/p>\n<h2><b>1. Pr\u00e9-requisitos<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Antes de iniciar os comandos no terminal, certifique-se de que os seguintes requisitos est\u00e3o atendidos:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Conta Locaweb Cloud ativa com <\/span><a href=\"https:\/\/painel-cloud.locaweb.com.br\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">acesso ao painel<\/span><\/a><span style=\"font-weight: 400;\">.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">M\u00e1quina virtual (VM) Linux ativa (recomendado: Ubuntu 22.04 LTS).<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Chave SSH privada (.key ou .pem) salva localmente.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Reposit\u00f3rio Git com o c\u00f3digo-fonte da sua API REST versionado no GitHub.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">    \t\t<div class=\"hts-messages hts-messages--alert  hts-messages--withtitle hts-messages--withicon \"   >\r\n    \t\t\t<span class=\"hts-messages__title\">Importante!<\/span>    \t\t\t    \t\t\t\t<p>\r\n    \t\t\t\t\t <\/span>Est\u00e1 com d\u00favidas sobre como come\u00e7ar no Locaweb Cloud? Acesse nosso <a href=\"https:\/\/www.locaweb.com.br\/ajuda\/wiki\/por-onde-comecar-no-locaweb-cloud\/\" target=\"_blank\" rel=\"noopener\">tutorial de apoio<\/a>.    \t\t\t\t<\/p>\r\n    \t\t\t    \t\t\t\r\n    \t\t<\/div><!-- \/.ht-shortcodes-messages -->\r\n    \t\t<\/p>\n<p>&nbsp;<\/p>\n<h2><b>2. Configura\u00e7\u00e3o de infraestrutura <\/b><b>(painel CloudStack)<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Antes de rodar qualquer comando no terminal, \u00e9 necess\u00e1rio preparar a rede para que sua VM seja alcan\u00e7\u00e1vel pela internet e, ao mesmo tempo, manter o banco de dados isolado. Fa\u00e7a login no seu painel administrativo e siga os passos:<\/span><\/p>\n<h3><b>Passo 1: Obter o IP P\u00fablico<\/b><\/h3>\n<ol>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">No menu lateral, acesse <\/span><b>Rede<\/b><span style=\"font-weight: 400;\"> &gt; <\/span><b>Endere\u00e7os IP P\u00fablicos<\/b><span style=\"font-weight: 400;\">.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Localize o IP p\u00fablico associado \u00e0 sua rede. Anote esse endere\u00e7o; ele ser\u00e1 o seu <\/span><span style=\"font-weight: 400;\">&lt;SEU_IP_PUBLICO&gt;<\/span><span style=\"font-weight: 400;\">.<\/span><\/li>\n<\/ol>\n<h3><b>Passo 2: Configurar o Encaminhamento de Portas (Port Forwarding)<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">O encaminhamento de portas direciona o tr\u00e1fego externo para o IP interno da sua VM. Acesse a aba <\/span><b>Encaminhamento de Portas (Port Forwarding)<\/b><span style=\"font-weight: 400;\"> e crie as seguintes regras:<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td><b>Regra<\/b><\/td>\n<td><b>Porta P\u00fablica<\/b><\/td>\n<td><b>Porta Privada<\/b><\/td>\n<td><b>Protocolo<\/b><\/td>\n<td><b>VM de Destino<\/b><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">SSH<\/span><\/td>\n<td><span style=\"font-weight: 400;\">22 \/ 22<\/span><\/td>\n<td><span style=\"font-weight: 400;\">22 \/ 22<\/span><\/td>\n<td><span style=\"font-weight: 400;\">TCP<\/span><\/td>\n<td><span style=\"font-weight: 400;\">sua-vm<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">HTTP<\/span><\/td>\n<td><span style=\"font-weight: 400;\">80 \/ 80<\/span><\/td>\n<td><span style=\"font-weight: 400;\">80 \/ 80<\/span><\/td>\n<td><span style=\"font-weight: 400;\">TCP<\/span><\/td>\n<td><span style=\"font-weight: 400;\">sua-vm<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">API (Opcional)<\/span><\/td>\n<td><span style=\"font-weight: 400;\">3000 \/ 3000<\/span><\/td>\n<td><span style=\"font-weight: 400;\">3000 \/ 3000<\/span><\/td>\n<td><span style=\"font-weight: 400;\">TCP<\/span><\/td>\n<td><span style=\"font-weight: 400;\">sua-vm<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">    \t\t<div class=\"hts-messages hts-messages--alert  hts-messages--withtitle hts-messages--withicon \"   >\r\n    \t\t\t<span class=\"hts-messages__title\">Aviso!<\/span>    \t\t\t    \t\t\t\t<p>\r\n    \t\t\t\t\t N\u00c3O crie nenhuma regra de encaminhamento para a porta do banco de dados (PostgreSQL 5432 ou MongoDB 27017). O banco deve permanecer acess\u00edvel apenas dentro da pr\u00f3pria VM. Expor essas portas \u00e0 internet \u00e9 uma falha grave de seguran\u00e7a.    \t\t\t\t<\/p>\r\n    \t\t\t    \t\t\t\r\n    \t\t<\/div><!-- \/.ht-shortcodes-messages -->\r\n    \t\t<\/span><\/p>\n<h3><b>Passo 3: Liberar as portas no Firewall<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">Na tela do IP p\u00fablico, abra a aba <\/span><b>Firewall<\/b><span style=\"font-weight: 400;\"> e crie as regras de entrada correspondentes:<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td><b>Origem (CIDR)<\/b><\/td>\n<td><b>Porta (Inicial\/Final)<\/b><\/td>\n<td><b>Protocolo<\/b><\/td>\n<td><b>Observa\u00e7\u00e3o<\/b><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">&lt;SEU_IP_DE_ADMIN&gt;<\/span><span style=\"font-weight: 400;\">\/32<\/span><\/td>\n<td><span style=\"font-weight: 400;\">22 \/ 22<\/span><\/td>\n<td><span style=\"font-weight: 400;\">TCP<\/span><\/td>\n<td><span style=\"font-weight: 400;\">SSH restrito ao seu IP de administra\u00e7\u00e3o<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">0.0.0.0\/0<\/span><\/td>\n<td><span style=\"font-weight: 400;\">80 \/ 80<\/span><\/td>\n<td><span style=\"font-weight: 400;\">TCP<\/span><\/td>\n<td><span style=\"font-weight: 400;\">HTTP p\u00fablico<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">0.0.0.0\/0<\/span><\/td>\n<td><span style=\"font-weight: 400;\">3000 \/ 3000<\/span><\/td>\n<td><span style=\"font-weight: 400;\">TCP<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Liberado apenas se utilizou a regra opcional<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">     \t\t<div class=\"hts-messages hts-messages--alert  hts-messages--withtitle hts-messages--withicon \"   >\r\n    \t\t\t<span class=\"hts-messages__title\">Importante!<\/span>    \t\t\t    \t\t\t\t<p>\r\n    \t\t\t\t\t<\/span><span style=\"font-weight: 400;\">Por seguran\u00e7a, restrinja o acesso SSH ao seu pr\u00f3prio CIDR de administra\u00e7\u00e3o em vez de liberar para toda a internet (0.0.0.0\/0). Isso neutraliza ataques por for\u00e7a bruta na porta 22.<\/span><span style=\"font-weight: 400;\">    \t\t\t\t<\/p>\r\n    \t\t\t    \t\t\t\r\n    \t\t<\/div><!-- \/.ht-shortcodes-messages -->\r\n    \t\t<\/span><\/p>\n<h2><b>3. Configura\u00e7\u00e3o do sistema: instala\u00e7\u00e3o do Docker na VM<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Acesse sua m\u00e1quina virtual pelo terminal local para instalar o Docker Engine e o utilit\u00e1rio Docker Compose.<\/span><\/p>\n<h3><b>Passo 1: Acessar a M\u00e1quina Virtual via SSH<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">Bash<br \/>\n<\/span><\/p>\n<pre><span style=\"font-weight: 400;\"># Define a permiss\u00e3o restrita na chave privada por seguran\u00e7a<\/span>\r\n\r\n<span style=\"font-weight: 400;\">chmod 400 ~\/Downloads\/sua-chave-locaweb.key\r\n\r\n<\/span><span style=\"font-weight: 400;\"># Estabelece a conex\u00e3o remota com a VM Linux\r\n<\/span><span style=\"font-weight: 400;\">ssh -i ~\/Downloads\/sua-chave-locaweb.key ubuntu@&lt;SEU_IP_PUBLICO&gt;<\/span><\/pre>\n<h3><b>Passo 2: Instalar o Docker Engine<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">Bash<br \/>\n<\/span><\/p>\n<pre><span style=\"font-weight: 400;\"># Atualiza os \u00edndices do sistema e instala depend\u00eancias HTTPS<\/span>\r\n\r\n<span style=\"font-weight: 400;\">sudo apt-get update<\/span>\r\n\r\n<span style=\"font-weight: 400;\">sudo apt-get install -y ca-certificates curl gnupg<\/span>\r\n\r\n\r\n\r\n<span style=\"font-weight: 400;\"># Adiciona a chave oficial de GPG do Docker<\/span>\r\n\r\n<span style=\"font-weight: 400;\">sudo install -m 0755 -d \/etc\/apt\/keyrings<\/span>\r\n\r\n<span style=\"font-weight: 400;\">curl -fsSL https:\/\/download.docker.com\/linux\/ubuntu\/gpg | \r\nsudo gpg --dearmor -o \/etc\/apt\/keyrings\/docker.gpg<\/span>\r\n\r\n<span style=\"font-weight: 400;\">sudo chmod a+r \/etc\/apt\/keyrings\/docker.gpg<\/span>\r\n\r\n\r\n\r\n<span style=\"font-weight: 400;\"># Configura o reposit\u00f3rio est\u00e1vel oficial do Docker<\/span>\r\n\r\n<span style=\"font-weight: 400;\">echo \\<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\"deb [arch=$(dpkg --print-architecture) signed-by=\/etc\/apt\r\n\/keyrings\/docker.gpg] https:\/\/download.docker.com\/linux\/ubuntu \\<\/span>\r\n\r\n<span style=\"font-weight: 400;\"> \u00a0$(. \/etc\/os-release &amp;&amp; echo \"$VERSION_CODENAME\") stable\" |\r\n<\/span> \\ <span style=\"font-weight: 400;\">sudo tee \/etc\/apt\/sources.list.d\/docker.list &gt; \/dev\/null<\/span>\r\n\r\n\r\n\r\n<span style=\"font-weight: 400;\"># Instala o motor do Docker e o plugin do Docker Compose<\/span>\r\n\r\n<span style=\"font-weight: 400;\">sudo apt-get update<\/span>\r\n\r\n<span style=\"font-weight: 400;\">sudo apt-get install -y docker-ce docker-ce-cli containerd.io \r\ndocker-buildx-plugin docker-compose-plugin<\/span>\r\n\r\n\r\n\r\n<span style=\"font-weight: 400;\"># Habilita o servi\u00e7o para inicializar junto com o servidor<\/span>\r\n\r\n<span style=\"font-weight: 400;\">sudo systemctl enable --now docker<\/span><\/pre>\n<h3><b>Passo 3: Configurar permiss\u00f5es do grupo<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">Bash<br \/>\n<\/span><\/p>\n<pre><span style=\"font-weight: 400;\"># Adiciona o usu\u00e1rio ao grupo docker para n\u00e3o depender do \r\ncomando 'sudo'<\/span>\r\n\r\n<span style=\"font-weight: 400;\">sudo usermod -aG docker ubuntu<\/span><\/pre>\n<p>&nbsp;<\/p>\n<p><i><span style=\"font-weight: 400;\">Nota: Encerre a sess\u00e3o SSH e reconecte-se para aplicar as permiss\u00f5es do grupo.<\/span><\/i><\/p>\n<h2><b>4. Configura\u00e7\u00e3o do banco de dados: PostgreSQL em Container<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Os dados da nossa API ser\u00e3o armazenados em uma inst\u00e2ncia de PostgreSQL, que operar\u00e1 de forma isolada dentro de um container. A defini\u00e7\u00e3o deste servi\u00e7o ocorrer\u00e1 integralmente dentro do arquivo <\/span><span style=\"font-weight: 400;\">docker-compose.yml<\/span><span style=\"font-weight: 400;\">, mantendo a porta 5432 protegida de acessos externos. A aplica\u00e7\u00e3o o alcan\u00e7ar\u00e1 internamente pelo hostname <\/span><span style=\"font-weight: 400;\">db<\/span><span style=\"font-weight: 400;\">:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Plaintext<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">DATABASE_URL=postgresql:\/\/api_user:&lt;SENHA_SEGURA_DO_BANCO&gt;@db:5432\/\r\napi_producao<\/span><\/pre>\n<h2><b>5. Prepara\u00e7\u00e3o da aplica\u00e7\u00e3o\u00a0<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Na raiz do seu projeto local, crie os arquivos de automa\u00e7\u00e3o do deploy:<\/span><\/p>\n<p><b>Dockerfile<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Dockerfile<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">FROM node:20-alpine<\/span>\r\n\r\n<span style=\"font-weight: 400;\">WORKDIR \/usr\/src\/app<\/span>\r\n\r\n<span style=\"font-weight: 400;\">COPY package*.json .\/<\/span>\r\n\r\n<span style=\"font-weight: 400;\">RUN npm ci --omit=dev<\/span>\r\n\r\n<span style=\"font-weight: 400;\">COPY . .<\/span>\r\n\r\n<span style=\"font-weight: 400;\">EXPOSE 3000<\/span>\r\n\r\n<span style=\"font-weight: 400;\">CMD [\"node\", \"app.js\"]<\/span><\/pre>\n<p><b>\u00a0 .dockerignore<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Plaintext<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">node_modules<\/span>\r\n\r\n<span style=\"font-weight: 400;\">npm-debug.log<\/span>\r\n\r\n<span style=\"font-weight: 400;\">.git<\/span>\r\n\r\n<span style=\"font-weight: 400;\">.github<\/span>\r\n\r\n<span style=\"font-weight: 400;\">.env<\/span><\/pre>\n<p><b>docker-compose.yml<\/b><\/p>\n<p><span style=\"font-weight: 400;\">YAML<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">services:<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0api:<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0build: .<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0container_name: api-producao<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0restart: always<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0ports:<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- \"3000:3000\"<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0env_file:<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- .env<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0depends_on:<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- db<\/span>\r\n\r\n\r\n\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0db:<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0image: postgres:16-alpine<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0container_name: postgres-producao<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0restart: always<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0environment:<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0POSTGRES_USER: api_user<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0POSTGRES_DB: api_producao<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0volumes:<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- pgdata:\/var\/lib\/postgresql\/data<\/span>\r\n\r\n\r\n\r\n\r\n<span style=\"font-weight: 400;\">volumes:<\/span>\r\n\r\n<span style=\"font-weight: 400;\"> \u00a0pgdata:<\/span><\/pre>\n<h2><b>6. Deploy da Aplica\u00e7\u00e3o<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Escolha o m\u00e9todo ideal para o seu momento de mercado:<\/span><\/p>\n<h3><b>M\u00e9todo 1: Deploy manual via Git (primeira valida\u00e7\u00e3o)<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">Bash<\/span><\/p>\n<pre><span style=\"font-weight: 400;\"># Cria o diret\u00f3rio de aplica\u00e7\u00f5es e clona seu reposit\u00f3rio Git<\/span>\r\n\r\n<span style=\"font-weight: 400;\">sudo mkdir -p \/var\/www &amp;&amp; sudo chown ubuntu:ubuntu \/var\/www<\/span>\r\n\r\n<span style=\"font-weight: 400;\">cd \/var\/www<\/span>\r\n\r\n<span style=\"font-weight: 400;\">git clone https:\/\/github.com\/seu-usuario\/sua-api-rest.git<\/span>\r\n\r\n<span style=\"font-weight: 400;\">cd sua-api-rest<\/span>\r\n\r\n\r\n\r\n\r\n<span style=\"font-weight: 400;\"># Configura as vari\u00e1veis de ambiente de produ\u00e7\u00e3o<\/span>\r\n\r\n<span style=\"font-weight: 400;\">nano .env<\/span><\/pre>\n<p><i><span style=\"font-weight: 400;\">Adicione suas vari\u00e1veis de ambiente no arquivo <\/span><\/i><i><span style=\"font-weight: 400;\">.env<\/span><\/i><i><span style=\"font-weight: 400;\"> mapeando a senha e a URL de conex\u00e3o do banco interna.<\/span><\/i><\/p>\n<p><span style=\"font-weight: 400;\">Bash<\/span><\/p>\n<pre><span style=\"font-weight: 400;\"># Inicializa a stack de servi\u00e7os em segundo plano<\/span>\r\n\r\n<span style=\"font-weight: 400;\">docker compose up -d --build<\/span><\/pre>\n<h3><b>M\u00e9todo 2: Deploy automatizado com GitHub Actions (recomendado)<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">Adicione os Secrets no seu reposit\u00f3rio do GitHub (<\/span><span style=\"font-weight: 400;\">SSH_HOST<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">SSH_USERNAME<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">SSH_KEY<\/span><span style=\"font-weight: 400;\">) e crie o arquivo <\/span><span style=\"font-weight: 400;\">.github\/workflows\/deploy-docker.yml<\/span><span style=\"font-weight: 400;\">:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">YAML<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">name: Deploy Docker Locaweb Cloud<\/span>\r\n\r\n\r\n<span style=\"font-weight: 400;\">on:<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0push:<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0branches:<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- main<\/span>\r\n\r\n\r\n\r\n<span style=\"font-weight: 400;\">jobs:<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0deploy:<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0runs-on: ubuntu-latest<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0steps:<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- name: Checkout do C\u00f3digo<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0uses: actions\/checkout@v4<\/span>\r\n\r\n\r\n\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- name: Deploy via SSH no Locaweb Cloud<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0uses: appleboy\/ssh-action@v1.0.3<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0with:<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0host: ${{ secrets.SSH_HOST }}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0username: ${{ secrets.SSH_USERNAME }}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0key: ${{ secrets.SSH_KEY }}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0port: 22<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0script: |<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cd \/var\/www\/sua-api-rest<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0git reset --hard HEAD<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0git pull origin main<\/span>\r\n\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0docker compose up -d --build<\/span><\/pre>\n<h2><b>7. Valida\u00e7\u00e3o\u00a0<\/b><\/h2>\n<h3><b>Valida\u00e7\u00e3o interna (na VM)<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">Bash<\/span><\/p>\n<pre><span style=\"font-weight: 400;\"># Confirma se os containers est\u00e3o com status 'Up'<\/span>\r\n\r\n<span style=\"font-weight: 400;\">docker compose ps<\/span>\r\n\r\n\r\n<span style=\"font-weight: 400;\"># Verifica os logs em tempo real da API<\/span>\r\n\r\n<span style=\"font-weight: 400;\">docker compose logs -f api<\/span><\/pre>\n<h3><b>Valida\u00e7\u00e3o externa (m\u00e1quina local)<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">Bash<\/span><\/p>\n<pre><span style=\"font-weight: 400;\"># Testa a resposta p\u00fablica da API atrav\u00e9s do IP p\u00fablico<\/span>\r\n\r\n<span style=\"font-weight: 400;\">curl -I http:\/\/&lt;SEU_IP_PUBLICO&gt;:3000<\/span><\/pre>\n<p><i><span style=\"font-weight: 400;\"><br \/>\nO retorno esperado \u00e9 o cabe\u00e7alho HTTP 200 OK. Caso ocorra timeout, valide as regras de Firewall e Port Forwarding no painel CloudStack.<\/span><\/i><\/p>\n<h3><b>Valida\u00e7\u00e3o de isolamento do banco<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">Bash<\/span><\/p>\n<pre><span style=\"font-weight: 400;\"># Garante que a porta 5432 do banco est\u00e1 blindada contra a internet<\/span>\r\n\r\n<span style=\"font-weight: 400;\">curl -v telnet:\/\/&lt;SEU_IP_PUBLICO&gt;:5432<\/span><\/pre>\n<p><i><span style=\"font-weight: 400;\"><br \/>\nO comportamento correto e seguro para esse teste \u00e9 apresentar uma FALHA de conex\u00e3o, comprovando o isolamento do banco de dados.<\/span><\/i><\/p>\n<h2><b>8. Solu\u00e7\u00e3o de problemas (Troubleshooting)<\/b><\/h2>\n<p>&nbsp;<\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Permiss\u00e3o SSH Negada (<\/b><b>Permission denied<\/b><b>):<\/b><span style=\"font-weight: 400;\"> Garanta que executou o comando <\/span><span style=\"font-weight: 400;\">chmod 400<\/span><span style=\"font-weight: 400;\"> na sua chave privada local antes de se conectar.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Container com status <\/b><b>Exited<\/b><b>:<\/b><span style=\"font-weight: 400;\"> Rode <\/span><span style=\"font-weight: 400;\">docker compose logs api<\/span><span style=\"font-weight: 400;\"> para inspecionar os erros de inicializa\u00e7\u00e3o do Node.js. Certifique-se de que a string <\/span><span style=\"font-weight: 400;\">DATABASE_URL<\/span><span style=\"font-weight: 400;\"> aponta para <\/span><span style=\"font-weight: 400;\">db<\/span><span style=\"font-weight: 400;\"> e n\u00e3o para <\/span><span style=\"font-weight: 400;\">localhost<\/span><span style=\"font-weight: 400;\">.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Erro <\/b><b>docker: permission denied<\/b><b>:<\/b><span style=\"font-weight: 400;\"> Significa que o usu\u00e1rio ainda n\u00e3o foi sincronizado com o grupo. Encerre sua sess\u00e3o SSH atual e reconecte-se para atualizar as diretrizes.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">    \t\t<div class=\"hts-messages hts-messages--info  hts-messages--withtitle hts-messages--withicon \"   >\r\n    \t\t\t<span class=\"hts-messages__title\">Pronto!<\/span>    \t\t\t    \t\t\t\t<p>\r\n    \t\t\t\t\t<\/span><span style=\"font-weight: 400;\">Sua API REST com Docker foi publicada com sucesso no Locaweb Cloud. Sua infraestrutura est\u00e1 invis\u00edvel, est\u00e1vel e pronta para escalar sua opera\u00e7\u00e3o sem travar.<\/span><span style=\"font-weight: 400;\">    \t\t\t\t<\/p>\r\n    \t\t\t    \t\t\t\r\n    \t\t<\/div><!-- \/.ht-shortcodes-messages -->\r\n    \t\t<\/span><br \/>\n<b><br \/>\nPr\u00f3ximos Passos recomendados para produ\u00e7\u00e3o:<\/b><\/p>\n<ol>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Habilitar HTTPS com Let\u2019s Encrypt:<\/b><span style=\"font-weight: 400;\"> Configure um proxy reverso Nginx na m\u00e1quina virtual para criptografar as requisi\u00e7\u00f5es web. Lembre-se de liberar a porta 443 nas regras de Firewall do painel.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Backups automatizados:<\/b><span style=\"font-weight: 400;\"> Crie rotinas peri\u00f3dicas de <\/span><span style=\"font-weight: 400;\">pg_dump<\/span><span style=\"font-weight: 400;\"> para salvaguardar o banco de dados.<\/span><\/li>\n<\/ol>\n    \t\t<div class=\"hts-messages hts-messages--info  hts-messages--withtitle hts-messages--withicon \"   >\r\n    \t\t\t<span class=\"hts-messages__title\">Conhe\u00e7a!<\/span>    \t\t\t    \t\t\t\t<p>\r\n    \t\t\t\t\t<span style=\"font-weight: 400;\">Quer proteger a identidade da sua marca e profissionalizar o contato com seus clientes? Conhe\u00e7a os planos de <\/span><a href=\"https:\/\/www.locaweb.com.br\/email-profissional\/\" target=\"_blank\" rel=\"noopener\"><b>Email Profissional<\/b><\/a><span style=\"font-weight: 400;\"> e <\/span><a href=\"https:\/\/www.locaweb.com.br\/registro-de-dominio-web\/\" target=\"_blank\" rel=\"noopener\"><b>Registro de Dom\u00ednio<\/b><\/a><span style=\"font-weight: 400;\"> da Locaweb e centralize sua presen\u00e7a digital no mesmo ecossistema com o melhor custo-benef\u00edcio.<\/span>    \t\t\t\t<\/p>\r\n    \t\t\t    \t\t\t\r\n    \t\t<\/div><!-- \/.ht-shortcodes-messages -->\r\n    \t\t\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; O uso de containers Docker no Locaweb Cloud profissionaliza sua infraestrutura, substituindo configura\u00e7\u00f5es manuais por imagens imut\u00e1veis que encapsulam toda a aplica\u00e7\u00e3o e depend\u00eancias. 1. Pr\u00e9-requisitos Antes de iniciar os comandos no terminal, certifique-se de que os seguintes requisitos est\u00e3o atendidos: Conta Locaweb Cloud ativa com acesso ao painel&#8230;.<\/p>\n","protected":false},"author":55,"comment_status":"closed","ping_status":"closed","template":"","format":"standard","meta":{"footnotes":""},"ht-kb-category":[666],"ht-kb-tag":[],"class_list":["post-38804","ht_kb","type-ht_kb","status-publish","format-standard","hentry","ht_kb_category-locaweb-cloud"],"_links":{"self":[{"href":"https:\/\/www.locaweb.com.br\/ajuda\/wp-json\/wp\/v2\/ht-kb\/38804","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.locaweb.com.br\/ajuda\/wp-json\/wp\/v2\/ht-kb"}],"about":[{"href":"https:\/\/www.locaweb.com.br\/ajuda\/wp-json\/wp\/v2\/types\/ht_kb"}],"author":[{"embeddable":true,"href":"https:\/\/www.locaweb.com.br\/ajuda\/wp-json\/wp\/v2\/users\/55"}],"replies":[{"embeddable":true,"href":"https:\/\/www.locaweb.com.br\/ajuda\/wp-json\/wp\/v2\/comments?post=38804"}],"version-history":[{"count":5,"href":"https:\/\/www.locaweb.com.br\/ajuda\/wp-json\/wp\/v2\/ht-kb\/38804\/revisions"}],"predecessor-version":[{"id":38810,"href":"https:\/\/www.locaweb.com.br\/ajuda\/wp-json\/wp\/v2\/ht-kb\/38804\/revisions\/38810"}],"wp:attachment":[{"href":"https:\/\/www.locaweb.com.br\/ajuda\/wp-json\/wp\/v2\/media?parent=38804"}],"wp:term":[{"taxonomy":"ht_kb_category","embeddable":true,"href":"https:\/\/www.locaweb.com.br\/ajuda\/wp-json\/wp\/v2\/ht-kb-category?post=38804"},{"taxonomy":"ht_kb_tag","embeddable":true,"href":"https:\/\/www.locaweb.com.br\/ajuda\/wp-json\/wp\/v2\/ht-kb-tag?post=38804"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}