# Como hospedar um site estático no Back4app Containers com Docker e nginx

Você tem um site e nenhum lugar para colocá-lo. Envolva-o em um container, aponte um host para o repositório e ele está online — sem servidor para alugar, atualizar ou manter rodando.

URL: https://www.back4app.com/blog/pt/como-hospedar-um-site-estatico-com-docker-e-nginx
Publicado: 2026-10-23 · Testado: 2026-09-23
Testado em: Local: Docker 29.4.3, macOS, arm64 · Imagens: ubuntu:latest (26.04.1), nginx:1.27-alpine · Plataforma: Back4app Containers, plano Free
Publisher: Back4app Engineering

Você tem um site. Um pouco de HTML, uma folha de estilo, talvez um pouco de JavaScript. Ele funciona quando você abre no seu laptop, e agora precisa de um endereço que outras pessoas possam digitar — sem alugar um servidor, mantê-lo atualizado ou aprender o que é um reverse proxy.

Colocá-lo em um container resolve isso. Você descreve o servidor web uma vez, em um arquivo pequeno, envia para um repositório, e um host faz o build e o executa para você. Não há nada para manter depois, porque não existe nenhuma máquina sua no caminho.

Este guia faz o percurso completo: o site, o arquivo do container, o deploy e um endereço no ar. Foram **9 segundos** do push ao site no ar — e a última seção explica por que a maioria dos exemplos que você encontra na internet demora bem mais do que isso.

## Prefere assistir?

O passo a passo original leva uma página de um repositório do GitHub a um container rodando, do começo ao fim.

## Do que você realmente precisa?

Dos seus arquivos, e de mais um arquivo ao lado deles. Essa é a lista inteira — nenhum servidor, nenhuma conta de hospedagem para configurar, nenhum servidor web para instalar em nada que seja seu.

O arquivo extra é um `Dockerfile`. Ele nomeia um servidor web, diz onde suas páginas ficam, e é só isso que ele precisa fazer. Um host o lê, faz o build do resultado uma vez e o executa.

O exemplo aqui é um site de quatro arquivos: uma página HTML, uma folha de estilo, algumas linhas de JavaScript e o `Dockerfile`. O seu pode ter mil páginas; nada do que vem abaixo muda.

## Como escrever o arquivo do container?

Três linhas. Parta da imagem oficial do nginx, copie seu site para a pasta que ela serve e declare a porta.

```dockerfile
FROM nginx:1.27-alpine
COPY site/ /usr/share/nginx/html
EXPOSE 80
```

Esse é o arquivo inteiro. Não há etapa de instalação, porque a imagem já contém o nginx, e não há comando de inicialização, porque a imagem já sabe como iniciá-lo.

O único valor que vale a pena conhecer é `/usr/share/nginx/html` — o diretório de onde essa imagem serve os arquivos. Coloque seu `index.html` ali e o site funciona; coloque em qualquer outro lugar e você recebe um 404.

Fixe a versão na tag, como `1.27-alpine` faz aqui. Isso garante que a imagem que você construir no mês que vem seja a mesma que construiu hoje, e não o que estiver em vigor naquele momento.

## Como colocar no ar?

Envie o repositório e aponte um app de container para ele. Na dashboard, **Web Deployment** → escolha o repositório do GitHub → branch e diretório raiz → **Create app**.

Não há nada para preencher no caminho. A plataforma encontra o `Dockerfile` e marca o build como detectado — sem comando de build, sem comando de inicialização, sem porta, porque os três já estão respondidos pelo arquivo que você escreveu.

![O painel de deployments do Containers mostrando o deployment marcado como Ready em 9 segundos, o app Available e um aviso de que a URL do plano Free é temporária e fica no ar por 60 minutos](/blog/blog-assets/host-a-static-website-in-a-container/02-deployment.jpg)

O deployment voltou marcado como **Ready em 9 segundos**. Esse é o número da própria plataforma, do push ao endereço HTTPS no ar, e é o número que a última seção deste post explica.

## Funcionou mesmo?

Sim — o endereço serve o site de verdade, não um placeholder. Cada arquivo voltou com exatamente o tamanho em bytes que o repositório guarda, e o header do servidor informa a versão fixada na tag.

```text
/            HTTP 200   text/html                2083 B
/style.css   HTTP 200   text/css                 2218 B
/app.js      HTTP 200   application/javascript    204 B

Server: nginx/1.27.5
```

