Store docker command result in varaible in Makefile - docker

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" "$#"

Related

How to run a "docker run .." command from within a shell script

I have a shell script containing a call to docker run. The script looks like this:
#!/bin/sh
#Local directory where your data is.
PATH_TO_EXPORTS="/home/user/data"
iType_NAME="iType.csv"
colIDs="X,Y,W,Z"
FLAG="FALSE"
#These next three variables don't need to, and should not be changed.
#They refer to locations within the docker container - DO NOT CHANGE !!!
IMG_EXPORTS_DIR="/home/rstudio/project/exports"
#Execute docker run to carry out your analysis
docker run -v $PATH_TO_EXPORTS:$IMG_EXPORTS_DIR \
-e PATH_TO_EXPORTS=$IMG_EXPORTS_DIR \
-e iType_NAME=$iType_NAME \
-e colIDs=$colIDs \
-e FLAG=$FLAG \
--user "$(id -u)" \
my_docker_image:3.0
If I try to run this script via command line by calling: sh myScript.sh , I get the following error:
docker: invalid reference format.
See 'docker run --help'.
However, if I manually run the docker run ... command on the command line, everything works as expected.
Does anybody know why this docker run ... command fails when inside a shell script ?
Many thanks in advance !
-M.

Visual Studio Dockerfile EntryPoint Override Explained?

I am new to Docker and trying to understand but I have noticed the Visual Studio does a lot of 'magic' behind the scenes. I have managed to figure out all my questions about the docker run command VS uses when you debug an ASP.NET Core app with Docker support except one.
docker run
-dt
-v "C:\Users\jnhaf\vsdbg\vs2017u5:/remote_debugger:rw"
-v "D:\ProtoTypes\WebAppDockerOrNot\WebAppDockerOrNot:/app"
-v "C:\Users\jnhaf\AppData\Roaming\ASP.NET\Https:/root/.aspnet/https:ro"
-v "C:\Users\jnhaf\AppData\Roaming\Microsoft\UserSecrets:/root/.microsoft/usersecrets:ro"
-v "C:\Users\jnhaf\.nuget\packages\:/root/.nuget/fallbackpackages2"
-v "C:\Program Files\dotnet\sdk\NuGetFallbackFolder:/root/.nuget/fallbackpackages"
-e "DOTNET_USE_POLLING_FILE_WATCHER=1"
-e "ASPNETCORE_ENVIRONMENT=Development"
-e "ASPNETCORE_URLS=https://+:443;http://+:80"
-e "ASPNETCORE_HTTPS_PORT=44328"
-e "NUGET_PACKAGES=/root/.nuget/fallbackpackages2"
-e "NUGET_FALLBACK_PACKAGES=/root/.nuget/fallbackpackages;/root/.nuget/fallbackpackages2"
-p 4800:80
-p 44328:443
--entrypoint tail webappdockerornot:dev -f /dev/null
The final argument --entrypoint tail webappdockerornot:dev -f /dev/null is the one that confuses me. I get that VS is overriding the entry point setup in the Dockerfile but what I do not understand nor can find online is what tail webappdockerornot:dev and the -f /dev/null. I figured out that webappdockerornot:dev is the docker image but can someone explain how this argument works or provide a link to something that explains it.
We can break down that command line a little differently as
docker run \
... some other arguments ... \
--entrypoint tail \
webappdockerornot:dev \
-f /dev/null
and match this against a general form
docker run [OPTIONS] [IMAGENAME:TAG] [CMD]
So the --entrypoint tail option sets the entry point to tail, and the "command" part is -f /dev/null. When Docker actually launches the container, it passes the command as additional arguments to the entrypoint. In the end, the net effect of this is
Ignore what the Dockerfile said to do; after setting up the container runtime environment, run tail -f /dev/null instead.
which in turn is a common way to launch a container that doesn't do anything but also stays running. Then you can use docker exec and similar debugging-oriented tools to do things inside the container.

How to specify in Dockerfile that the image is interactive?

