25

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?

2
  • 1
    Did you try: docker exec [id] /bin/bash -c 'cd /var/www/project && composer install' Commented Feb 2, 2017 at 18:07
  • thanks dude, i didn't saw your comment but it worked! Commented Feb 3, 2017 at 9:03

5 Answers 5

40

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'
Sign up to request clarification or add additional context in comments.

2 Comments

Hi, i tried your command and it's not working, that's the error shown: rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:247: starting container process caused "exec: \"cd /var/www/project && composer install\": stat cd /var/www/project && composer install: no such file or directory" obviously, the directory does exist so i can access manually.
@Adrià Yes, I hadn't thought about cd being the command here. I updated the answer, though it more or less now matches the answer you yourself posted (but with more explanation of why it works).
4

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'

Comments

3

The other answers are fine if you want to run 2 arbitrary commands. But if the first command is simply cd, then you should use the -w option to set the working directory instead.

docker exec -w {dir} {container} {commands}

So in your example:

docker exec -w /var/www/project {container} composer install

Comments

2

as Nehal J Wani said in his commentary, the correct syntax is the following:

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

many thanks!

Comments

0

I would like to add my example here because it is a bit more complex then the ones thate were shown above. This example also illustrates on how to find a container id that should be used in the docker exec command.

I needed to execute a composite docker exec command against docker container over ssh. I managed to achieve this in 2 steps:

-definition of the variable that contains a command expored as an environment variable

-ssh command that runs it

  1. environment varialbe definition:

    export COMMAND="bash -c 'php bin/console --version && composer --version'"

  2. ssh command that runs on a remote system:

ssh -t -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i keyfile.pem [email protected] 'docker exec docker ps|grep php|grep api|grep -v cron|awk '"'"'{print $1}'"'"' '$COMMAND

As you can see I left the command out of the single quotes to pass its actual value to the SSH process

The output of the command execution is:

Warning: Permanently added '111.222.111.222' (ECDSA) to the list of known hosts.
Cannot load Xdebug - it was already loaded
Symfony 4.3.5 (env: dev, debug: true)
Cannot load Xdebug - it was already loaded
Composer version 1.9.1 2019-11-01 17:20:17
Connection to 111.222.111.222 closed.

If you wish to execute this command in a single line you can use a bit modified version of my first example:

COMMAND="bash -c 'php bin/console --version && composer --version'" ssh -t -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i keyfile.pem [email protected] 'docker exec `docker ps|grep php|grep api|grep -v cron|awk '"'"'{print $1}'"'"'` '$COMMAND

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.