10

I have a bash alias loaded into a Docker container, in /etc/bash.bashrc. It functions as a shortcut to a commandline PHP script. This is convenient, since anyone can use that alias directly after one logs into the container, with:

$ docker exec -it my-container bash

However, I would also like to be able to use this alias in one-off commands without logging in, like:

$ docker exec -it my-container my-alias

I have tried different variations, such as defining the alias in other places than /etc/bash.bashrc, but I keep running into this error:

rpc error: code = 2 desc = oci runtime error: exec failed: exec: "my-alias": executable file not found in $PATH

Other suggestions I find on the web did not do the trick, so far. Anyone?

5 Answers5

6

It doesn't due to limitations due to aliases being meant to be used interactively. You can probably hack around this but the easiest solution is by far to simply make your "alias" into a script and place it in /bin.

Dockerfile

RUN echo '#! /bin/sh'                >> /bin/mycommand
RUN echo 'echo "running mycommand!"' >> /bin/mycommand
RUN chmod u+x /bin/mycommand

Then it works as expected

docker exec -it f3a34 mycommand # => running mycommand!
Pithikos
  • 1,654
2

Aliases are mostly useful when you want to shorten part of a commonly used command which takes variable arguments. In a ruby dev context that might be creating an alias like

alias be="bundle exec"

because who wants to type out bundle exec all the time?

If what you really want is a shorter version of a longer command with static arguments then you should create a script anyway. With a script, it will always be available and not be dependent on sourcing particular profiles in particular contexts (which you can basically never rely on).

A more comman case (like that above) is when you use an alias because you want to effortless string arguments on to the end of the alias. For instance

$ be rails server

or

$ be rake db:migrate

In both cases, i don't want to have to type out more than I need to. With just a dash of bash, however, you can achieve the same thing in a more versatile solution.

Similar to some of the above answers, create a file - /usr/local/bin/be in this example. This assumes that /usr/local/bin is included in your PATH.

#!/usr/bin/env bash

bundle exec "$@"

followed up with (possibly with sudo)

$ chmod +x /usr/local/bin/be

This is a bit of a naive example, and requires that both ruby and the bundler gem have been installed, but the thing to notice is "$@" which let's you pass in a variable number of arguments into the script. Thus, you get the ergonomics of the alias, but with a command that is always available and not context dependent.

I find this approach particularly helpful when working with containers. Hope it helps.

1

If you have a script file under your container just add a these RUN.

RUN cat /workdir/bin/doit.sh >> /bin/doit
RUN chmod u+x /bin/doit

to run it:

docker exec -it container_name doit

doit.sh sample

#!/usr/bin/env bash
python manage.py $@
0

It took me a slightly different approach eventually, because I haven't managed to get it to work with the bash.bashrc strategy. @joat is right, an alias is probably an unfortunate combination with the partial execution of a command line (with docker exec).

In the end, I injected a script (in my case through PHP Composer) into the image. In my case by mounting my local directory, although that shouldn't matter. Then I add the path to this script in my Dockerfile through an environment variable:

ENV PATH $PATH:./vendor/bin

This makes the script globally available at runtime.

I do consider it a workaround, still, so interested to hear from anyone who actually got regular aliases to work at docker exec runtime.

0

I had this problem and I solved it by wrapping the command I wanted to execute inside a temporary shell, in the example you have it would be done like this:

$ docker exec -it my-container sh -l -c "my-alias"

(the -l flag is only needed if your aliases are only available in login shells, which is my case)

It does make it more verbose, but you can always create an alias or a function to wrap this.