Se você já ouviu a frase “na minha máquina funciona”, sabe exatamente o problema que o Docker resolve. Este guia de Docker para iniciantes foi escrito para quem nunca rodou um container na vida: vamos começar pelos conceitos, instalar a ferramenta, executar os primeiros comandos e terminar criando uma imagem própria de uma aplicação Node.js — tudo com prints de cada etapa.
Ao final, você vai entender a diferença entre imagem e container, saber ler a saída do docker ps, publicar portas, ver logs, e ter um Dockerfile funcional que pode reaproveitar nos seus projetos.
O que é Docker e por que ele existe
Docker é uma plataforma que empacota uma aplicação junto com tudo o que ela precisa para rodar — sistema base, bibliotecas, runtime da linguagem, dependências e configurações — em uma unidade padronizada chamada container. Esse container roda do mesmo jeito no seu notebook, no computador do colega e no servidor de produção.
Antes do Docker, era comum cada ambiente ter uma versão diferente do PHP, do Node.js ou do banco de dados. Um sistema funcionava no computador do desenvolvedor e quebrava no servidor porque faltava uma extensão, porque a versão da biblioteca era outra ou porque uma variável de ambiente não existia. O Docker elimina boa parte dessa loteria: o ambiente passa a ser descrito em código e reproduzido de forma idêntica.
Container não é máquina virtual
Uma confusão comum de quem está começando é achar que container é uma máquina virtual mais leve. A ideia é parecida, mas o funcionamento é diferente:
- Máquina virtual (VM) emula um computador inteiro, com um sistema operacional completo rodando por cima de um hypervisor. Ela consome gigabytes de disco e leva minutos para iniciar.
- Container compartilha o kernel do sistema hospedeiro e isola apenas os processos, a rede e o sistema de arquivos da aplicação. Ele ocupa megabytes e sobe em segundos (às vezes em milissegundos).
Na prática, isso significa que você consegue rodar dezenas de containers em um notebook comum, algo impensável com VMs.
Conceitos essenciais: imagem, container, registry e volume
Antes de digitar qualquer comando, vale fixar quatro palavras que vão aparecer o tempo todo:
| Conceito | O que é | Analogia |
|---|---|---|
| Imagem | Um pacote somente leitura com o sistema base, dependências e o código da aplicação | A receita de um bolo |
| Container | Uma instância em execução de uma imagem | O bolo pronto, saído do forno |
| Registry | Um repositório de imagens, como o Docker Hub | O livro de receitas compartilhado |
| Volume | Um espaço de armazenamento que sobrevive quando o container é removido | A geladeira onde você guarda o que sobrou |
Uma mesma imagem pode gerar vários containers ao mesmo tempo, assim como uma receita pode gerar vários bolos. E, importante: containers são descartáveis. Qualquer arquivo gravado dentro de um container é perdido quando ele é removido — a não ser que esteja em um volume.
Como instalar o Docker
A instalação muda conforme o sistema operacional. Os caminhos oficiais são:
- Windows: instale o Docker Desktop. Ele usa o WSL 2 por baixo dos panos, então ative o WSL antes (
wsl --installno PowerShell como administrador) e reinicie o computador. - macOS: baixe o Docker Desktop para a arquitetura do seu Mac (Apple Silicon ou Intel) e arraste para a pasta Aplicativos.
- Linux (Ubuntu/Debian): o caminho mais rápido é o script oficial de conveniência.
No Linux, os comandos são:
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Permite usar o docker sem sudo (faça logout e login depois)
sudo usermod -aG docker $USER
Verificando se a instalação funcionou
Abra um terminal e rode docker --version. Se aparecer a versão, o cliente está instalado. Para confirmar que o daemon (o serviço que realmente executa os containers) está no ar, use docker info:

Se o docker info retornar um erro como Cannot connect to the Docker daemon, o serviço não está rodando. No Windows e no Mac, abra o Docker Desktop e aguarde o ícone da baleia ficar estável. No Linux, rode sudo systemctl start docker.
Seu primeiro container: docker run hello-world
O teste clássico de toda instalação é a imagem hello-world. Ela não faz nada de útil além de imprimir uma mensagem — e justamente por isso é perfeita para entender o fluxo:
docker run hello-world

