# O que é Docker: imagem, container e Dockerfile na prática

> Entenda a diferença entre imagem e container, pegue uma imagem no Docker Hub e construa a sua com Dockerfile, partindo do Ubuntu 18.04.

- Autor: Henrylle Maia, consultor AWS
- Publicado em: 2026-10-15
- Assuntos: Containers, Carreira
- URL: https://pages.formacaoaws.com.br/blog/o-que-e-docker/
- Aula de origem: "O que é e como trabalhar com Docker" (https://www.youtube.com/watch?v=Yqi3gN3sAe8)

Docker é uma tecnologia criada para abstrair uma série de coisas na hora de construir uma aplicação, e dois pilares sustentam tudo: a imagem e o container. Para quem programa, a imagem é a classe e o container é a instância. Abaixo eu mostro a diferença na prática: pego uma imagem pronta, rodo um container e construo uma imagem minha com um Dockerfile.

> **Importante:** esta é uma aula de julho de 2021, e os comandos e as telas são os daquela época. Para instalar o Docker, siga o guia da página oficial do seu sistema operacional.

## Imagem e container: classe e instância

Para quem vem da programação, a imagem é a classe e o container é a instância dessa classe. A imagem é uma especificação do que você quer que esteja pronto para rodar. O container é o que você manda executar para conseguir interagir com ele.

Pegue como exemplo uma imagem do Ubuntu. Quando eu mando rodar essa imagem, tenho um container do Ubuntu. Se mando rodar de novo, tenho um segundo container, novo. O que você tem pronto é a imagem. O que você tem rodando é o container.

## Por que o container é leve

Uma VM precisa de um sistema operacional próprio para rodar. O container roda acima do sistema operacional da máquina: no meu desenho, o Linux fica embaixo e os containers em cima. Por rodar acima, ele abstrai uma série de recursos que dependem do sistema operacional, e por isso a execução é muito mais leve. É isso que explica tanta adoção de container.

![Dois blocos lado a lado, máquina de dev e produção (PROD): em cada um, o container fica acima do Linux, a mesma estrutura nos dois](https://pages.formacaoaws.com.br/blog/assets/posts/o-que-e-docker/container-acima-do-so.svg)

Outro ganho: a máquina de desenvolvimento e a de produção têm a mesma estrutura, uma distribuição Linux com o container em cima. Acaba a conversa de "roda na minha máquina, mas em produção dá problema". O dev perde essa desculpa.

## VM virtualiza o hardware, Docker virtualiza o SO

Numa aula de abril de 2023, [Docker versus VM](https://www.youtube.com/watch?v=95uQFarX7_Y), o Henrylle põe as duas lado a lado. Com VM você virtualiza o hardware (disco, memória), e quem faz isso é o hypervisor, como o VirtualBox. Cada máquina virtual ainda precisa de um sistema operacional instalado, e depois a aplicação e as dependências, uma a uma. Com Docker você virtualiza o sistema operacional: em vez do hypervisor, instala o Docker, e em vez de um SO mais a aplicação, roda a imagem da aplicação. Sem o SO por aplicação, o peso sai da casa dos gigas para a dos megas, e o início, de minutos para segundos.

A imagem gerada na sua máquina é a mesma que roda em produção. Ele não promete 100%: em 99% dos casos o ambiente é igual, porque pode haver alguma particularidade muito específica. Fica 100% igual quando o container não tem estado e a imagem vem de um Dockerfile com boas práticas.

Ter container sem estado quer dizer que ele foi feito para morrer: o que ele precisa gravar vai para fora dele, e um novo container volta ao estado original. Mostro isso em [Volume no Docker](https://pages.formacaoaws.com.br/blog/volume-no-docker-windows-e-linux/).

Um detalhe do `docker build`: se o Dockerfile tem outro nome, o `-f` indica qual arquivo usar.

## Passo 1: achar uma imagem pronta no Docker Hub

Há duas formas de ter uma imagem: usar uma pronta ou construir a sua, partindo de uma pronta. As prontas ficam no Docker Hub, onde você encontra imagens para criar containers.

Pesquisei `ubuntu` e abri a imagem oficial, que já passou de 1 bilhão de downloads. A página mostra como rodar a imagem. Toda imagem tem um **nome** e uma **tag**: a tag é a versão. O Ubuntu tem várias, como a 18.04, que é a que eu uso.

![A página da imagem oficial do Ubuntu no Docker Hub, com o selo Docker Official Images e mais de 1 bilhão de downloads (1B+)](https://pages.formacaoaws.com.br/blog/assets/posts/o-que-e-docker/docker-hub-ubuntu.webp)

## Passo 2: conferir o Docker e rodar um container

Antes de tudo, o Docker precisa estar rodando na sua máquina. Para conferir, rode:

```bash
docker run hello-world
```

Se aparecer a mensagem "Hello from Docker", está tudo certo. Se não, instale o Docker: a página oficial tem um guia para cada sistema operacional. No Ubuntu, o guia que eu segui usa o repositório: `apt update`, `apt install` e a chave GPG oficial do Docker.

Para baixar a imagem existe o `docker pull`. Eu fui direto ao `run`, passando o nome da imagem com a tag:

```bash
docker run -ti ubuntu:18.04
```

O `-ti` serve para interagir com o container que sobe. Pronto: você está dentro do Ubuntu. O `apt` existe, mas `curl` e `git` não. É um Ubuntu limpo, com poucas opções.

## Passo 3: construir a própria imagem com um Dockerfile

Aqui está a grande vantagem do Docker: você constrói uma imagem já preparada para rodar a sua aplicação. No exemplo, a imagem se chama `app` e precisa ter `curl` e `git`. Na prática, pode levar o seu código-fonte e o que mais deixar o container pronto para rodar.

Crie um arquivo chamado `Dockerfile`. A primeira instrução diz de qual imagem você parte:

```dockerfile
FROM ubuntu:18.04
```

Para construir, rode na pasta do arquivo:

```bash
docker build -t app .
```

O `-t` dá o nome (a tag) da imagem. O ponto no fim é o local dos arquivos que o build pode levar para dentro do container, como o fonte da aplicação. É o último argumento e você precisa informá-lo. Não preciso do `-f` porque, por convenção, o Docker usa o arquivo de nome `Dockerfile`.

Rodando `docker run -ti app`, o container sobe, mas ainda sem `curl` e sem `git`: a imagem só tem o ponto de partida.

## Passo 4: instalar dentro do container não vale para a imagem

Antes de ajustar o Dockerfile, uma demonstração do conceito de classe e instância. Dentro do container, atualizei o Ubuntu e instalei o `curl`:

```bash
apt update
apt install curl -y
```

O `curl` passou a funcionar. Mas a imagem é a classe e o container é a instância, e eu coloquei o `curl` dentro de uma instância. Ao sair, o container deixa de existir. O `docker ps` mostrava só outro container que já rodava na minha máquina, com outro propósito. Rodei `docker run -ti app` de novo e o `curl` sumiu: o Docker instanciou outra vez a imagem `app`, que originalmente não tinha nada.

Para o `curl` já nascer no container, ele precisa entrar na imagem. É o `RUN` do Dockerfile, que executa comandos na construção da imagem:

```dockerfile
FROM ubuntu:18.04
RUN apt update -y
RUN apt install curl -y
```

O `-y` confirma de antemão, para o build não perguntar "tem certeza que quer instalar?". Rodei o `docker build -t app .` de novo e o `docker run -ti app`: agora o `curl` está lá, em todo container criado a partir dessa imagem.

## Passo 5: acrescentar o git e ver o cache

Faltava o `git`. Acrescentei mais uma linha e construí de novo:

```dockerfile
FROM ubuntu:18.04
RUN apt update -y
RUN apt install curl -y
RUN apt install git -y
```

No build, o Docker usa **cache**. O `apt update` e a instalação do `curl` já tinham rodado, então passaram rápido. Só a instalação do `git`, que era nova, precisou ser executada.

![O Dockerfile com as quatro instruções e a saída do build: as etapas 2/4 e 3/4 com "Using cache" e a 4/4, a do git, que é a nova](https://pages.formacaoaws.com.br/blog/assets/posts/o-que-e-docker/dockerfile-e-cache.webp)

Ao rodar `docker run -ti app`, o `git` também está instalado. A imagem `app` agora parte do Ubuntu 18.04 e já tem `curl` e `git`, e poderia ter o que mais você achasse conveniente para levantar a sua aplicação.

**Fluxo:** Imagem (a especificação pronta) → docker run (cria o container) → Container (a instância que roda) → Dockerfile (parte de FROM e acrescenta RUN) → docker build (gera a nova imagem)

## Onde o Docker procura a imagem e como levar arquivos para ela

Numa aula de junho de 2022, [Primeiros passos com Docker + Dockerfile, parte 1](https://www.youtube.com/watch?v=jpJuTs0LQHY), o Henrylle detalha dois pontos que ficaram de fora acima.

Ao rodar `docker run ubuntu:22.04`, o Docker olha primeiro se a imagem existe na sua máquina. Se não existir, procura no Docker Hub, que é o registro padrão, e baixa. Para ver o que já está local, use `docker images`. Se você não informa a tag, vale a `latest`: no caso do Ubuntu, ela apontava para a 22.04. A tag vem depois dos dois pontos.

Outro ponto é o `COPY`, que leva arquivos da sua pasta para a imagem na hora do build. Na aula, uma pasta `teste` com um arquivo `teste2` ("oi, nasci no host") fica ao lado do Dockerfile:

```dockerfile
FROM ubuntu:22.04
COPY teste .
```

Depois do `docker build -t aula-docker .` e do `docker run -ti aula-docker`, o `teste2` já está no container. O `COPY teste .` copia o conteúdo da pasta para o diretório atual do container. Para copiar tudo, inclusive a própria pasta `teste` e o Dockerfile, troque por:

```dockerfile
FROM ubuntu:22.04
COPY . .
```

É assim que o código da sua aplicação entra na imagem. Sem isso, o que você cria dentro de um container some quando ele termina.

## Para ir além

Este post é a base conceitual. Os próximos passos:

- Instalar e usar o Docker no Windows: [Docker no Windows: instalar e rodar o primeiro container](https://pages.formacaoaws.com.br/blog/docker-no-windows/).
- Guardar logs e arquivos fora do container: [Volume no Docker](https://pages.formacaoaws.com.br/blog/volume-no-docker-windows-e-linux/).
- Rodar sem o Docker Desktop: [Finch da AWS: alternativa ao Docker Desktop](https://pages.formacaoaws.com.br/blog/finch-da-aws-alternativa-ao-docker-desktop/).
- Levar a imagem para a AWS: [Primeiro container Docker em produção no Amazon ECS](https://pages.formacaoaws.com.br/blog/primeiro-container-em-producao-no-ecs/).

## Checklist

- Entenda a regra: a imagem é a especificação pronta, o container é a instância que roda.
- Rode `docker run hello-world` para saber se o Docker está funcionando.
- Procure a imagem no Docker Hub e escolha a tag da versão.
- Rode `docker run -ti <imagem>:<tag>` para entrar no container.
- Crie um `Dockerfile` com `FROM` e uma linha `RUN` para cada comando.
- Construa com `docker build -t <nome> .` na pasta do Dockerfile.
- Lembre que o que você instala dentro de um container some quando ele termina. O que vale vai no Dockerfile.

Imagem é a classe, container é a instância: o que você instala no container some quando ele termina, e o que precisa nascer pronto entra na imagem, pelo Dockerfile.
