From Docker to Kubernetes: Starting apps in containers

CMD, ENTRYPOINT, and ARGS

Dejanu Alex
3 min readNov 19, 2023

Containers have become the de facto compute units of modern cloud-native applications, and at the end of the day,…containers are just a fancy way to run a process.

The first step is to containerize your application. Let’s use a very simple app more exactly cowsay, which is a program that generates ASCII art pictures of a cow with a message. 🐮

Docker

First Dockerfile, using plain CMD instruction, we’re going to build the image docker build -t first <build context with the location of the Dockerfile :

FROM ubuntu:14.04

# install cowsay: "cowsay" default installs to /usr/games
RUN apt-get update && apt-get install -y cowsay --no-install-recommends \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
ENV PATH $PATH:/usr/games


CMD ["cowsay", "Hello World!"]

Using the exec form of CMD instruction we can provide a default execution for our app when the container is being started.

start container

When starting the container using doker run without any arguments, the default behavior (from Dockerfile) is the desired one, but when passing arguments e.g. Test cowsay the container runtime (runc in this case) tries to start Test as an executable in the image, but as one can expect this is not possible.

This behavior can be corrected in the Dockerfile using ENTRYPOINT :

FROM ubuntu:14.04

# install cowsay: "cowsay" default installs to /usr/games
RUN apt-get update && apt-get install -y cowsay --no-install-recommends \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
ENV PATH $PATH:/usr/games

ENTRYPOINT ["cowsay"]
CMD ["Hello World!"]

Building the image, and starting the container once more, we can see that the behaviour of the container is the desired one and when args are being used, they are actually passed to the cowsay bin.

start container

Basically using ENTRYPOINT we set cowsay bin to run as an executable and using CMD we set default arguments that can be overridden when starting the container.

Kubernetes

Next, we are going to start the app in Kubernetes using kubectl in an imperative fashion.

kubectl run with arg

We started a pod (as a job) and once more overridden the default arguments of cowsay app using kubect run :

kubectl run cowsay --image=dejanualex/dockersay:1.0 --restart=Never -- Test me

# check the args of the po
kubectl get po cowsay -ojsonpath="{.spec.containers[0].args}"

What happens if we don’t pass any arguments when running the pod? And the answer is that we’re going to have the default behavior (embedded in our Dockerfile).

kubectl run defaults

Last but not least if we would like to simply start the pod in which our bin cowsay will run without any arguments, we’re going to leverage the command flag:


kubectl run cowsay --image=dejanualex/dockersay:1.0 --restart=Never --command -- cowsay

# check args and command
kubectl get po cowsay -ojsonpath="{.spec.containers[0].args}"
kubectl get po cowsay -ojsonpath="{.spec.containers[0].command}"
kubectl run command

It is rather straightforward to control how the app starts in the container using CMD, ENTRYPOINT, and ARGS.

# start container
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

# start pod
kubectl run NAME --image=image ... [--command] -- [COMMAND] [args...]

In terms of usage, one can say that:

  • ENTRYPOINT Dockerfile instruction corresponds to COMMAND passed to kubectl run
  • CMD Dockerfile instruction corresponds to ARG passed to kubectl run

Last but not least, some resources:

--

--

Dejanu Alex
Dejanu Alex

Written by Dejanu Alex

Seasoned DevOps engineer — Jack of all trades master of None

No responses yet