O JavaScript roda, a folha de estilo se aplica, e a página fica igual ao que fica no laptop. Um container não está fazendo nada de engenhoso aqui — essa é justamente a razão de usar um.

## Por que a maioria dos exemplos constrói algo muito maior?

Porque eles instalam o servidor web em vez de partir de um. Quase todo tutorial que você vai encontrar, incluindo o vídeo acima, começa de uma imagem Linux de uso geral e usa o gerenciador de pacotes.

```dockerfile
FROM ubuntu:latest
RUN apt-get update
RUN apt-get -y install nginx
COPY index.html /var/www/html/index.html
EXPOSE 80
CMD nginx -g "daemon off;"
```

Funciona, e a página servida é idêntica. O que difere é o que é construído, enviado e baixado toda vez que você faz o deploy — e a divisão por camadas mostra de onde vem esse peso.

| Camada, como o `docker history` reporta | Tamanho |
| --- | --- |
| Base Ubuntu 26.04 | 135 MB |
| `apt-get update` | **43,1 MB** |
| `apt-get -y install nginx` | 3,62 MB |
| `COPY index.html` | 20,5 kB |

O que você queria — um servidor web e a sua página — soma 3,64 MB, dentro de uma imagem que o `docker images` reporta como 254 MB. A etapa `apt-get update`, que existe só para que a linha *seguinte* possa rodar, é mais de dez vezes maior do que o software que ela buscou.

## Dá para manter a distribuição e ainda ser pequeno?

Em boa parte, sim — e vale saber disso se você precisa de uma distribuição para outra coisa. O custo acima não é bem do Ubuntu; é que o `apt-get update` grava seu catálogo em uma camada, e camadas são imutáveis, então apagá-lo depois não recupera nada.

Faça a instalação e a limpeza em uma única instrução e ele nunca é gravado.

```dockerfile
FROM ubuntu:26.04
RUN apt-get update \
 && apt-get install -y --no-install-recommends nginx \
 && rm -rf /var/lib/apt/lists/*
COPY site/ /var/www/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
```

Isso mede **181 MB** — 73 MB a menos, mesma distribuição, mesmo nginx. Também fixa a base em vez de seguir a `latest`, pula os pacotes recomendados e escreve o `CMD` na forma exec, para que o nginx receba sinais diretamente.

| | Tamanho da imagem | Build a frio | Versão do nginx |
| --- | --- | --- | --- |
| Distribuição, como se costuma escrever | 254 MB | 12 s | 1.28.3, a que o apt tiver |
| Distribuição, com limpeza | 181 MB | 9 s | 1.28.3, a que o apt tiver |
| nginx Alpine oficial | **75,9 MB** | **1 s** | 1.27.5, fixada pela tag |

![As três imagens desenhadas em escala: 254 MB para a base de distribuição como se costuma escrever, com 43,1 MB marcados como índice de pacotes do apt; 181 MB para a mesma base com limpeza; 75,9 MB para a imagem oficial nginx Alpine](/blog/blog-assets/host-a-static-website-in-a-container/01-sizes.svg)

É daqui que vieram os nove segundos. Um arquivo de três linhas não tem etapa de instalação para rodar, então o deploy é um pull e uma cópia; um arquivo que instala pacotes repete esse trabalho a cada release.

## O que o plano Free oferece?

O suficiente para colocar algo na frente de alguém, e não o suficiente para deixar rodando. O container recebe 0,25 vCPU, 256 MB de memória e 100 GB de transferência, o que é confortável para um site estático.

O limite que importa é o endereço: no plano Free ele é temporário e expira **60 minutos** depois do deployment. Isso o torna uma janela de compartilhamento, não hospedagem — serve para mostrar a um cliente, não para um site que as pessoas salvam nos favoritos. Um subdomínio permanente ou seu próprio domínio exige um plano pago.

## O que fazer em seguida?

Coloque seus próprios arquivos em `site/`, não mude mais nada e faça o deploy. O arquivo do container não se importa se está carregando uma página ou um site de documentação gerado, então as mesmas três linhas cobrem quase tudo de estático que você vier a construir.

Mantenha a imagem oficial do servidor de que você precisa e fixe a tag. Recorra a uma distribuição só quando algo exigir de fato — um módulo incomum, uma etapa de build — e, quando fizer isso, mantenha a instalação e a limpeza em uma única instrução.
