Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute for loop in docker container

Tags:

bash

docker

I use a docker container to perform a curl

docker run --rm --network=mynetwork tutum/curl for i in `seq 1 10`; do curl -s http://Url; done

But the output is -bash: syntax error near unexpected tokendo'`. How do I execute this in a proper way. I want to see the output without going inside the container or checking their logs.

For example this works:

docker run --rm -d -it --network=mynetwork tutum/curl /bin/sh
docker exec -it 4e8cb1e8c9fb bash
root@4e8cb1e8c9fb:/# for i in `seq 1 20`; do curl http://Url; done
curl: (6) Could not resolve host: url
curl: (6) Could not resolve host: url
curl: (6) Could not resolve host: url
curl: (6) Could not resolve host: url
curl: (6) Could not resolve host: url
curl: (6) Could not resolve host: url
...
like image 328
DenCowboy Avatar asked Feb 28 '17 13:02

DenCowboy


2 Answers

As Aaron points to, you need a shell inside the container to parse this line, rather than letting it get parsed by the same shell that parses the docker command. By default docker will pass commands to a /bin/sh entrypoint if you don't have one defined. And if you try escaping any shell characters on the docker cli, it "helps" you by also escaping them on the /bin/sh command line which prevents you from passing something like a ; through and getting it parsed by the shell there or quoting your script and having it parsed by the /bin/sh -c. If you quote the script without parsing it, you'll find that it looks for an executable with the full string's name.

The solution, as you've found, is to run a shell with /bin/sh -c "your script" as your command. Note that the script you run needs to be a single argument to /bin/sh -c, anything else will get passed as args to that script (which you can read with $0, $1, etc).

The resulting command should look like:

docker run --rm --network=mynetwork tutum/curl \
  /bin/sh -c 'for i in `seq 1 10`; do curl -s http://Url; done'
like image 87
BMitch Avatar answered Nov 18 '22 15:11

BMitch


Your problem happens because the ; after your for is parsed by the bash outside your container as a command separator, so these are the two commands you're executing :

  1. docker run --rm --network=mynetwork tutum/curl for i in `seq 1 10`
  2. do curl -s http://Url; done

The second is invalid, which is what the error you're getting means.

I think you could simply enclose the command you want to pass to docker in single-quotes :

docker run --rm --network=mynetwork tutum/curl 'for i in $(seq 1 10); do curl -s http://Url; done'

The use of single-quotes over double-quotes means that the command won't be expanded in your current shell but rather inside the docker component. It doesn't matter here as the only thing to expand is the seq 1 10 subshell which will obviously produce the same result on both environments.

like image 28
Aaron Avatar answered Nov 18 '22 13:11

Aaron