Você viu Entrypoint e CMD em algum lugar, seja em um dockerfile ou em um docker run, mas não faz a ideia do que seja?
Vem comigo, é mais simples do que você imagina.
Esse é o típico cenário em que a resposta é mais idiota do que você possa imaginar. É algo que não é nem sofisticado, nem complexo, mas gera confusão.
Entrypoint e CMD só existem de forma separada para facilitar nossas vidas. Nada mais.
Quando um container é inicializado, o que será executado é a soma de Entrypoint e CMD.
Então em um dockerfile:
... ENTRYPOINT ["dotnet", "suaapp.dll"] CMD ["meuparametro"] ...
O resultado da execução é semelhante a:
... dotnet suaapp.dll meuparametro ...
Isso quer dizer que, se as 3 sentenças estivessem somente no Entrypoint ou somente no CMD, o resultado seria exatamente o mesmo? Sim!
“Se funciona, então estás certo!” Será?
Então podemos concluir que tanto faz usar CMD ou ENTRYPOINT? Não!
Estou contanto qual é o efeito prático. Você precisa entender agora pra que existe a divisão entre Entrypoint e CMD e pra que foram criados separados.
A anatomia do docker run
Essa é a anatomia de um docker run:
... docker run [OPTIONS] IMAGE [COMMAND] [ARG...] ...
Nota que você enxerga um COMMAND, mas não enxerga o ENTRYPOINT?
Isso é feito para que o Entrypoint seja estático, definido na imagem, durante o build, enquanto o CMD, você teria um default no dockerfile, mas pode facilmente sobrescrever durante um docker run, por exemplo.
“O ENTRYPOINT de uma imagem é semelhante a um COMMAND porque especificam o executável a ser executado quando o contêiner é iniciado, mas é (intencionalmente) mais difícil de substituir.” Docker run reference
Você pode sobrescrever o entrypoint usando –entrypoint em um docker run, mas sobrescrever o command é mais prático, e possui diversos facilitadores.
O Entrypoint foi desenhado para ser estático (sem impedir a modificação) e o Command foi desenhado para ser uma parte mais dinâmica, com facilitadores para a sobrescrita (com um default expresso no dockerfile).
Exemplo
Em um dockerfile de uma aplicação .NET Core padrão.
- O EntryPoint é
["dotnet","assembly.dll" ]
. - O CMD é null
Dessa forma, se usarmos o Dockerfile ou sobrescrevermos em qualquer outra oportunidade o CMD, esses parâmetros serão passados no argumento args do método Main da classe Program.
class Program { static void Main(string[] args) { if (args != null && args.Length > 0) Console.WriteLine("Seus parâmetros " + args[0]); else Console.WriteLine("Sem parâmetros "); } }
FROM ... Entrypoint ["dotnet", "seuassembly.dll"] CMD ["none"]
Na execução padrão, docker run imagem
teríamos como output “none”.
Mas para ter como output o texto “teste” é basta executar docker run imagem teste
.
Claro que o exemplo foi ridículo e simples, no entanto esse é um recurso poderoso.
Testa aí!?!
Te ajudou?
Quando eu pensei nisso pela primeira vez, tentei achar algo relevante, mas cheguei na documentação a explicações muito simplistas. Eu queria achar um bom e fantástico motivo. Na verdade depois de entender o propósito eu acho de fato sofisticado, principalmente pela simplicidade.
Você sabia disso? Te ajudou?
Compartilha com alguém que possa ser ajudado também!
Sensacional! Muitíssimo obrigado! Finalmente entendi!