Entrypoint y Command de Contenedor
¿Una imagen puede poseer entrypoints y commands y cuál es la diferencia entre ellos?
Primeramente necesitamos entender que un contenedor debe morir si el proceso que él necesita ejecutar también muere. Ese es el ciclo de vida de un contenedor.
Si hacemos una prueba simple de ejecutar un contenedor ubuntu estándar sin pasar nada, él ejecuta y muere. ¿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
Porque él hizo lo que tenía que haber sido hecho... Ejecutó el comando /bin/bash y listo. Nada lo mantuvo vivo.
Vamos a ejecutar nuevamente pero ahora pasando lo que queremos ejecutar.
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
# y después de 60s murió
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Dentro de las definiciones del dockerfile tenemos:
ENTRYPOINT \
CMD
ENTRYPOINT representa el ejecutable que se ejecutará y CMD lo que viene después.
Si tenemos un contenedor con:
ENTRYPOINT ["sleep"]
CMD ["10"]
Lo que él intentará ejecutar siempre será ENTRYPOINT + CMD, o sea: sleep 10
Si no tuviéramos el entrypoint y solo CMD, solamente 10 no funcionaría, pero podríamos traer el binario para acá. La primera cadena siempre necesita ser un ejecutable y el resto son los parámetros de ella.
CMD ["sleep", "10"]
Por otro lado si tuviéramos solamente el entrypoint sleep sin el cmd por sí solo no hace nada, y causaría error, pues él está esperando un parámetro.
ENTRYPOINT ["sleep"]
Sería la misma cosa que hacer esto.
sleep
sleep: missing operand
Try 'sleep --help' for more information.
En el caso en que solamente necesitamos ejecutar un binario que no necesita de entradas, funcionaría perfectamente.
Si quisiéramos crear un pod con la imagen ubuntu y ejecutar el sleep 10, podríamos hacer una sustitución del entrypoint y del cmd.
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: sleeper
name: sleeper
spec:
containers:
- image: ubuntu
name: sleeper
command: ["sleep"]
args: ["10"]
# sería lo mismo
# command:
# - sleep
# args:
# - "10"
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
Solo para tener una referencia:

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 levantar un pod y pasar los comandos tenemos:
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