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.
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 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.
/ 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.
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.
O índice de pacotes é uma lista de compras. Não há motivo para despachá-la junto com as compras.
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.
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 |
É 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.
