You’ve heard, read or otherwise know that Docker containers are only meant to run a single command. When building an image it’s difficult (by design) to run multiple commands.
CMD turns into additional arguments to the command in
ENTRYPOINT. Despite what the name implies, you can’t run a command in
CMD if it comes after
If you list more than one command in
ENTRYPOINT "somecommand && othercommand" or ENTRYPOINT ["somecommand", "&&", "othercommand"]
you’ll be out of luck. The container will exit after the first command exits.
Exactly the same thing happens with
What if you need to initialize some sort of state at run time instead of one time during the build? I ran into this problem. I was running redundant web servers in a swarm. I wanted to download something from remote storage that would be the content of the static website on these servers. If the content changes, all I should have to do is “docker update –force” on the service and they will each restart with the new content. That would be easy enough to script from my Continuous Integration service. There are certainly many more scenarios requiring similar functionality.
The solution that I finally arrived at was to launch a shell script in
ENTRYPOINT. The script sets up the state I need then launches a shell with the arguments from
#!/bin/bash # #do some stuff # bash -c "$@"
If the build has
ENTRYPOINT ["somecommand.sh","nginx"] CMD ["-g 'no-daemon']
then at the end of somecommand.sh, bash will execute
nginx -g 'no daemon'. If you override CMD on the command line, then that will execute in place of
Of course you could run any command instead of nginx, that’s just my example. You could move nginx or your command to
CMD and specify only the setup script in
ENTRYPOINT if you want to have a default command that you can override from the command line. For example, if you want to debug some unexpected situation, you could have this in the build:
ENTRYPOINT ["somecommand.sh"] CMD ["nginx", "-g 'no-daemon']
and override the
/bin/bash from the command line so that you can poke around in the container.
In either scenario, if
CMD is not overridden from the command line, then the exact same arguments will get passed into somecommand.sh.