Execute for loop in docker container

11,457

Solution 1

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'

Solution 2

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.

Share:
11,457
DenCowboy
Author by

DenCowboy

Updated on June 27, 2022

Comments

  • DenCowboy
    DenCowboy almost 2 years

    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
    ...
    
  • DenCowboy
    DenCowboy about 7 years
    Thanks, But now I get something like: done\": executable file not found in $PATH" (with the single quotes). Without the single quotes and using your $() it's just the same error as before
  • Aaron
    Aaron about 7 years
    @DenCowboy $() and backticks have the same effect, I just switched to the more modern $() because it has a few advantages such as the possibility of nesting, but it shouldn't matter in your case. Could you maybe edit the exact error message in your question? Right now it looks like you've got an extra double quote just after the done keyword which makes it misunderstood, but I don't see what could cause this
  • DenCowboy
    DenCowboy about 7 years
    ... tutum/curl /bin/bash -c 'for i... this worked. You can edit if you want. found it thanks to your answer
  • Aaron
    Aaron about 7 years
    Hmm I'd rather not edit my answer without understanding why it worked. I'll try to understand what went on here, but if I don't edit in a few hours you might as well just upvote my answer, post your own and accept it.
  • Aaron
    Aaron about 7 years
    Looks like docker run uses /bin/sh -c to execute the commands it's provided, so either you made a typo when you first tried with just the command, something adds an extra ", your url contains a quote, or the command is valid in bash but not in sh. Also /bin/sh -c 'for i in seq 1 10; do echo $i;done' works just fine, so I doubt the last one