Por que containers
"Na minha máquina funciona" é o problema; container empacota o ambiente inteiro, não só o código.
Um app raramente é só código — ele depende de uma versão específica do Ruby, do Node, de bibliotecas do sistema operacional, de variáveis de ambiente. "Funciona na minha máquina" normalmente significa: funciona com o ambiente que eu tenho instalado, não necessariamente o que está descrito em lugar nenhum. Um container resolve isso empacotando o ambiente inteiro — não só o código.
Container não é VM
Uma máquina virtual (VM) simula um computador inteiro, com seu próprio kernel — pesada, lenta pra iniciar. Um container compartilha o kernel do host e isola só o processo (sistema de arquivos, rede, processos) — por isso inicia em milissegundos e pesa megabytes, não gigabytes.
VM Container
├─ Kernel próprio ├─ Compartilha o kernel do host
├─ Gigabytes de tamanho ├─ Megabytes de tamanho
├─ Minutos pra iniciar ├─ Milissegundos pra iniciar
└─ Isolamento total └─ Isolamento de processo (namespaces/cgroups)Imagem vs. container
Uma imagem é o "molde" — um arquivo somente leitura com tudo que o app precisa (sistema de arquivos, dependências, comando de inicialização). Um container é uma imagem em execução — você pode rodar vários containers a partir da mesma imagem, cada um isolado dos outros.
docker run -d -p 8080:80 nginx:alpineIsso baixa a imagem nginx:alpine (se ainda não existir localmente) e sobe um container a partir dela, mapeando a porta 80 do container pra 8080 da sua máquina (-p, próxima lição fala mais disso) — sem instalar nginx na sua máquina, sem configurar nada além dessa linha.