Prevent Makefile command to print error after exiting a Docker container - makefile

Consider the following Makefile
bash:
docker run -it --rm bash:4.4
When I run the Makefile command, attach to the Docker container, create an error on the console and exit, I get a "make: *** [bash] Error 127":
➜ make bash
docker run -it --rm bash:4.4
bash-4.4# peng
bash: peng: command not found
bash-4.4# exit
exit
make: *** [bash] Error 127
When I simply run the same command without the Makefile context - there is no error.
Is there a way I can prevent this error from getting printed after exiting the Docker container? This is a minimal example - we would like to use Makefile for running Docker related tasks in a development setup.

Make will run the recipe you give it in a shell. If the shell exits with a non-0 error code, make thinks that the operation failed and prints that message. So, all you have to do is make sure that the recipe doesn't fail. For example:
bash:
docker run -it --rm bash:4.4 || true
Now, if the docker command exits with a non-0 code the || true will be run and exit with a success code.
Alternatively you could prefix the recipe with - which will still print a message but make will ignore the error:
bash:
-docker run -it --rm bash:4.4
Just be aware, that if you do this you have no way to inform make that the command you tried to run didn't succeed.

Related

How to run a bash script from a Dockerfile on a Mac

I'm trying to run a bash script from a Docker Image on a Mac. Here is my Dockerfile
FROM bash
ADD app.sh /
ENTRYPOINT ["/bin/bash", "/app.sh"]
Error
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "/bin/bash": stat /bin/bash: no such file or directory: unknown.
This is a simple exercise in creating Docker Images where I need to execute app.sh when I run docker run.
Any idea what I'm doing wrong?
According to your error message, the file /bin/bash does not exist in your Docker image. Why is this?
The bash image puts the bash executable at /usr/local/bin/bash. Here's how I determined this:
$ docker run -it bash
bash-5.1# which bash
/usr/local/bin/bash
bash-5.1#
I ran the bash image with -it to make it interactive, then used the which command to give me the full path to bash, which is /usr/local/bin/bash.
For that reason, you need to change your Dockerfile like this:
FROM bash
ADD app.sh /
ENTRYPOINT ["/usr/local/bin/bash", "/app.sh"]

What that this line means in a make file `DOCKER := $(shell command -v docker)`

