<p>I'm new to docker/k8s world... I was asked if I could deploy a container using args to modify the behavior (typically if the app is working in "master" or "slave" version), which I did. Maybe not the optimal solution but it works:</p>

<p>This is a simple test to verify. I made a custom image with a script inside:
role.sh:</p>

<pre><code>#!/bin/sh
ROLE=$1
echo "You are running "$ROLE" version of your app"
</code></pre>

<p>Dockerfile:</p>

<pre><code>FROM centos:7.4.1708

COPY ./role.sh /usr/local/bin
RUN chmod a+x /usr/local/bin/role.sh
ENV ROLE=""
ARG ROLE

ENTRYPOINT ["role.sh"]
CMD ["${ROLE}"]
</code></pre>

<p>If I start this container with docker using the following command:</p>

<pre><code>docker run -dit --name test docker.local:5000/test master
</code></pre>

<p>I end up with the following log, which is exactly what I am looking for:</p>

<pre><code>You are running master version of your app
</code></pre>

<p>Now I want to have the same behavior on k8s, using a yaml file. I tried several ways but none worked.</p>

<p>YAML file:</p>

<pre><code>apiVersion: v1
kind: Pod
metadata:
  name: master-pod
  labels:
     app: test-master
spec:
  containers:
    - name: test-master-container
      image: docker.local:5000/test
      command: ["role.sh"]
      args: ["master"]
</code></pre>

<p>I saw so many different ways to do this and I must say that I still don't get the difference between ARG and ENV.</p>

<p>I also tried with</p>

<pre><code> - name: test-master-container
   image: docker.local:5000/test
   env:
     - name: ROLE
       value: master
</code></pre>

<p>and</p>

<pre><code> - name: test-master-container
   image: docker.local:5000/test    
   args:
     - master
</code></pre>

<p>but none of these worked, my pods are always in CrashLoopBackOff state..
Thanks in advance for your help!</p>

IsKor
<p>In terms of specific fields:</p>

<ul>
<li>Kubernetes's <code>command:</code> matches Docker's "entrypoint" concept, and whatever is specified here is run as the main process of the container.  You don't need to specify a <code>command:</code> in a pod spec if your Dockerfile has a correct <code>ENTRYPOINT</code> already.</li>
<li>Kubernetes's <code>args:</code> matches Docker's "command" concept, and whatever is specified here is passed as command-line arguments to the entrypoint.</li>
<li>Environment variables in both Docker and Kubernetes have their usual Unix semantics.</li>
<li>Dockerfile <code>ARG</code> specifies a <em>build-time</em> configuration setting for an image.  The <a href="https://docs.docker.com/engine/reference/builder/#using-arg-variables" rel="noreferrer">expansion rules and interaction with environment variables</a> are a little odd.  In my experience this has a couple of useful use cases ("which JVM version do I actually want to build against?"), but <em>every</em> container built from an image will have the same inherited <code>ARG</code> value; it's not a good mechanism for <em>run-time</em> configuration.</li>
<li>For various things that could be set in either the Dockerfile or at runtime (<code>ENV</code> variables, <code>EXPOSE</code>d ports, a default <code>CMD</code>, especially <code>VOLUME</code>) there's no particular need to "declare" them in the Dockerfile to be able to set them at run time.</li>
</ul>

<p>There are a couple of more-or-less equivalent ways to do what you're describing.  (I will use <code>docker run</code> syntax for the sake of compactness.)  Probably the most flexible way is to have <code>ROLE</code> set as an environment variable; when you run the entrypoint script you can assume <code>$ROLE</code> has a value, but it's worth checking.</p>

<pre class="lang-sh prettyprint-override"><code>#!/bin/sh
# --&gt; I expect $ROLE to be set
# --&gt; Pass some command to run as additional arguments
if [ -z "$ROLE" ]; then
  echo "Please set a ROLE environment variable" &gt;&amp;2
  exit 1
fi
echo "You are running $ROLE version of your app"
exec "$@"
</code></pre>

<pre class="lang-sh prettyprint-override"><code>docker run --rm -e ROLE=some_role docker.local:5000/test /bin/true
</code></pre>

<p>In this case you can specify a default <code>ROLE</code> in the Dockerfile if you want to.</p>

<pre><code>FROM centos:7.4.1708
COPY ./role.sh /usr/local/bin
RUN chmod a+x /usr/local/bin/role.sh
ENV ROLE="default_role"
ENTRYPOINT ["role.sh"]
</code></pre>

<p>A second path is to take the role as a command-line parameter:</p>

<pre class="lang-sh prettyprint-override"><code>#!/bin/sh
# --&gt; pass a role name, then a command, as parameters
ROLE="$1"
if [ -z "$ROLE" ]; then
  echo "Please pass a role as a command-line option" &gt;&amp;2
  exit 1
fi
echo "You are running $ROLE version of your app"
shift        # drops first parameter
export ROLE  # makes it an environment variable
exec "$@"
</code></pre>

<pre class="lang-sh prettyprint-override"><code>docker run --rm docker.local:5000/test some_role /bin/true
</code></pre>

<p>I would probably prefer the environment-variable path both for it being a little easier to supply multiple unrelated options and to not mix "settings" and "the command" in the "command" part of the Docker invocation.</p>

<p>As to why your pod is "crashing": Kubernetes generally expects pods to be long-running, so if you write a container that just prints something and exits, Kubernetes will restart it, and when it doesn't stay up, it will <em>always</em> wind up in <code>CrashLoopBackOff</code> state.  For what you're trying to do right now, don't worry about it and look at the <code>kubectl logs</code> of the pod.  Consider setting the pod spec's <a href="https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy" rel="noreferrer">restart policy</a> if this bothers you.</p>
