Específicos · Infraestrutura em TI
Docker: imagem × contêiner, Dockerfile (CMD × ENTRYPOINT), camadas, volumes, multi-stage
Imagem é molde imutável, contêiner é instância descartável — quase todo item se decide perguntando se a frase fala do tempo de construção ou do tempo de execução.
Altíssima28 itens no tópico
A ideia que organiza o assunto
O problema que o contêiner resolve tem nome antigo: na minha máquina funciona. A aplicação depende de uma versão de biblioteca, de uma variável de ambiente, de um caminho no disco — e nada disso viaja junto com o código. A máquina virtual resolvia empacotando um sistema operacional inteiro por aplicação, o que é caro demais para se repetir dezenas de vezes em um servidor.
O Docker empacota a aplicação com o seu ambiente de execução — bibliotecas, binários, arquivos da distribuição — e deixa o núcleo de fora, porque o núcleo é o do hospedeiro, compartilhado por todos os contêineres. Daí virem juntas as duas propriedades que o tópico inteiro explora: portabilidade (o pacote é o mesmo em qualquer lugar) e leveza (não há sistema convidado a manter).
E há uma segunda ideia, que decide mais itens que a primeira: existem duas linhas do tempo, e a banca vive na fronteira entre elas.
| tempo de construção | tempo de execução | |
|---|---|---|
| artefato | Dockerfile → imagem | contêiner |
| comando | docker build | docker run, start, exec |
| camadas | somente leitura, imutáveis | uma camada gravável por contêiner |
| o que sobra depois | tudo, na imagem | nada, salvo em volume |
Quem guarda essa tabela responde sozinho por que não se edita imagem pronta, por
que o dado escrito dentro do contêiner some, por que a ordem das instruções do
Dockerfile importa para o cache e por que EXPOSE não abre porta nenhuma.
Por que se usa (e o que custa)
Ganha-se portabilidade e densidade. O mesmo artefato sobe em desenvolvimento, homologação e produção sem readaptação de código, e, como não há hipervisor nem sistema convidado por instância, a partida é de segundos e o consumo de memória é uma fração do de uma máquina virtual equivalente.
Paga-se em três lugares. O isolamento é mais fraco: o núcleo é um só, e uma falha de núcleo alcança todos os contêineres da máquina — é por isso que a máquina virtual continua ganhando em isolamento. O estado passa a ser problema seu: a camada gravável morre com o contêiner, e persistência exige volume declarado. E surge uma cadeia de suprimento nova — imagens vindas de registries, com camadas herdadas de terceiros, que precisam ser autenticadas, verificadas e atualizadas.
A formulação honesta para a prova: o contêiner troca isolamento por eficiência e padronização. Ele não é uma máquina virtual mais leve; é outra coisa, com outro compromisso.
Como funciona
Do arquivo à imagem. O Dockerfile é texto escrito por uma pessoa, e o
docker build o lê para produzir a imagem — nunca o contrário. Cada instrução
gera uma camada somente leitura, e o resultado é empilhado por um sistema de
arquivos em união (o driver overlay2, hoje o padrão). Como o cache é por
instrução e cai a partir da primeira que mudou, a ordem manda: o que muda pouco
— imagem base, instalação de dependências — vem antes; o código da aplicação, que
muda a cada commit, vem por último.
Da imagem ao contêiner. docker run é create mais start: cria a camada
gravável, fixa a configuração (nome, variáveis de ambiente, portas, volumes) e
dispara o processo principal. Quando um arquivo da imagem é alterado dentro do
contêiner, ele é primeiro copiado para a camada gravável — é a cópia na
escrita — e a alteração existe apenas ali; outros contêineres da mesma imagem
continuam vendo o original. Removido o contêiner, a camada vai junto.
O isolamento tem duas peças. Os namespaces isolam a visão: PID, rede, montagens, usuários. Processos no mesmo namespace se enxergam; processos em namespaces distintos, não. Os cgroups limitam o consumo: CPU, memória, E/S. Confundir as duas é o caminho mais curto para errar um item.
Persistência e rede. Sem volume, dado não sobrevive. O volume é gerenciado
pelo Docker e montado no contêiner; o bind mount liga um diretório do
hospedeiro. Em rede, cada contêiner tem sua própria pilha — por isso dois
contêineres podem escutar na mesma porta interna —, e o acesso a partir do
hospedeiro só existe com -p HOST:CONTÊINER (ou -P).
Distribuição. O registry armazena e entrega imagens: pull traz, push
envia, e a conversa é por TLS, o que significa certificado e chaves. No Docker
Desktop, o Registry Access Management permite à organização autorizar quais
registries os desenvolvedores podem usar, filtrando por nome de domínio.
Vários contêineres. O Compose descreve serviços em um único YAML e os sobe
juntos; com vários -f, o primeiro arquivo é a base e os seguintes sobrepõem.
Acima disso entra o orquestrador — Kubernetes —, e boa parte dos itens deste
tópico atravessa essa fronteira sem avisar.
O que decide os itens
Imagem × contêiner — a distinção de base, e a origem de metade dos erros:
| imagem | contêiner | |
|---|---|---|
| natureza | molde estático, somente leitura | instância em execução |
| mutabilidade | imutável; muda-se o Dockerfile e reconstrói-se | camada gravável própria, descartável |
| identidade | nome e etiqueta (tag), digest | nome, PID, IP |
| cardinalidade | uma imagem → N contêineres | um contêiner → uma imagem |
O verbo do comando — leia-o antes do resto da frase:
| comando | faz | não faz |
|---|---|---|
docker build | constrói imagem a partir do Dockerfile (contexto local, URL de Git ou tarball) | não executa |
docker run | cria e inicia contêiner de imagem existente | não constrói |
docker create | cria e configura, incluindo variáveis de ambiente | não inicia |
docker start | inicia contêiner já criado | não recria |
docker exec / attach | executa outro processo dentro / conecta-se ao principal | não criam contêiner |
docker commit | gera imagem a partir do estado de um contêiner | não lê Dockerfile |
docker push / pull | envia / traz imagem do registry | não constrói |
A instrução do Dockerfile e o seu tempo — FROM, WORKDIR, COPY, ADD,
RUN e USER agem na construção; CMD e ENTRYPOINT só significam alguma
coisa quando o contêiner inicia; EXPOSE não age em tempo algum — é metadado.
CMD × ENTRYPOINT — em uma frase: o argumento passado no docker run
substitui o CMD e é anexado ao ENTRYPOINT. O ENTRYPOINT fixa o
executável; o CMD dá o comando ou os argumentos padrão.
EXPOSE × -p — o primeiro documenta em que porta o contêiner escuta
(EXPOSE 80/tcp); o segundo publica a porta no hospedeiro. Só o segundo torna o
serviço alcançável de fora.
Contêiner × máquina virtual — contêiner: virtualização em nível de sistema operacional, núcleo compartilhado, sem sistema convidado, isolamento por namespaces e cgroups, partida em segundos. Máquina virtual: hipervisor, sistema convidado completo com núcleo próprio, hardware virtualizado, isolamento maior e custo maior.
Namespace × cgroup — visão × consumo. Mesmo namespace significa enxergar; namespaces distintos significam isolamento.
Quem é quem no ecossistema — registry armazena e distribui imagens; Compose define e executa uma aplicação de vários contêineres a partir de um YAML; Kubernetes orquestra contêineres em um cluster; o union file system e o driver de armazenamento sustentam as camadas.
Como a CEBRASPE derruba você aqui
Os 28 itens do tópico estão explicados. Sobre os 14 de gabarito Errado, a contagem é esta: inversão 43% (6 itens), troca de termo 36% (5), e atribuição errada, generalização e relação causal com 7% cada. Os outros 14 itens são Certo — metade exata do tópico.
Docker é um dos poucos tópicos em que inversão supera troca de termo, e isso
não é acidente: o assunto inteiro é feito de cadeias com direção
(Dockerfile → imagem → contêiner; cluster → nó → pod → contêiner) e de ordens que
importam (camadas, arquivos -f). Onde há seta, a banca a vira. A frase que
resume o tópico: em Docker o erro quase nunca é uma definição — é uma seta
apontando para o lado errado.
Um aviso sobre o recorte: 6 dos 28 itens (21%) mencionam Kubernetes, pod ou
cluster, e o título não avisa. Dois deles são errados justamente por atribuir ao
Kubernetes o que é do Docker, ou vice-versa. E 12 dos 28 (43%) trazem comando ou
Dockerfile literal — docker run, docker build, docker create,
docker compose -f, EXPOSE, ENTRYPOINT, RUN pip install. Este é um tópico
de linha de comando tanto quanto de conceito.
A seta ou a ordem virada — 43%, a família dominante. Seis itens, e cada um é
uma cadeia lida ao contrário. A cadeia de construção: “é correto criar um arquivo
Dockerfile por meio do comando docker build” — o build consome o Dockerfile e
produz imagem; jamais o cria. A hierarquia do cluster: “Um nó master do
Kubernetes, composto por um ou mais workloads, é responsável por executar os
contêineres em estruturas de pods” — o master decide, quem executa é o nó de
trabalho, e é o nó que hospeda o pod, não o contrário. A ordem das camadas: “suas
camadas são ordenadas da mais provável de ser alterada para a menos provável de
ser alterada” — é o inverso, porque o cache é invalidado a partir da primeira
instrução alterada e derruba todas as seguintes. A ordem dos arquivos do Compose:
“o arquivo compose.yml especifica as configurações ou personalizações adicionais”
num docker compose -f compose.yml -f compose.admin.yml — o primeiro -f é a
base e quem sobrepõe é o seguinte. A condição do isolamento: “processos executados
em containers nos mesmos namespaces são invisíveis entre si” — mesmo namespace é
exatamente onde se enxergam; invisíveis são os de namespaces distintos, e é por
compartilharem namespace que contêineres de um mesmo pod conversam por localhost.
E a direção da escrita: “as alterações […] são vistas pelos múltiplos containers
do mesmo sistema de arquivos” — a camada gravável é privada de cada contêiner, por
cópia na escrita. Defesa, em uma regra por cadeia: monte a cadeia antes de ler
o item; quem vem depois, no -f e nas camadas, vence; e compartilhado é o que é
somente leitura, privado é o que é gravável.
O termo trocado, com o resto da frase intacto — 36%. Cinco itens, e eles se
dividem em dois moldes. Dois trocam o verbo do comando: “O comando a seguir é
capaz de fazer o build e iniciar a execução do container” seguido de um
docker run (run cria e inicia a partir de imagem pronta; não constrói); e “Para
construir uma imagem […] docker commit -f example-java-df” (commit fotografa o
estado de um contêiner; construir de Dockerfile é docker build -f). Dois trocam
o nome da tecnologia, deixando o predicado correto palavra por palavra:
“Registry Docker é uma ferramenta que favorece a definição e a execução de
aplicativos […] utiliza um único arquivo de configuração YAML” — isso é Docker
Compose, e o registry só guarda e distribui imagens; e “O Docker utiliza sistemas
de arquivos chamados de build” — o nome é union file system, com drivers como
o overlay2, e “build” não é nome de sistema de arquivos nenhum. O quinto troca o
tempo: “modificar diretamente a imagem Docker já criada” para acrescentar uma
dependência — imagem é artefato imutável; altera-se o Dockerfile e reconstrói-se.
Defesa: leia o verbo antes do efeito (build constrói, run cria e inicia, start
religa, exec entra, commit fotografa, push envia); e, quando a descrição estiver
perfeita, desconfie do sujeito.
O contêiner vestido de máquina virtual — 7%. “Quando se executa um container de aplicação .NET, o sistema operacional (SO) contido no convidado, ou seja, sob o SO host, com acesso ao hardware subjacente”: três marcas de máquina virtual numa linha só. Defesa: convidado, hipervisor e acesso ao hardware são vocabulário de VM; o contêiner responde por núcleo compartilhado, namespaces, cgroups e virtualização em nível de sistema operacional.
A metade verdadeira com fecho falso — 7%. “O Registry Access Management permite controlar quais registries os desenvolvedores podem acessar […]; esse recurso opera no nível de DNS e garante suporte a registries somente locais.” A primeira metade é exata; o fecho inverte o propósito do recurso, que existe para autorizar registries remotos, locais e espelhos por nome de domínio — e que, por filtrar por hostname, nem alcança registry acessado por IP. Defesa: frase ligada por ponto e vírgula ou por “e” se julga em duas partes, e basta uma falsa.
O efeito anunciado sem a opção que o produziria — 7%. Um
RUN pip install -r requirements.txt apresentado como instalação “sem o
armazenamento de caches, o que ajuda a reduzir o tamanho final da imagem” — sem
--no-cache-dir, ou sem apagar o cache no mesmo RUN, ele fica gravado dentro da
camada e aumenta a imagem. Defesa: em item com código, procure na linha a opção
que sustentaria o efeito anunciado; se ela não está escrita, o efeito é inventado,
e o próprio Dockerfile exibido é a prova.
Erros clássicos
Achar que se edita uma imagem pronta. Precisou de uma dependência nova? Altera-se o Dockerfile e reconstrói-se, gerando nova etiqueta. Imagem não se remenda.
Confundir EXPOSE com publicação de porta. EXPOSE documenta; -p publica.
Um contêiner com EXPOSE 80 e sem -p está inacessível a partir do hospedeiro.
Trocar CMD por ENTRYPOINT. O que o usuário digita no docker run
substitui o CMD e vira argumento do ENTRYPOINT.
Esperar que o dado sobreviva sem volume. A camada gravável é parte do contêiner; removido ele, o que foi escrito ali desaparece.
Tratar a porta interna como recurso escasso. Dez contêineres podem escutar na 5432 ao mesmo tempo. O que não pode repetir é a porta publicada no hospedeiro.
Confundir os papéis do ecossistema. Registry guarda imagem, Compose sobe um conjunto de serviços em uma máquina, Kubernetes orquestra em um cluster. Nenhum dos três faz o trabalho dos outros.
LidoPraticado