Quotes in scripts results in “unterminated quoted string” - docker

I'm trying to use scripts of Composer with quotes to pass an environment variable to the command that will be run with Docker.
I use sh -c 'A=b [command]' in order to run a command with an environment variable.
Here is a minimal example:
{
"scripts": {
"docker-run": "docker run --tty composer:2",
"docker-version": "#docker-run composer --version",
"docker-version2": "#docker-run sh -c 'CONSTANT=6.2.x-dev composer --version'"
}
}
When I run it, the script docker-version works as expected:
$ composer run-script docker-version
> docker run --tty composer:2 'composer' '--version'
Composer version 2.3.10 2022-07-13 15:48:23
But the script docker-version2 fails. The simple quotes are escaped and it breaks the command:
$ composer run-script docker-version2
> docker run --tty composer:2 'sh' '-c' ''\''CONSTANT=6.2.x-dev' 'composer' '--version'\'''
composer: line 0: syntax error: unterminated quoted string
Script docker run --tty composer:2 handling the docker-run event returned with error code 2
Script #docker-run sh -c 'CONSTANT=6.2.x-dev composer --version' was called via docker-version2

You can set environment variables with env command.
docker-run env CONSTANT=6.2.x-dev composer --version

Related

docker exec error with sh command returns "Unterminated quoted string"

