diff --git a/content/docker_entrypoint.rst b/content/docker_entrypoint.rst new file mode 100644 index 0000000000000000000000000000000000000000..9710ef61b33abab6dc89923d21e2383fbda6cd86 --- /dev/null +++ b/content/docker_entrypoint.rst @@ -0,0 +1,96 @@ +Expanding variables and shell expressions in parameters to Docker entrypoint +############################################################################ + +:date: 2016-06-13 +:summary: Expanding variables and shell expressions in parameters to Docker entrypoint + +A known best practice when creating Docker images is when you need to run +commands in runtime before starting the actual application/ daemon is to create +an entrypoint script and pass the command as parameters in the :code:`CMD` +instruction. Another best practice is to exec the final command so it would be +PID 1 and receive the signals passed to it. Let's create a small example. Here's +the :code:`Dockerfile`: + +.. code:: + + FROM alpine + COPY entrypoint.sh /entrypoint.sh + RUN chmod +x entrypoint.sh + ENTRYPOINT ["/entrypoint.sh"] + ENV var value + CMD ["echo", "$var"] + +And the :code:`entrypoint.sh` script: + +.. code:: shell + + #!/bin/sh + set -eu + # Perform any needed tasks here. + exec $@ + +Now let's build and run this container: + +.. code:: shell + + $ docker build --tag entrypoint . + Sending build context to Docker daemon 28.67 kB + Step 0 : FROM alpine + ---> 5f05d2ba9e65 + Step 1 : COPY entrypoint.sh /entrypoint.sh + ---> f59f4d7f3546 + Removing intermediate container 27ca546c6b6c + Step 2 : ENTRYPOINT /entrypoint.sh + ---> Running in 98c65b63948a + ---> 1de45b33021b + Removing intermediate container 98c65b63948a + Step 3 : ENV var value + ---> Running in 133a8781f0ac + ---> bba451334fb2 + Removing intermediate container 133a8781f0ac + Step 4 : CMD echo $var + ---> Running in e8436c6c3202 + ---> a49d9b335b74 + Removing intermediate container e8436c6c3202 + Successfully built a49d9b335b74 + $ docker run entrypoint + $var + +As we can see the variable :code:`var` wasn't expanded to it's content. After a +bit of head scratching, The following simple change was made to the entrypoint +script. + +.. code:: shell + + #!/bin/sh + set -eu + # Perform any needed tasks here. + eval "exec $@" + +The change is to first evaluate the expression (expanding any variable and +expression found), then :code:`exec` it. The outcome is what you'd expect. + +.. code:: + + $ docker build --tag entrypoint . + Sending build context to Docker daemon 28.67 kB + Step 0 : FROM alpine + ---> 5f05d2ba9e65 + Step 1 : COPY entrypoint.sh /entrypoint.sh + ---> b874d862999d + Removing intermediate container fb6483ff00e3 + Step 2 : ENTRYPOINT /entrypoint.sh + ---> Running in 82adf0b2c4c7 + ---> 6674f336c5e1 + Removing intermediate container 82adf0b2c4c7 + Step 3 : ENV var value + ---> Running in 599f3f98c11d + ---> 980f1e1e1ad5 + Removing intermediate container 599f3f98c11d + Step 4 : CMD echo $var + ---> Running in e29f1948480a + ---> e27fd79143f8 + Removing intermediate container e29f1948480a + Successfully built e27fd79143f8 + $ docker run entrypoint + value