dockerfile copy from with variable - docker

Is it possible to copy from another image inside a dockerfile, using a variable as parameter of the from flag?
What I would achieve is the following
ARG MY_VERSION
COPY --from=my-image:$MY_VERSION /src /dst
But i always get
invalid from flag value my-image:$MY_VERSION: invalid reference format

You can do what you want, but you need to have a FROM statement identifying the image you want to copy from. Something like this
ARG MY_VERSION
FROM my-image:$MY_VERSION as source
FROM scratch as final
COPY --from=source /src /dst
Replace scratch with the base image you want to use for your new image.
Here's an example to show that it works. Dockerfile:
ARG MY_VERSION
FROM ubuntu:$MY_VERSION as source
FROM alpine:latest
COPY --from=source /etc/os-release /
Build and run with
docker build --build-arg MY_VERSION=20.04 -t test .
docker run --rm test cat /os-release
The output shows
NAME="Ubuntu"
VERSION="20.04.2 LTS (Focal Fossa)"
ID=ubuntu
...
which shows that it has copied a file from the Ubuntu 20.04 image to an Alpine image.

Related

The image docker built through jenkins didn't have name and tag

Here is my Dockerfile:
FROM golang:1.17.5 as builder
WORKDIR /go/src/github.com/cnosdb/cnosdb
COPY . /go/src/github.com/cnosdb/cnosdb
RUN go env -w GOPROXY=https://goproxy.cn,direct
RUN go env -w GO111MODULE=on
RUN go install ./...
FROM debian:stretch
COPY --from=builder /go/bin/cnosdb /go/bin/cnosdb-cli /usr/bin/
COPY --from=builder /go/src/github.com/cnosdb/cnosdb/etc/cnosdb.sample.toml /etc/cnosdb/cnosdb.conf
EXPOSE 8086
VOLUME /var/lib/cnosdb
COPY docker/entrypoint.sh /entrypoint.sh
COPY docker/init-cnosdb.sh /init-cnosdb.sh
RUN chmod +x /entrypoint.sh /init-cnosdb.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["cnosdb"]
Here is my configuration of my jenkins:
But the image docker built didn't have a name.
why?
I haven't used Jenkins for this, as I build from the command line. But are you expecting your name arg to show up in the REPOSITORY and TAG columns? If that is the case, docker has a docker tag command, like so:
~$ docker tag <image-id> repo/name:tag
When I build from the command line, I do it like this:
~$ docker build -t repo/name:0.1 .
Then if I check images:
❯ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
repo/name 0.1 689459c139ef 2 days ago 187MB
Adding to what #rtl9069 mentioned the docker build command can be ran as part of a pipeline. Please take a look at this article https://www.liatrio.com/blog/building-with-docker-using-jenkins-pipelines as it describes it with examples.

Docker: Multistage builds result in multiple images

Given this small example of a multistage build
FROM node:10 AS ui-build
WORKDIR /usr/src/app
FROM node:10 AS server-build
WORKDIR /root/
EXPOSE 3070
ENTRYPOINT ["node"]
CMD ["index.js"]
why does this result in 3 images on my local file system?
"<none>";"<none>";"58d63982fbef";"2020-04-15 17:53:14";"912MB"
"node";"10";"bd83fcefc19d";"2020-04-14 01:32:21";"912MB"
"test";"latest";"3913dd4d03b6";"2020-04-15 17:53:15";"912MB"
I expected two images, the base image and the server-build image. I used the standard docker build command, i.e.
docker build -t test .
so which of the parts of the image is none and which is test?
I am confused
Each block in the Dockerfile starting with a FROM line creates a new image. If you use a docker build -t option, only the last stage gets tagged with the name you specify; the remaining blocks will appear as <none> in places like docker images output.
# node:10 is a base image
# Not the final image, will appear as <none>:<none>
FROM node:10 AS ui-build
...
# The final image, will appear as test:latest (`docker build -t` option)
FROM node:10 AS server-build
...
You will occasionally see Dockerfiles where a base image is reused in later build stages, and there it will not show up at all in docker images output.
# Will be hidden because it has descendant images
FROM node:10 AS base
RUN apt-get update && apt-get upgrade
# Will appear as <none>:<none>
FROM base AS ui
...
# Will get the `docker build -t` tag
FROM base

Docker ARG or ENV not working as expected in Dockerfile

I use Docker Toolbox for windows (for compatibility issues) and in the Dockerfile I specify an ARG so that I can use it when building the image with --build-arg command. Inside the dockerfile I also have some COPY commands and there I would like to use my variable but when I run docker build --build-arg VERSION_APP=something . it does not translate the variable . I have already used $VERSION_APP or ${VERSION_APP} or %VERSION_APP%.
FROM alpine
MAINTAINER Marinos
ARG VERSION_APP
RUN apk update && apk add dos2unix
COPY script.sh /home/script.sh
RUN chmod a+x /home/script.sh
RUN dos2unix /home/script.sh
RUN sh /home/script.sh
COPY installation.txt /home/Desktop/${VERSION_APP}
UPDATE
It seems that you should pass the whole path to the variable you use that is how I got it working.
If you actually use the command below then it is expected not to work because the argument called VERSION_APP
docker build --build-arg myVar=something
So the command should be
docker build --build-arg VERSION_APP=something
And in Dockerfile it should be %VERSION_APP% also you may need to use ENV like below:
ARG VERSION_APP
ENV VERSION_APP ${VERSION_APP}

ARG substitution in RUN command not working for Dockerfile

