How do I override the entrypoint and pass Bash commands as a string?

Viewed 3249

I don't want to modify the Dockerfile.

I want to override the entrypoint and run arbitrary commands but this is not working for me:

docker run -it --entrypoint /bin/bash myimage bash -c "echo aaaa &"

I get /bin/bash: /bin/bash: cannot execute binary file

I want to be able to immediately start a background job before entering the container interactively- again without modifying the Dockerfile.

1 Answers

When Docker launches a container, it combines the "entrypoint" and "command" parts together into a single command. The docker run --entrypoint option only takes a single "word" for the entrypoint command.

So, say you need to run some command --with an-arg. You need to

  1. Break this into words
  2. Pass the first word as docker run --entrypoint, before the image name
  3. Pass the remaining words as the command part, after the image name.
# some command --with an-arg
docker run \
  --entrypoint some
  image-name \
  command --with an-arg

# ls -al /
docker run --rm \
  --entrypoint /bin/ls
  image-name \
  -al /

# bash -c "echo aaaa"
docker run --rm \
  --entrypoint /bin/bash \
  image-name \
  -c 'echo aaaa'

This construct is kind of awkward. If you control the image, I tend to recommend making the image's CMD be a complete command, and either omitting ENTRYPOINT or making it be a wrapper that takes a complete command as arguments (for example, a shell script that ends in exec "$@").

# Hard to replace with an alternate command:
# ENTRYPOINT python3 ./manage.py runserver

# Better:
CMD python3 ./manage.py runserver
# Takes a complete command as arguments
# (MUST use JSON-array form)
ENTRYPOINT ["bundle", "exec"]

# Can be overridden at runtime
# (But whatever you supply will run in a Ruby Bundler context)
CMD ["rails", "server", "-b", "0.0.0.0"]
Related