$(shell command -v docker) What command means? it's being used in a Makefile.
I saw this in a github repository that I'm trying to understand.
It looks like it's setting a variable with a command to test if docker is installed, and stop the build if its not, the problem is this that I don't have a command installed and I tryed to install command in ubuntu but it can't find it, looking on internet how to install this commad command seems realy difficult because of its name, how to install command in linux/ubuntu didn't bring anything useful, also search for this being using on Makefiles trying to get some clue but nothing so far.
Running the build command seems to work becuse it build the image and yes I have docker installed, but still getting that message in the terminal make: command: Command not found
Any idea?
make build output (trucated):
$ make build
make: command: Command not found
make: command: Command not found
docker build -t codelytv/typescript-ddd-skeleton:dev .
Sending build context to Docker daemon 1.023MB
.....
This is the Makefile:
.PHONY = default deps build test start clean start-database
IMAGE_NAME := codelytv/typescript-ddd-skeleton
SERVICE_NAME := app
# Test if the dependencies we need to run this Makefile are installed
DOCKER := $(shell command -v docker)
DOCKER_COMPOSE := $(shell command -v docker-compose)
deps:
ifndef DOCKER
#echo "Docker is not available. Please install docker"
#exit 1
endif
ifndef DOCKER_COMPOSE
#echo "docker-compose is not available. Please install docker-compose"
#exit 1
endif
default: build
# Build image
build:
docker build -t $(IMAGE_NAME):dev .
# Run tests
test: build
docker-compose run --rm $(SERVICE_NAME) bash -c 'npm run build && npm run test'
# Start the application
start: build
docker-compose up $(SERVICE_NAME) && docker-compose down
# Clean containers
clean:
docker-compose down --rmi local --volumes --remove-orphans
# Start mongodb container in background
start_database:
docker-compose up -d mongo
What it means is that the person who wrote this makefile wasn't careful enough to write it in a portable way.
The command command is part of the shell (which is why you won't see it if you look for it in the GNU make manual). Not only that, it's part of the bash shell specifically: it is not a POSIX sh standard command. The bash man page says:
command [-pVv] command [arg ...]
Run command with args suppressing the normal shell function
lookup. Only builtin commands or commands found in the PATH are
executed.
Basically, running command docker ... means that any shell alias or function named docker is ignored, and only the actual docker command is run.
However, GNU make always runs /bin/sh as its shell, including for both recipes and for the $(shell ...) function.
So, if you're on a system (such as Red Hat or CentOS or Fedora GNU/Linux) where the /bin/sh is a link to the bash shell, then the above command will work.
However, if you're on a system (such as Debian or Ubuntu GNU/Linux) where the /bin/sh is a link to a simpler POSIX shell such as dash, then the above command will not work.
In reality, this is not needed because there won't be any shell aliases or functions defined in the shell that make invokes, regardless. However, if the author wants to use bash shell features in their makefiles and allow them to work, they also need to tell make to use bash as its shell, by adding this to their makefile:
SHELL := /bin/bash
(of course this assumes that the user has a /bin/bash on their system, but...)

Command Not Found with Dockerfile CMD

I have a Dockerfile that uses
CMD ['/usr/local/bin/gunicorn', '-b 0.0.0.0:8000', 'myapp.wsgi']
But when I run the container using docker run --rm myimage:latest I get an error:
/bin/sh: 1: [/usr/local/bin/gunicorn,: not found
Yet, when I run docker run --rm -it myimage:latest /bin/bash to go into the container, I can see that gunicorn runs, and running which gunicorn returns the correct path for gunicorn. Why is it failing to run?
Similarly, I planned on adding
ENTRYPOINT ['/entrypoint.sh']
to my Dockerfile, but when I run that, I get the error
/bin/sh: 1: /bin/sh: [/entrypoint.sh]: not found
The entrypoint.sh file contains:
#! /bin/bash
echo 'Starting app...'
cd /app || exit;
python manage.py migrate;
So why does it keep saying command not found when all the commands are there?
The issue here is the quotes. Use double " quotes.
From Docker Documentation:
The exec form is parsed as a JSON array, which means that you must use
double-quotes (“) around words not single-quotes (‘).
This is applicable for other instructions such as RUN, LABEL, ENV, ENTRYPOINT and VOLUME.

Error on zsh: docker: Error response from daemon: invalid volume specification

I have a bash script that composes a docker run command chaining different volumes with -v:
VOL_ONE="-v $PWD/path/one:/home/docker/app/path/one"
VOL_TWO="-v $PWD/path/two:/home/docker/app/path/two"
RUN_VOLUMES="$VOL_ONE $VOL_TWO"
docker run --rm -it $RUN_VOLUMES docker.myserver.io/path/to/image:latest command
It runs absolutely fine when I use bash to run it.
However when I run the exact same script using zsh instead of bash I get:
docker: Error response from daemon: invalid volume specification
I've tried both on Ubuntu and macOS, getting the exact same problem.
Does this work:
VOL_ONE=(-v $PWD/path/one:/home/docker/app/path/one)
VOL_TWO=(-v $PWD/path/two:/home/docker/app/path/two)
RUN_VOLUMES=(${VOL_ONE[*]} ${VOL_TWO[*]})
echo docker run --rm -it ${RUN_VOLUMES[*]} docker.myserver.io/path/to/image:latest command
If it prints the desired result, remove the echo.

Kubectl: get a shell to a running container under Windows

I'm trying to log into running container using Kubectl, according to instructions in https://kubernetes.io/docs/tasks/debug-application-cluster/get-shell-running-container/, but I'm failing miserably:
kubectl exec -it mycontainer -- /bin/bash
Unable to use a TTY - input is not a terminal or the right kind of
file rpc error: code = 2 desc = oci runtime error: exec failed:
container_linux.go:247: starting container process caused "exec:
\"D:/Applications/Git/usr/bin/bash\": stat
D:/Applications/Git/usr/bin/bash: no such file or directory"
command terminated with exit code 126
It looks like kubectl tries to exec bash on my machine, which is totally not what I want to achieve.
I can exec commands without spaces:
$ kubectl exec mycontainer 'ls'
lib
start.sh
But with not:
$ kubectl exec mycontainer 'ls .'
rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:247: starting container process caused "exec: \"ls .\": executable file not found in $PATH"
command terminated with exit code 126
What I'm doing wrong?
I've tried both in mingw git shell , as with plain windows console.
Seems it might be related to this github issue.
One of the workarounds might be to use winpty as specified here.
winpty kubectl.exe exec -it pod-name -- sh
You can also try /bin/sh instead of /bin/bash it worked for me, but I do not have a Windows machine to check it in the same environment as you.
Below command worked for me to launch windows command prompt
kubectl exec -it mycontainer -- cmd.exe

Resources