If I run two commands:
export TMPCMD='sh -c "if [ `uname -m` = aarch64 ]; then echo 0; fi"'
docker exec container sh -c "..."
It produces an error:
[: 1: [: Syntax error: Unterminated quoted string
How might I fix this?
So far I have tried I could not find to execute like docker exec container sh -c "..."
Alternatively, You can create a shell script file name example Stackoverflow.sh
Dockerfile
FROM nginx:latest
COPY Stackoverflow.sh bin/Stackoverflow.sh
RUN chmod u+x bin/Stackoverflow.sh
RUN bin/Stackoverflow.sh
docker exec -it <conyainer-ID> bash
root#<conyainer-ID>:/bin# ./Stackoverflow.sh
#=>Logging-Container has started.
#=>Check uname -m command.
#=>0
Hope this help you.

Shell script unknown operand alpine

I am running into a problem where my shell script doesn't work if the variable is not set/set to empty string.
For this I am using the alpine image
docker run -dt alpine
docker exec -it <container> sh
Here is the problematic code:
x=""
sh -c "if [ "$x" != "required" ]; then sed; fi"
When x is not set, I get the error:
sh: required: unknown operand
This seems to only be the problem on an empty string. If I set x="lkajsdfasl", it will work just fine.
This just breaks down on an empty string/not set.
Due to the way my docker-compose is setup, I can only use sh and have to use sh -c
It's a quoting issue. Use single quotes around the command like this
sh -c 'if [ "$x" != "required" ]; then sed; fi'

Jenkins Pipeline ${params.Environment} bad substitution

I am trying to send commands to a docker container within docker run via a Jenkins pipeline.
The Jenkins machine is at a different server and the docker image is in a different server.
When I hard code the environment param, the scripts execute as expected. But whenever I try to replace it with the params, it errors out saying :
bash: ${params.Environment} bad substitution
This is my pipeline script
pipeline {
agent any
parameters {
choice(
name: 'Environment',
choices: ['qa','dev'],
description: 'Passing the Environment'
)
}
stages {
stage('Environment') {
steps {
echo " The environment is ${params.Environment}"
}
}
stage('run') {
steps {
sh 'ssh 10.x.x.x \'sudo docker run --name docker_container_name docker_image_name sh -c "cd mytests ; pip3 install -r requirements.txt ; python3 runTests.py -env ${params.Environment} "\''
}
}
}
}
The sh command's parameters needs to have double quotes, or triple double quotes.
sh """ssh 10.x.x.x 'sudo docker run --name docker_container_name docker_image_name sh -c "cd mytests ; pip3 install -r requirements.txt ; python3 runTests.py -env ${params.Environment} "'"""
In the Groovy language used by pipeline scripts, single-quoted strings don't do any interpolation at all, so the ${params.Environment} string gets passed on as-is to the shell. Double-quoted strings do perform interpolation, so the Groovy engine substitutes ${params.Environment} before invoking the shell.
(You might look at the native support for Using Docker with Pipeline which can avoid the ssh 'sudo "..."' wrapping, though it requires Jenkins be able to run Docker itself on the worker nodes.)

How can I use a dredd docker image interactively?

I would like to use this docker container apiaryio/dredd instead of the npm package dredd. I am not familiar with running and debugging npm based docker images. How can I run the basic usage example of the npm package "Quick Start" section
$ dredd init
$ dredd
if I have a Swagger file instead of the api-description.apib in $PWD/api/api.yaml or $PWD/api/api.json?
TL;DR
Run dredd image as a command line. Dredd Image at Docker Hub
docker run -it -v $PWD:/api -w /api apiaryio/dredd init
[Optional] Turn it into a script:
#!/bin/bash
echo '***'
echo 'Root dir is /api'
export MYIP=`ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'`
echo 'Host ip is: ' $MYIP
echo 'Configure URL of tested API endpoint: http://api-srv::<enpoint-port>. Set api-srv to point to your server.'
echo 'This script will set api-srv to docker host machine - ' $MYIP
echo '***'
docker run -it --add-host "api-srv:$MYIP" -v $PWD:/api -w /api apiaryio/dredd dredd $1
[Optional] And put this script in a folder that is in your PATH variable and create an alias for short it
alias dredd='bash ./scripts/dredd.sh'
Code at Github gist.

How to workaround "the input device is not a TTY" when using grunt-shell to invoke a script that calls docker run?

When issuing grunt shell:test, I'm getting warning "the input device is not a TTY" & don't want to have to use -f:
$ grunt shell:test
Running "shell:test" (shell) task
the input device is not a TTY
Warning: Command failed: /bin/sh -c ./run.sh npm test
the input device is not a TTY
Use --force to continue.
Aborted due to warnings.
Here's the Gruntfile.js command:
shell: {
test: {
command: './run.sh npm test'
}
Here's run.sh:
#!/bin/sh
# should use the latest available image to validate, but not LATEST
if [ -f .env ]; then
RUN_ENV_FILE='--env-file .env'
fi
docker run $RUN_ENV_FILE -it --rm --user node -v "$PWD":/app -w /app yaktor/node:0.39.0 $#
Here's the relevant package.json scripts with command test:
"scripts": {
"test": "mocha --color=true -R spec test/*.test.js && npm run lint"
}
How can I get grunt to make docker happy with a TTY? Executing ./run.sh npm test outside of grunt works fine:
$ ./run.sh npm test
> yaktor#0.59.2-pre.0 test /app
> mocha --color=true -R spec test/*.test.js && npm run lint
[snip]
105 passing (3s)
> yaktor#0.59.2-pre.0 lint /app
> standard --verbose
Remove the -t from the docker run command:
docker run $RUN_ENV_FILE -i --rm --user node -v "$PWD":/app -w /app yaktor/node:0.39.0 $#
The -t tells docker to configure the tty, which won't work if you don't have a tty and try to attach to the container (default when you don't do a -d).
This solved an annoying issue for me. The script had these lines:
docker exec **-it** $( docker ps | grep mysql | cut -d' ' -f1) mysql --user= ..... > /var/tmp/temp.file
mutt -s "File is here" someone#somewhere.com < /var/tmp/temp.file
The script would run great if run directly and the mail would come with the correct output. However, when run from cron, (crontab -e) the mail would come with no content. Tried many things around permissions and shells and paths etc. However no joy!
Finally found this:
*/20 * * * * scriptblah.sh > $HOME/cron.log 2>&1
And on that cron.log file found this output:
the input device is not a TTY
Search led me here. And after I removed the -t, it's working great now!
docker exec **-i** $( docker ps | grep mysql | cut -d' ' -f1) mysql --user= ..... > /var/tmp/temp.file

Resources