In my Dockerfile I have the following:
ARG a-version
RUN wget -q -O /tmp/alle.tar.gz http://someserver/server/$a-version/a-server-$a-version.tar.gz && \
mkdir /opt/apps/$a-version
However when building this with:
--build-arg http_proxy=http://myproxy","--build-arg a-version=a","--build-arg b-version=b"
Step 10/15 : RUN wget... is shown with $a-version in the path instead of the substituted value and the build fails.
I have followed the instructions shown here but must be missing something else.
My questions is, what could be causing this issue and how can i solve
it?
Another thing to be careful about is that after every FROM statements all the ARGs get collected and are no longer available. Be careful with multi-stage builds.
You can reuse ARG with omitted default value inside FROM to get through this problem:
ARG VERSION=latest
FROM busybox:$VERSION
ARG VERSION
RUN echo $VERSION > image_version
Example taken from docs:
https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact
Don't use - in variable names.
Docker build will always show you the line as is written down in the Dockerfile, despite the variable value.
So use this variable name a_version:
ARG a_version
See this example:
Dockerfile:
FROM alpine
ARG a_version
RUN echo $a_version
Build:
$ docker build . --build-arg a_version=1234
Sending build context to Docker daemon 2.048 kB
Step 1/3 : FROM alpine
---> a41a7446062d
Step 2/3 : ARG a_version
---> Running in c55e98cab494
---> 53dedab7de75
Removing intermediate container c55e98cab494
Step 3/3 : RUN echo $a_version <<< note this <<
---> Running in 56b8aeddf77b
1234 <<<< and this <<
---> 89badadc1ccf
Removing intermediate container 56b8aeddf77b
Successfully built 89badadc1ccf
I had the same problem using Windows containers for Windows.
Instead of doing this (Which works in linux containers)
FROM alpine
ARG TARGETPLATFORM
RUN echo "I'm building for $TARGETPLATFORM"
You need to do this
FROM mcr.microsoft.com/windows/servercore
ARG TARGETPLATFORM
RUN echo "I'm building for %TARGETPLATFORM%"
Just change the variable resolution according to the OS.
I spent much time to have the argument substitution working, but the solution was really simple. The substitution within RUN needs the argument reference to be enclosed in double quotes.
ARG CONFIGURATION=Debug
RUN dotnet publish "Project.csproj" -c "$CONFIGURATION" -o /app/publish
The only way I was able to substitute an ARG in a Windows Container was to prefix with $env:, as mentioned here.
An example of my Dockerfile is below. Notice that the ARG PAT is defined after the FROM so that it's in scope for its use in the RUN nuget sources add command (as Hongtao suggested). The only successful way I found to supply the personal access token was using $env:PAT
FROM mcr.microsoft.com/dotnet/framework/sdk:4.7.2 AS build
WORKDIR /app
ARG PAT
# copy csproj and restore as distinct layers
COPY *.sln .
COPY WebApi/*.csproj ./WebApi/
COPY WebApi/*.config ./WebApi/
RUN nuget sources add -name AppDev -source https://mysource.pkgs.visualstudio.com/_packaging/AppDev/nuget/v2 -username usern -password $env:PAT
RUN nuget restore
# copy everything else and build app
COPY WebApi/. ./WebApi/
WORKDIR /app/WebApi
RUN msbuild /p:Configuration=Release
FROM mcr.microsoft.com/dotnet/framework/aspnet:4.7.2 AS runtime
WORKDIR /inetpub/wwwroot
COPY --from=build /app/WebApi/. ./
The actual Docker command looks like this:
docker build --build-arg PAT=mypatgoeshere -t webapi .
I had the same problem accessing build-args in my RUN command. Turns out that the line containing the ARG definition should not be the first line. The working Dockerfile snippet looks like this:
FROM centos:7
MAINTAINER xxxxx
ARG SERVER_IPS
Earlier, I had placed the ARG definition as the first line of Dockerfile . My docker version is v19.
There are many answers, which make sense.
But the main thing is missed.
The way, how to use build arguments depends on the base image.
For Linux image, it will work with $ARG
For Windows, depending on image, it can be either $env:ARG(e.g. for mcr.microsoft.com/dotnet/framework/sdk:4.8) or %ARG% (e.g. for mcr.microsoft.com/windows/nanoserver:1809)
For me it was argument's order:
docker build . -f somepath/to/Dockerfile --build-arg FOO=BAR
did not work, but:
docker build --build-arg FOO=BAR . -f somepath/to/Dockerfile
did.

Docker build-arg and copy

Trying to copy a folders content, it works when i hard code the path like:
COPY ./my-folder /path/to/location
But need to be able to change this path so i tried using a build argument like this:
COPY ${folderVariable} /path/to/location
and then build with
--build-arg folderVariable=./my-folder
But it copies everything in the same folder as "my-folder", when i only want the contents of "my-folder"
You need to define it with ARG in Dockerfile before using:
FROM alpine:3.3
ARG folderVariable=./my-folder # Optional default value to be `./my-folder`
COPY ${folderVariable} /opt/my-folder
And build it like:
docker build --build-arg folderVariable=./folder-copy -t test .
More details please refer to: https://docs.docker.com/engine/reference/builder/#arg
Expansion still does not work for the COPY --from=$var ... case.
But you can create intermediate image as an alias, like this:
ARG docsBranch=4.5
ARG docsFullPath=registry.myCompany.pro/group/project-docs/docs:$docsBranch
# Lifehack
FROM $docsFullPath as docs
FROM node:10.21.0-buster-slim
WORKDIR /app
# Now we can use docs instead of $docsFullPath
COPY --from=docs /app/html/en ./documentation/en

Resources