ENTRYPOINT e CMD são duas instruções em um Dockerfile que definem o que será executado dentro do contêiner quando ele é iniciado. Embora possam parecer semelhantes, eles têm finalidades distintas e funcionam de maneiras diferentes. Aqui está uma comparação detalhada para esclarecer como e quando usar cada uma:
ENTRYPOINT
Objetivo: Define o comando principal que será sempre executado quando o contêiner for iniciado.
Imutabilidade: ENTRYPOINT é utilizado para definir o comando que deve sempre ser executado no contêiner, independentemente dos comandos ou argumentos passados na linha de comando ao iniciar o contêiner.
Uso como Executável: Configura o contêiner para se comportar como um executável específico, onde argumentos podem ser passados dinamicamente.
Execução Consistente: Se você deseja que o contêiner sempre execute um comando específico, use ENTRYPOINT.
Exemplo:
FROM ubuntu:20.04
ENTRYPOINT ["echo", "Hello"]
Neste exemplo, o comando echo Hello será sempre executado ao iniciar o contêiner, e você pode passar argumentos adicionais para o echo no momento da execução do contêiner:
docker run minha_imagem World
Resultado:
Hello World
CMD
Objetivo: Define comandos ou argumentos padrão que podem ser substituídos ao executar o contêiner.
Flexibilidade: CMD é mais flexível e pode ser facilmente sobrescrito passando um comando diferente na linha de comando ao iniciar o contêiner.
Combinação com ENTRYPOINT: Quando usado junto com ENTRYPOINT, CMD fornece argumentos padrão para o comando especificado em ENTRYPOINT. Se não houver ENTRYPOINT, CMD define o comando padrão para o contêiner.
Comando Opcional: Se você quer que o contêiner tenha um comando padrão, mas permita ao usuário passar um comando diferente quando necessário, use CMD.
Exemplo:
FROM ubuntu:20.04
CMD ["echo", "Hello, World!"]
Neste caso, se você iniciar o contêiner sem passar nenhum comando, ele executará echo Hello, World!. No entanto, você pode substituir isso ao iniciar o contêiner:
docker run minha_imagem echo "Outro comando"
Resultado:
Outro comando
Usando ENTRYPOINT e CMD Juntos
Quando combinados, ENTRYPOINT define o comando principal que sempre será executado, enquanto CMD pode fornecer argumentos padrão para esse comando.
Exemplo:
FROM ubuntu:20.04
ENTRYPOINT ["echo"]
CMD ["Hello, World!"]
Neste exemplo:
ENTRYPOINT é definido como echo.
CMD fornece o argumento padrão Hello, World!.
Ao iniciar o contêiner sem argumentos adicionais, ele executará:
docker run minha_imagem
Resultado:
Hello, World!
Se você passar um argumento diferente, ele substituirá o CMD:
docker run minha_imagem "Outro texto"
Resultado:
Outro texto
Resumo das Diferenças
ENTRYPOINT:
Define um comando fixo que sempre será executado.
Ideal para configurar o contêiner para se comportar como um executável.
Não é facilmente substituível a menos que se use a flag --entrypoint.
CMD:
Define um comando ou argumentos padrão.
Pode ser substituído ao iniciar o contêiner.
É usado para fornecer argumentos ao ENTRYPOINT ou para definir um comando padrão se ENTRYPOINT não for usado.
Quando Usar Cada Um
Use ENTRYPOINT quando você deseja que o contêiner sempre execute um comando específico e permita que o usuário apenas passe argumentos adicionais.
Use CMD quando você deseja fornecer um comando ou argumentos padrão que podem ser facilmente substituídos.
Laboratório
CMD e ENTRYPOINT
Executa o comando de inicialização do container;
Não cria uma camada no file system da imagem, mas como metadado
Será executado somente na inicialização do container;
Podem ser combinados para otimizar a execução dos comandos.
ENTRYPOINT
Utilizado quando o comando não será sobrescrito, somente argumentos adicionais
CMD
Utilizado quando o comando ou argumentos podem ser sobrescritos.
No exemplo abaixo /bin/bash seria o CMD do containter:
$ docker container run -it ubuntu /bin/bash
Outro exemplo:
$ docker container run ubuntu echo Marcelo
Marcelo
Entrypoint
Exemplo para imprimir "Hello World!"
FROM ubuntu
RUN apt update && apt install curl --yes
WORKDIR /app
ENTRYPOINT [ "echo", "Hello World!" ]
$ docker container run ubuntu-curl teste
$ docker container run ubuntu-curl teste
Hello World! teste
$ docker image inspect ubuntu-curl
...
"Cmd": [
"combinado com o entrypoint"
],
...
"Entrypoint": [
"echo",
"Hello World!"
],
...
Sobrescrever o ENTRYPOINT
$ docker container run --entrypoint echo ubuntu-curl teste
teste
$ docker image inspect ubuntu-curl
...
"Cmd": [
"combinado com o entrypoint"
],
...
"Entrypoint": [
"echo",
"Hello World!"
],
...
Shell Script
$ touch entrypoint.sh
$ vim entrypoint.sh
$ cat entrypoint.sh
#!/bin/bash
if [ -z $1 ]
then
echo "Iniciando o container sem parametro"
else
echo "Iniciando o container com o parametro $1"
fi
Arquivo entrypoint.sh:
#!/bin/bash
if [ -z $1 ]
then
echo "Iniciando o container sem parametro"
else
echo "Iniciando o container com o parametro $1"
fi