Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute two commands with docker exec

Tags:

I'm trying to do two commands in docker exec. Concretely, I have to run a command inside a specific directory. I tried this, butit didn't work:

docker exec [id] -c 'cd /var/www/project && composer install'

Parameter -c is not detected. I also tried this:

docker exec [id] cd /var/www/project && composer install

But the command composer install is executed after the docker exec command. How can I do it?

like image 980
BraveAdmin Avatar asked Feb 02 '17 17:02

BraveAdmin


People also ask

How do I run multiple commands in Docker exec?

In order to execute multiple commands using the “docker exec” command, execute “docker exec” with the “bash” process and use the “-c” option to read the command as a string. Note : simple quotes may not work in your host terminal, you will have to use double quotes to execute multiple commands.

Can Dockerfile run 2 commands?

There can only be one CMD instruction in a Dockerfile. If you list more than one CMD then only the last CMD will take effect. If CMD is used to provide default arguments for the ENTRYPOINT instruction, both the CMD and ENTRYPOINT instructions should be specified with the JSON array format.

What is the difference between docker run and Docker exec?

Docker Run vs Docker Exec! This is a fairly common question – but has a simple answer! In short, docker run is the command you use to create a new container from an image, whilst docker exec lets you run commands on an already running container! Easy!


2 Answers

In your first example, you are giving the -c flag to docker exec. That's an easy answer: docker exec does not have a -c flag.

In your second example, your shell is parsing this into two commands before Docker even sees it. It is equivalent to this:

if docker exec [id] cd /var/www/project
then
    composer install
fi

First, the docker exec is run, and if it exits 0 (success), composer install will try to run locally, outside of Docker.

What you need to do is pass both commands in as a single argument to docker exec using a string. Then they will not be interpreted by a shell until already inside the container.

docker exec [id] "cd /var/www/project && composer install"

However, as you noted in the comments, this also does not work. That's because cd is a shell builtin, and doesn't exist on its own. Trying to execute it as the initial command will fail. So the next step is to hand this off to a shell to execute.

docker exec [id] "bash -c 'cd /var/www/project && composer install'"

And finally, at this point the && has moved into an inner set of quote marks, so we don't really need the quotes around the bash command... you can drop them if you prefer.

docker exec [id] bash -c 'cd /var/www/project && composer install'
like image 137
Dan Lowe Avatar answered Oct 19 '22 01:10

Dan Lowe


Everything after the container id is the command to run, so in the first example -c isn't an option to exec, but a command docker tries to run and fails since that command doesn't exist.

Most likely you found this syntax from a docker run command where the entrypoint was set to /bin/sh. However, exec bypasses the entrypoint, so you need to include the full command to run. As others have pointed out, that command includes a shell like bash or in the below example, sh:

docker exec [id] /bin/sh -c 'cd /var/www/project && composer install'
like image 36
BMitch Avatar answered Oct 19 '22 00:10

BMitch