cd ..
DOCKER

Todas as instruções do Dockerfile e a diferença entre ENTRYPOINT e CMD

Todas as instruções do Dockerfile e a diferença entre ENTRYPOINT e CMD

Na parte anterior, construímos uma imagem simples com FROM, RUN, EXPOSE e CMD. O Dockerfile tem várias outras instruções — cada uma resolvendo um problema específico de como a imagem é montada e como o container se comporta ao iniciar.

Guia de referência das instruções

InstruçãoO que faz
FROMindica qual imagem será utilizada como base. Precisa ser a primeira linha do Dockerfile
RUNexecuta um comando em uma nova camada no topo da imagem e “commita” a alteração, disponível para as próximas instruções
COPYcopia novos arquivos e diretórios do contexto de build e adiciona ao filesystem do container
ADDcopia arquivos, diretórios, arquivos TAR ou arquivos remotos (URLs) para o filesystem do container — mais poderoso que o COPY, mas também menos previsível
CMDdefine o comando padrão executado quando o container é iniciado. Diferente do RUN, que roda durante o build, o CMD só roda em tempo de execução
ENTRYPOINTconfigura o container para rodar como um executável fixo. Quando esse executável termina, o container também termina
ENVdefine variáveis de ambiente disponíveis dentro do container
EXPOSEinforma qual porta o container estará ouvindo (documentação — não publica a porta sozinho)
LABELadiciona metadados à imagem, como versão, descrição e autor
MAINTAINERdefine o autor da imagem (instrução antiga, hoje substituída por LABEL)
USERdetermina qual usuário será utilizado ao rodar a imagem. Por padrão é o root
VOLUMEcria um ponto de montagem no container, marcando aquele caminho como dado persistente
WORKDIRmuda do diretório raiz (/) para o diretório especificado

ENTRYPOINT vs CMD

Esse é o ponto que mais gera confusão, então vale destrinchar com calma.

O detalhe importante aparece quando os dois estão juntos no mesmo Dockerfile: nesse caso, o CMD deixa de ser um comando e passa a fornecer apenas os parâmetros para o ENTRYPOINT.

ENTRYPOINT ["/usr/sbin/apachectl"]
CMD ["-D", "FOREGROUND"]

Isso é útil porque o CMD ainda pode ser sobrescrito ao rodar o container (docker run minha-imagem -D BACKGROUND, por exemplo), enquanto o ENTRYPOINT permanece garantido — o container sempre vai rodar o Apache, o que muda são só os parâmetros.

Um exemplo mais próximo do dia a dia, com Nginx:

ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]

Aqui o ENTRYPOINT transforma o container definitivamente em “um Nginx”. O daemon off; do CMD serve para que o Nginx rode em primeiro plano (foreground) — sem isso, o processo se colocaria em segundo plano e o container, sem nenhum processo em primeiro plano para acompanhar, seria encerrado imediatamente.

Passando variáveis do build para o container com ARG e ENV

ARG define uma variável disponível apenas durante o build. Para que ela também fique acessível dentro do container em tempo de execução, é preciso “promovê-la” para uma ENV:

ARG GIROPOPS
ENV GIROPOPS=$GIROPOPS

Inspecionando o resultado

Depois de buildar a imagem, dá para conferir tudo o que foi configurado — Entrypoint, Cmd, Env, ExposedPorts — com:

docker container inspect meu-nginx

Conclusão

Com essas instruções, um Dockerfile deixa de ser só “instalar um pacote e rodar um comando” e passa a descrever de verdade como uma aplicação deve se comportar dentro do container: qual usuário usar, quais variáveis injetar, quais dados persistir e qual processo é, de fato, o dono do container.

Se o objetivo for reduzir o tamanho final da imagem — por exemplo, quando a aplicação precisa de ferramentas de build que não deveriam ir para produção —, vale complementar esta leitura com o post sobre multi-stage builds, que separa a etapa de build da etapa de execução dentro do mesmo Dockerfile.

Na próxima parte da série, vamos ensinar o Docker a desconfiar do próprio container com HEALTHCHECK.

Referências

O que achou?