Bash command with $(subcommand) not working in make [duplicate] - bash

This question already has an answer here:
Makefile runs differently than shell command? (when using cat)
(1 answer)
Closed 1 year ago.
this is in my makefile:
docker-rm:
docker rm $(docker ps -aq)
and when I run it, I get this:
$ make docker-rm
docker rm
"docker rm" requires at least 1 argument.
See 'docker rm --help'.
Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...]
Remove one or more containers
make: *** [Makefile:15: docker-rm] Błąd 1
It is not that I have no containers to remove, because when I run docker command without makefile it works fine:
$ docker rm $(docker ps -aq)
463323e2bcf0
eef08f265387
2152910c6fe6
d7e7e9aff4e2
82875b1966c9
2d9295c8d32d
b9a45885e45d

You have to quote $ in Makefile's.
docker-rm:
docker rm $$(docker ps -aq)

Related

Jenkinsfile multiline sh continue on error

I want to do some Docker cleanup steps before a Jenkins build. This is the build step:
steps {
script {
try {
sh '''
docker container stop $(docker ps -q)
docker rm $(docker ps -aq)
docker rmi -f $(docker images -q)
docker build -f Dockerfile_build | tee buildlog.txt
'''
} catch(err) {
echo err.getMessage()
}
}
}
The first lines of the sh part may fail, causing the whole build to fail:
[Pipeline] sh
++ docker ps -q
+ docker container stop Error: you must provide at least one name or id
[Pipeline] echo
script returned exit code 125
However, that only means that there's no cleanup to do. I want to continue the build job, no matter how many of the first three lines fail. My question is whether I have to put each of them in its own try/catch block, or if there's a more concise way of saying "try these and ignore any errors".
If you want to continue your script even if you get errors for individual commands you can set +e in your script, but the sh step will never error out. You can also ignore first 3 commands and then error out the last command as well by setting -e and removing it. See the example below.
sh '''
#!/bin/bash
set +e
docker container stop $(docker ps -q)
docker rm $(docker ps -aq)
docker rmi -f $(docker images -q)
set -e
docker build -f Dockerfile_build | tee buildlog.txt
'''

How to bash into a docker container

trying to bash into container and do a for loop which simply performs a command (which works on a single file by the way). it even seems to echo the right command...what did I forget
Untitled
for pdf in *.pdf ;
do
docker run --rm -v "$(pwd):/home/docker" leofcardoso/pdf2pdfocr -g jpeg2000 -v -i '\'''$pdf''\''';
done
You can bash in a container with this commands:
To see the docker container id
docker container ls
To enter in bash inside a container.
docker exec -it CONTAINER_ID bash
First thing, you are not allocating tty in the docker run command and the docker container dies soon after converting files. Here is main process of container
#!/bin/bash
cd /home/docker
exec pdf2pdfocr.py "$#"
So, in this case, the life of this container is the life of exec pdf2pdfocr.py "$#" command.
As mentioned by #Fra, override the entrypoint and run the command manually.
docker run --rm -v "$(pwd):/home/docker" -it --entrypoint /bin/bash leofcardoso/pdf2pdfocr
but in the above run command, docker container will do not a thing and will just allocate the tty and the bash will open. So you can convert files inside your containers using docker exec and then run pdf2pdfocr.py -g jpeg2000 -v -i mypdf.pdf
So, if you want to run with override entry point then you can try.
docker run -it --rm --entrypoint /bin/bash -v "$(pwd):/home/docker" leofcardoso/pdf2pdfocr -c "pdf2pdfocr.py -g jpeg2000 -v -i mypdf.pdf"
or with the bash script
#!/bin/bash
for pdf in *.pdf ;
do
echo "converting $pdf"
docker run -it --rm --entrypoint /bin/bash -v "$(pwd):/home/docker" leofcardoso/pdf2pdfocr -c "pdf2pdfocr.py -g jpeg2000 -v -i $pdf"
done
But the container will die after completing the conversion.

Stop and remove docker container with force ignore

