Skip to main content

Container Entrypoint e Command

Uma imagem pode possuir entrypoints e commands e qual a diferença entre eles?

Primeiramente precisamos entender que um container deve morrer se o processo que ele precisa executar também morrer. Essa é o ciclo de vida de um container.

Se fizermos um teste simples de executar um container ubuntu padrão sem passar nada ele executa e morre. Por quê?

docker run ubuntu
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
a48641193673: Pull complete
Digest: sha256:6042500cf4b44023ea1894effe7890666b0c5c7871ed83a97c36c76ae560bb9b
Status: Downloaded newer image for ubuntu:latest

docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7b8e6f3f1825 ubuntu "/bin/bash" 22 seconds ago Exited (0) 21 seconds ago jovial_noyce

Por que ele fez o que tinha que ter sido feito... Executou o comando /bin/bash e pronto. Nada segurou ele vivo.

Vamos executar novamente porém agora passando o que queremos executar.

docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
15c54353ebf9 ubuntu "sleep 60" 12 seconds ago Up 11 seconds adoring_ramanujan

docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
15c54353ebf9 ubuntu "sleep 60" 49 seconds ago Up 48 seconds adoring_ramanujan

# e depois de 60s morreu
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

Dentro das definições do dockerfile temos:

ENTRYPOINT \
CMD

ENTRYPOINT representa o executável que irá rodar e CMD o que vem depois.

Se temos um container com:

ENTRYPOINT ["sleep"]
CMD ["10"]

O que ele irá tentar executar sempre será ENTRYPOINT + CMD, ou seja: sleep 10

Se não tivermos o entrypoint e só CMD somente 10 não funcionaria, mas poderíamos trazer o binário para cá. A primeira string sempre precisa ser um executável e o resto são os parâmetros dela.

CMD ["sleep", "10"]

Por outro lado se tivéssemos somente o entrypoint sleep sem o cmd por si só não faz nada, e causaria erro, pois ele está esperando um parâmetro.

ENTRYPOINT ["sleep"]

Seria a mesma coisa que fazer isso.

sleep
sleep: missing operand
Try 'sleep --help' for more information.

No caso em que somente precisamos executar um binário que não precisa de entradas, funcionaria perfeitamente.

Se quiséssemos criar um pod com a imagem ubuntu e rodar o sleep 10, poderíamos fazer uma substituição do entrypoint e do cmd.

apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: sleeper
name: sleeper
spec:
containers:
- image: ubuntu
name: sleeper
command: ["sleep"]
args: ["10"]
# seria a mesma coisa
# command:
# - sleep
# args:
# - "10"
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}

Só para ter uma referência:

Alt text

kubectl apply -f sleeper.yaml
kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-7b8df77865-gt6fd 1/1 Running 1 (39m ago) 128m
nginx-7b8df77865-95qhp 1/1 Running 1 (39m ago) 128m
sleeper 1/1 Running 0 8s

kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-7b8df77865-gt6fd 1/1 Running 1 (39m ago) 128m
nginx-7b8df77865-95qhp 1/1 Running 1 (39m ago) 128m
sleeper 0/1 Completed 0 16s

Para subir um pod e passar os comandos temos:

kubectl run busybox --image busybox --dry-run=client -o yaml --command -- sleep 1000
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: busybox
name: busybox
spec:
containers:
- command:
- sleep
- "1000"
image: busybox
name: busybox
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}

kubectl exec -it busybox -- ping www.google.com.br

PING www.google.com.br (172.217.162.131): 56 data bytes
64 bytes from 172.217.162.131: seq=0 ttl=110 time=15.942 ms
64 bytes from 172.217.162.131: seq=1 ttl=110 time=15.956 ms