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:
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