Repare no que aconteceu, porque é o mesmo fluxo de qualquer container:
- O Docker procurou a imagem
hello-world:latestno seu computador e não encontrou (Unable to find image locally). - Ele então baixou a imagem do Docker Hub, o registry público padrão (Pulling from library/hello-world).
- Criou um container a partir dessa imagem e executou o programa dentro dele.
- O programa imprimiu a mensagem e terminou — e, quando o processo principal termina, o container para.
Se você rodar o mesmo comando de novo, o passo de download não acontece: a imagem já está em cache local.
Rodando um servidor web de verdade com Nginx
Agora vamos subir algo útil: o servidor web Nginx. Desta vez usaremos três opções novas do docker run:
docker run -d --name meu-nginx -p 8080:80 nginx
-d(detached) roda o container em segundo plano e devolve o terminal para você.--name meu-nginxdá um nome amigável ao container. Sem isso, o Docker inventa um nome aleatório.-p 8080:80publica a porta: tudo o que chegar na porta 8080 do seu computador é encaminhado para a porta 80 do container. O formato é sempreHOST:CONTAINER.
Em seguida, liste os containers em execução com docker ps:

A coluna PORTS confirma o mapeamento 0.0.0.0:8080->80/tcp. Abra o navegador em http://localhost:8080 e você verá a página padrão do Nginx, servida de dentro do container:

Os comandos do dia a dia
Com um container rodando, estes são os comandos que você mais vai usar:
docker ps # lista containers em execução
docker ps -a # lista todos, inclusive os parados
docker logs meu-nginx # mostra os logs do container
docker logs -f meu-nginx # acompanha os logs em tempo real
docker exec -it meu-nginx sh # abre um terminal dentro do container
docker stop meu-nginx # para o container
docker start meu-nginx # inicia de novo
docker rm meu-nginx # remove (precisa estar parado)
docker images # lista as imagens baixadas
docker rmi nginx # remove uma imagem
O docker exec -it merece atenção: ele permite “entrar” no container para investigar arquivos, testar comandos e depurar problemas. O -i mantém a entrada interativa e o -t aloca um terminal.
Criando sua própria imagem com Dockerfile
Usar imagens prontas é ótimo, mas o poder do Docker aparece quando você empacota a sua aplicação. Para isso existe o Dockerfile: um arquivo de texto com as instruções para montar a imagem, passo a passo.
Vamos usar como exemplo a API de tarefas que construímos no tutorial Minha primeira API em Node.js com Express. Na raiz do projeto, crie um arquivo chamado exatamente Dockerfile (sem extensão):

Cada instrução gera uma camada da imagem:
- FROM define a imagem base. Aqui usamos
node:22-alpine, uma versão enxuta do Node.js baseada em Alpine Linux. - WORKDIR cria e entra na pasta
/appdentro da imagem. - COPY package*.json ./ copia apenas os arquivos de dependências. Fazemos isso antes de copiar o resto do código por um motivo de performance: se só o código mudar, o Docker reaproveita a camada do
npm cido cache e o build fica muito mais rápido. - RUN executa um comando durante o build — no caso, instala as dependências de produção.
- EXPOSE documenta a porta usada pela aplicação (ele não publica a porta sozinho; quem faz isso é o
-p). - CMD define o comando executado quando o container inicia.
Crie também um arquivo .dockerignore para evitar copiar lixo para dentro da imagem:
node_modules
npm-debug.log
.git
.env
Ignorar o .env é especialmente importante: tokens e senhas não devem ficar gravados dentro de uma imagem. Falamos disso em detalhes no tutorial sobre variáveis de ambiente e arquivo .env.
Construindo a imagem com docker build
Na mesma pasta do Dockerfile, rode:
docker build -t minha-api:1.0 .
O -t dá nome e versão (tag) à imagem, e o ponto final indica que o contexto do build é a pasta atual.

Executando a imagem que você criou
Agora é só rodar a imagem como qualquer outra:

Pronto: sua aplicação está empacotada. Qualquer pessoa com Docker instalado consegue rodá-la com um único comando, sem instalar Node.js, sem npm install e sem se preocupar com a versão do sistema.
Volumes: como não perder dados
Lembra que containers são descartáveis? Se você rodar um banco de dados em um container e removê-lo, os dados vão junto. A solução são os volumes:
# Volume nomeado, gerenciado pelo Docker
docker volume create dados-mysql
docker run -d --name banco -v dados-mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=segredo mysql:8.4
# Bind mount: espelha uma pasta do seu computador dentro do container
docker run -d -p 8080:80 -v "$(pwd)/site:/usr/share/nginx/html" nginx
O volume nomeado é ideal para bancos de dados. O bind mount é ótimo em desenvolvimento: você edita os arquivos no seu editor e o container enxerga as mudanças na hora.
Erros comuns de quem está começando com Docker
“port is already allocated” — outra aplicação (ou outro container) já está usando a porta do host. Troque o lado esquerdo do -p, por exemplo -p 8081:80, ou pare o processo que ocupa a porta.
“Conflict. The container name is already in use” — já existe um container com esse nome, mesmo que parado. Remova com docker rm nome ou escolha outro nome.
“permission denied while trying to connect to the Docker daemon socket” — no Linux, seu usuário não está no grupo docker. Rode sudo usermod -aG docker $USER e faça logout/login.
O container para logo depois de iniciar — o processo principal terminou ou deu erro. Veja o motivo com docker logs nome-do-container. Um container só fica vivo enquanto o processo definido no CMD estiver rodando.
Disco cheio de imagens antigas — com o tempo, imagens e containers parados se acumulam. O comando docker system prune remove o que não está em uso (leia o aviso com atenção antes de confirmar).
Boas práticas desde o primeiro dia
- Fixe versões das imagens base. Prefira
node:22-alpineanode:latest. Olatestmuda sem aviso e pode quebrar seu build. - Uma responsabilidade por container. API em um container, banco em outro. Para orquestrar vários, use o Docker Compose — veja o tutorial Docker Compose com PHP e MySQL.
- Nunca coloque segredos na imagem. Passe tokens por variáveis de ambiente em tempo de execução (
-eou--env-file). - Use
.dockerignorepara manter a imagem pequena e sem arquivos sensíveis. - Ordene o Dockerfile pensando em cache: o que muda pouco (dependências) vem antes do que muda muito (código).
Perguntas frequentes sobre Docker para iniciantes
Docker é gratuito?
O Docker Engine (usado em servidores Linux) é open source e gratuito. O Docker Desktop é gratuito para uso pessoal, educacional, projetos open source e empresas pequenas; organizações maiores precisam de uma assinatura. Consulte os termos atuais no site oficial.
Preciso saber Linux para usar Docker?
Não para começar, mas ajuda muito. A maioria das imagens é baseada em Linux, então comandos como ls, cd, cat e noções de permissões de arquivo aparecem com frequência ao depurar containers.
Qual a diferença entre docker run e docker start?
O docker run cria um container novo a partir de uma imagem e o inicia. O docker start apenas reinicia um container que já existe e está parado.
Docker substitui o Kubernetes?
Não. Docker cria e executa containers; Kubernetes orquestra muitos containers em vários servidores, com escalonamento automático e alta disponibilidade. Se quiser se aprofundar, leia nosso artigo sobre arquitetura de microserviços com Docker e Kubernetes.
Onde encontro imagens prontas?
No Docker Hub. Dê preferência às imagens marcadas como Docker Official Image ou Verified Publisher, que têm manutenção e atualizações de segurança.
Conclusão e próximos passos
Neste tutorial de Docker para iniciantes você aprendeu os conceitos de imagem, container, registry e volume; instalou o Docker; rodou o hello-world e o Nginx; e criou sua primeira imagem com Dockerfile. Isso já é suficiente para padronizar o ambiente dos seus projetos e acabar com o “na minha máquina funciona”.
O próximo passo natural é subir mais de um serviço ao mesmo tempo — uma aplicação PHP conversando com um banco MySQL, por exemplo. É exatamente isso que fazemos no tutorial Docker Compose com PHP e MySQL. E, se você quer usar containers para consumir APIs brasileiras como CEP, CNPJ, SMS e WhatsApp, conheça a APIBrasil.
![]()