How can I delete a docker container with force ignore that means if there is no running docker container it should do nothing and if there is a running docker container with the name then it should stop and remove that container.
I am executing the following code to stop and remove the container.
docker rm -f CONTAINER_NAME || true
If there is a running container then everything works fine, however, if there is no container then the following error is thrown:
Error: No such container: CONTAINER_NAME
Is there something like --force ignore? I need this behaviour in order to include it in an automated Makefile.
try this exit code will be 1:
docker rm -f CONTAINER_NAME 2> /dev/null
this with exit code 0:
docker rm -f CONTAINER_NAME 2> /dev/null || true
Makefiles have built-in support to ignore errors on a specific command by adding a dash before the command.
rmDocker:
-docker rm -f CONTAINER_NAME
#echo "Container removed!"
You'll still see the error message, but the makefile will ignore the error and proceed anyway.
Output:
docker rm -f CONTAINER_NAME
Error: No such container: CONTAINER_NAME
make: [rmDocker] Error 1 (ignored)
Container removed!
Reference: GNU Make Manual
You can add OR true value, as per below:
One Container
docker rm -f CONTAINER_1 || true
Multiple Containers
(docker rm -f CONTAINER_1 || true) && (docker rm -f CONTAINER_2 || true)
I prefer
docker container inspect CONTAINER_NAME &>/dev/null && docker rm -f CONTAINER_NAME
Solution based on this answer: docker container inspect sets return-code to 1 if container does not exist, else sets it to 0, so docker rm will be executed, too.
As an alternative you can run container with docker run --rm. Container will remove itself once stopped.

Jenkins shell dont interpret $ variables

I am trying to deploy a nodejs app inside docker container on a prod machine using jenkins.
I have this shell :
ssh -tt vagrant#10.2.3.129<<EOF
cd ~/app/backend
git pull
cat <<EOM >./Dockerfile
FROM node:8
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD [ "npm", "start" ]
EOM
docker build -t vagrant/node-web-app .
docker kill $(docker ps -q)
docker rm $(docker ps -a -q)
docker run -p 3000:3000 -d vagrant/node-web-app
exit
EOF
this will connect via ssh to prod machine and create a Dockerfile then build and run image. but it failed.
and this a part of the jenkins logs:
Successfully built 8e5796ea9846
vagrant#ubuntu-xenial:~$ docker kill
"docker kill" requires at least 1 argument.
See 'docker kill --help'.
Usage: docker kill [OPTIONS] CONTAINER [CONTAINER...]
Kill one or more running containers
vagrant#ubuntu-xenial:~$ docker rm
"docker rm" requires at least 1 argument.
See 'docker rm --help'.
Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...]
Remove one or more containers
vagrant#ubuntu-xenial:~$ docker run -p 3000:3000 -d vagrant/node-web-app
0cc8b5b67f70065ace03e744500b5b66c79941b4cb36d53a3186845445435bb5
docker: Error response from daemon: driver failed programming external connectivity on endpoint stupefied_margulis (d0e4cdd5642c288a31537e1bb8feb7dde2d19c0f83fe5d8fdb003dcba13f53a0): Bind for 0.0.0.0:3000 failed: port is already allocated.
vagrant#ubuntu-xenial:~$ exit
logout
Connection to 10.2.1.129 closed.
Build step 'Execute shell' marked build as failure
Finished: FAILURE
It seems like jenkins dont execute the " $(docker ps -q) "
and " $(docker ps -a -q) "
so docker kill and docker rm got 0 arguments.
But why this happen ?
I found the issue,
Just I have to replace "$" with "\$" .
this solve the problem.

Is there a flag to silence docker when an empty list is provided

Such a feature is useful when running multiple docker commands in one that follow this pattern:
docker do_smth $(docker query_smth)
For example:
docker stop $(docker ps -q)
or
docker rm $(docker ps -a -q)
or
docker network rm $(docker inspect ... --format ...)
If the inner docker command returns an empty list, the outer command will fail because and will display the help.
"docker stop" requires at least 1 argument.
See 'docker stop --help'.
Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...] [flags]
Stop one or more running containers
Is there a way to silence docker or make docker not complain on empty lists? Something like: "Kill everybody. If there is no one, job done."
This would be similar to mkdir -p exiting_directory vs mkdir exiting_directory where the former will not complain if the directories exist.
For scripting where the result may be empty, I prefer to use xargs --no-run-if-empty:
docker ps -aq | xargs --no-run-if-empty docker rm

Resources