I have created a docker container that runs a command line tool. The container is supposed to be interactive. Am I somehow able to specify in the Dockerfile that the container is always started in interactive mode?
For reference this is the dockerfile:
FROM ubuntu:latest
RUN apt-get update && apt-get -y install curl
RUN mkdir adr-tools && \
cd adr-tools && \
curl -L https://github.com/npryce/adr-tools/archive/2.2.0.tar.gz --output adr-tools.tar.gz && \
tar -xvzf adr-tools.tar.gz && \
cp */src/* /usr/bin && \
rm -rf adr-tools
CMD ["/bin/bash"]
EDIT:
I know of the -it options for the run command. I'm explicitly asking for a way to do this in the docker file.
EDIT2:
This is not a duplicate of Interactive command in Dockerfile since my question addresses an issue with how arguments specified to docker run can be avoided in favor of specifying them in the Dockerfile whereas the supposed duplicate addresses an issue of interactive input during the build of the image by docker itself.
Many of the docker run options can only be specified at the command line or via higher-level wrappers (shell scripts, Docker Compose, Kubernetes, &c.). Along with port mappings and network settings, the “interactive” and “tty” options can only be set at run time, and you can’t force these in the Dockerfile.
You can use the docker run command.
docker build -t curly .
docker run -it curly curl https://stackoverflow.com
The convention is:
docker run -it IMAGE_NAME [COMMAND] [ARG...]
Where [COMMAND] is curl and [ARG...] are the curl arguments, which is https://stackoverflow.com in my example.
-i enables interactive process mode. You can't specify this in the Dockerfile.
-t allocates a pseudo-TTY for the container.
Are you looking for the -it option?
From the Docker documentation:
For interactive processes (like a shell), you must use -i -t together
in order to allocate a tty for the container process.
So, for example you can run it like:
docker run -it IMAGE_NAME [COMMAND] [ARG...]
Actually, in Ubuntu, I am running Apache Server in the background.
But for you, Try with below command and you should be able to go inside docker container.
docker exec -i -t your_container_name bash

How to read docker command?

I would like someone to assist me in reading below docker run command
docker run --rm \
--volumes-from myredis \
-v $PWD/backup:/backup \
debian \
cp /data/dump.rdb /backup/
I know it dumps redis, and attaching volume from container myredis into cwd backup. As for the rest of the command I am having trouble interpreting it.
Thanks.
this command is to create a redis's backup you are coping the dump.rdb into the /backup dir on your host.
--rm means remove the container after run, usually it's a good way to clean your env because you can not reuse this container when it finish its work.
debian is the name of the image that you are using.
"cp /data/dump.rdb /backup/" is the command that you are doing inside your container

Start and attach a docker container with X11 forwarding

There are various articles like this, this and this and many more, that explains how to use X11 forwarding to run GUI apps on Docker. I am using a Centos Docker container.
However, all of these approaches use
docker run
with all appropriate options in order to visualize the result. Any use of docker run creates a new image and performs the operation on top of that.
A way to work in the same container is to use docker start followed by docker attach and then executing the commands on the prompt of the container. Additionally, the script (let's say xyz.sh) that I intend to run on Docker container resides inside a folder MyFiles in the root directory of the container and accepts a parameter as well
So is there a way to run the script using docker start and/or docker attach while also X11-forwarding it?
This is what I have tried, although would like to avoid docker run and instead use docker start and docker attach
sudo docker run -it \
--env="DISPLAY" \
--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
centos \
cd MyFiles \
./xyz.sh param1
export containerId='docker ps -l -q'
This in turn throws up an error as below -
/usr/bin/cd: line 2: cd: MyFiles/: No such file or directory
How can I run the script xyz.sh under MyFiles on the Docker container using docker start and docker attach?
Also since the location and the name of the script may vary, I would like to know if it is mandatory to include each of these path in the system path variable on the Docker container or can it be done at runtime also?
It looks to me your problem is not with X11 forwarding but with general Docker syntax.
You could do it rather simply:
sudo docker run -it \
--env="DISPLAY" \
--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
-w MyFiles \
--rm \
centos \
bash -c xyz.sh param1
I added:
--rm to avoid stacking old dead containers.
-w workdir, obvious meaning
/bin/bash -c to get sure your script is interpreted by bash.
How to do without docker run:
run is actually like create then start. You can split it in two steps if you prefer.
If you want to attach to a container, it must be running first. And for it to be running, there must be a process currently running inside.

Resources