makefile cannot run docker image with -w -v -u options - docker

I have working docker image that i can run locally by command
docker run --rm -u $(id -u) -v${PWD}:${PWD} -w${PWD} protocbuilder:1.0 [other unimportant args]
And everything works fine. I want use makefile to automate things using that container, so i created make command:
test:
docker run --rm -u $(id -u) -v${PWD}:${PWD} -w${PWD} protocbuilder:1.0 [other unimportant args]
But when I call make test I'm getting following output:
docker run --rm -u -v/Users/mikolaj/GolandProjects/project:/Users/mikolaj/GolandProjects/project -w/Users/mikolaj/GolandProjects/project protocbuilder:1.0 [other unimportant args]
docker: Error response from daemon: unable to find user -v/Users/mikolaj/GolandProjects/project: no matching entries in passwd file.
make: *** [test] Error 125
I'm not very into makefile things, so I don't understand why makefile fails with that when in standard call of docker run in console everything works fine. It seems that there is a problem with mapping user into container using -u, -v and -w arguments. Should I do some additional steps in makefile to make this work correctly? Or maybe I need to change something in docker run command inside makefile?
Thanks in advance

$(...) is (GNU) make function syntax. If you need to include a literal $ in a shell command for something like command substitution, you need to escape it by doubling the $
test:
docker run --rm -u $$(id -u) ...
# ^^
You could also use the backtick syntax to avoid this escaping issue
test:
docker run --rm -u `id -u` ...
Similarly ${PWD} gets expanded by make before the command gets run in the shell, but this probably isn't a significant difference.

Related

No access to volume after docker run -v

The following command runs fine on my local machine.
docker run -it --rm --ulimit memlock=-1 \
-v "$HOMEDIR/..":"/home/user/repo" \
-w "/home/user/repo/linux" \
${DOCKER_IMAGE_NAME} bash build.sh
Running it in a docker-in-docker evirionment (that means the mentioned docker command is executed in a container on google cloudbuild) is leading to two problems though:
Docker complains The input device is not a tty. My workaround: I simply used only docker run -i --rm.
Somehow the assigned volume and working directory on the container do not exist under the given path. But i checked them on the host system and they exist, but somehow do not make it until the container.
I thought also already about using docker exec but there i don't have the fancy -v options. I tried both, the docker run command with the -i and the -it flag on my local machine where it both runned fine. Anyway on cloudbuild i get the tty error when usind -it and the unacessible volume problem occurs when using -i.

docker with makefile volume mounts

So recently came across this weird case where I am trying to access file in my local dir into my container.
When I run the following command on terminal it runs fine and shows the expected list of file
docker run -it --rm -v $(pwd):/mnt/data -w /mnt/data-sink artprod.dev.abc.com/org/cli ls
But when I try to run this via makefile it shows nothing,(I run make in the same path where I run the docker cmd in the previous step)
docker-publish: build
echo "Publishing $(APP_NAME) snapshot $(VERSION)"
docker run -it --rm -v $(pwd):/mnt/data -w /mnt/data-sink artprod.dev.abc.com/org/cli ls
$(shell pwd) worked simply $(pwd) in make didnt do the shell interpolation.

Store docker command result in varaible in Makefile

We are trying to store the container names in my Makefile but I see below error when executing the build, someone please advise. Thanks.
.PHONY: metadata
metadata: .env1
docker pull IMAGE_NAME
docker run $IMAGE_NAME;
ID:= $(shell docker ps --format '{{.Names}}')
#echo ${ID}
docker cp ${ID}:/app/.env .env2
Container names are not shown in below "ID" Variable when executing the makefile from Jenkins
ID:=
/bin/sh: ID:=: command not found
There are a couple of things you can do in terms of pure Docker mechanics to simplify this.
You can specify an alternate command when you docker run an image: anything after the image name is taken as the image to run. For instance, you can cat the file as the main container command, and replace everything you have above as:
.PHONY: getmetadata
getmetadata: .env2
.env2: .env1
docker run --rm \
-e "ARTIFACTORY_USER=${ARTIFACTORY_CREDENTIALS_USR}" \
-e "ARTIFACTORY_PASSWORD=${ARTIFACTORY_CREDENTIALS_PSW}" \
--env-file .env1 \
"${ARTIFACTDATA_IMAGE_NAME}" \
cat /app/.env \
> $#
(It is usually better to avoid docker cp, docker exec, and other imperative-type commands; it is fairly inexpensive and better practice to run a new container when you need to.)
If you can't do this, you can docker run --name your choice of names, and then use that container name in the docker cp option.
.PHONY: getmetadata
getmetadata: .env2
.env2: .env1
docker run --name getmetadata ...
docker cp getmetadata:/app/.env $#
docker stop getmetadata
docker rm getmetadata
If you really can't avoid this at all, each line of the Makefile runs in a separate shell. On the one hand this means you need to join together lines if you want variables from one line to be visible in a later line; on the other, it means you have normal shell functionality available and don't need to use the GNU Make $(shell ...) extension (which evaluates when the Makefile is loaded and not when you're running the command).
.PHONY: getmetadata
getmetadata: .env2
.env2: .env1
# Note here:
# $$ escapes $ for the shell
# Multiple shell commands joined together with && \
# Beyond that, pure Bourne shell syntax
ID=$$(docker run -d ...) && \
echo "$$ID" && \
docker cp "$$ID:/app/.env" "$#"

Docker Unable to find image '502:20' locally. How can I resolve this issue?

When I run the following command I get the following output message. How can I resolve this issue?
docker run -it --rm "$(id -u):$(id -g)" -v "PWD":/usr/src/app -w /usr/src/app \
rails rails new --skip-bundle --api --database postgresql webapp
Command prints:
Unable to find image '502:20' locally
docker: Error response from daemon: repository 502 not found: does not exist or no pull access.
It looks like you are adding some extraneous items (user and group ids) to your docker run call:
"$(id -u):$(id -g)"
Docker is seeing this as the first positional argument and assuming that it is the repository/image name. Running without that argument should work:
docker run -it --rm -v "PWD":/usr/src/app -w /usr/src/app \
rails rails new --skip-bundle --api --database postgresql webapp

Define Docker commands aliases

I several of my projects I am using docker and docker-compose.
It's great, but now many command I am using are very long, like
docker run --rm -it -v $(pwd):/app -u $(id -u):$(id -g) php:7.1 php vendor/bin/phpunit
I would like to use just something like
docker phpunit
providing details in docker-compose or some other configuration file.
Is there a way to define aliases of these commands on a per project basis?
I don't want to use global aliases since such commands can vary for every project.
You could simply add a bash script docker.sh to each one of your projects:
#!/usr/bin/env bash
docker run --rm -it -v $(pwd):/app -u $(id -u):$(id -g) php:7.1 php vendor/bin/phpunit
and run it with ./docker.sh. This is a easy way to customize it considering each particularity and have the command under your version control.

Resources