Docker image composition COPY command - docker

I am building a docker image and need to include some contents from particular url.
So I make a curl request and get the contents as a zip. I am able to extract the zip into a folder as well.
However in the very next line if I try to copy the folder I get error that such file or folder does not exist.
Can someone help me?
Below is the docker file. If I do a ls -a after the unzip I can see 2 items drop and amui which is correct. But very next line if I try to copy it fails.
# escape=`
# Setup arguments
ARG BuildConfiguration=Release
ARG ASSEMBLY_VERSION=0.0
ARG FILE_VERSION=0.0.0.0
ARG NUGET_CONFIG=NuGet.config
ARG SYSTEM_ACCESSTOKEN
# base image stage
FROM abc.io/aspnet-runtime:3.1.6 AS base
WORKDIR /app
EXPOSE 80
FROM abc.io/dotnet-build:3.1.6 AS build
ARG BuildConfiguration
ARG ASSEMBLY_VERSION
ARG FILE_VERSION
ARG NUGET_CONFIG
ARG SYSTEM_ACCESSTOKEN
ENV BuildConfiguration=$BuildConfiguration `
ASSEMBLY_VERSION=$ASSEMBLY_VERSION `
FILE_VERSION=$FILE_VERSION `
NUGET_CONFIG=$NUGET_CONFIG `
SYSTEM_ACCESSTOKEN=$SYSTEM_ACCESSTOKEN
WORKDIR /build
RUN Write-Host "BuildConfiguration: ${env:BuildConfiguration}"; `
Write-Host "ASSEMBLY_VERSION: ${env:ASSEMBLY_VERSION}"; `
Write-Host "FILE_VERSION: ${env:FILE_VERSION}"; `
Write-Host "NUGET_CONFIG: ${env:NUGET_CONFIG}"; `
Write-Host "SYSTEM_ACCESSTOKEN: ${env:SYSTEM_ACCESSTOKEN}";
RUN apt-get install -y apt-transport-https
RUN apt-get update
RUN apt-get install -y aspnetcore-runtime-3.1
RUN apt-get install -y curl
RUN apt-get install -y unzip
FROM build as drop
RUN curl -o drop -u sdf#dise.com:ydfesdfasdfdf56pxvwnd5z6445l7kgezpb2lky6ja2g6xvtina4a --request GET 'https://abe.com/ded/c8002d3e-f4a9-4aea-9ab8-230027996c53/_apis/build/builds/1133376/artifacts?artifactName=drop&api-version=6.0&%24format=zip' -L
RUN unzip drop -d amui
COPY amui .
Here is the output of the docker build command. Entire output is not shown for sake of brevity.
100 18.8M 0 18.8M 0 0 757k 0 --:--:-- 0:00:25 --:--:-- 450k
100 20.4M 0 20.4M 0 0 784k 0 --:--:-- 0:00:26 --:--:-- 573k
100 20.7M 0 20.7M 0 0 774k 0 --:--:-- 0:00:27 --:--:-- 543k
100 21.1M 0 21.1M 0 0 759k 0 --:--:-- 0:00:28 --:--:-- 582k
100 21.7M 0 21.7M 0 0 764k 0 --:--:-- 0:00:29 --:--:-- 795k
Removing intermediate container 5cf617b55a61
---> 79d3a513aaf3
Step 25/45 : RUN unzip drop -d amui
---> Running in d1c070949cf9
Archive: drop
creating: amui/drop/
creating: amui/drop/amui/
inflating: amui/drop/SQL/Sql.Template.json
Removing intermediate container d1c070949cf9
---> 73959bf35eca
Step 26/45 : COPY amui src/I.C.AM.C.P
Service 'p.am.ui' failed to build: COPY failed: stat /var/lib/docker/tmp/docker-builder955237576/amui: no such file or directory

Make sure the file or folder is present in the location you expect it to be. The WORKDIR /app from the FROM abc.io/aspnet-runtime:3.1.6 AS base sets the working directory for all contexts until there's another WORKDIR encountered, thus even for the ones that "inherit" from the previous one (FROM previous as new) or for the RUN context. Once that is out of the way, for the remaining part it's about contexts created by FROM and its order.
Sending build context to Docker daemon 3.072kB
Step 1/7 : FROM alpine as base
---> 6dbb9cc54074
Step 2/7 : WORKDIR /hello
---> Running in 5b7f95f0d20b
Removing intermediate container 5b7f95f0d20b
---> 0f139883db01
Step 3/7 : RUN pwd
---> Running in 1a6d896f621b
/hello
Removing intermediate container 1a6d896f621b
---> a09834ecd175
Step 4/7 : RUN cd /
---> Running in 3e6f35bf70e1
Removing intermediate container 3e6f35bf70e1
---> 9636932e3f16
Step 5/7 : RUN pwd
---> Running in fa5dc0c60493
/hello
Removing intermediate container fa5dc0c60493
---> 1d2630c5a098
Step 6/7 : FROM base as test
---> 1d2630c5a098
Step 7/7 : RUN pwd
---> Running in fabd6c1e82f8
/hello
Removing intermediate container fabd6c1e82f8
---> b39b67911581
Successfully built b39b67911581
COPY is for external files i.e. OUT of the image filesystem/context, on your host system and relative to the context path you specify for the docker build [...] <context> (or relative to the WORKDIR of a previous stage IIRC, use absolute paths if unsure).
So the case is one of this:
you already have the contents in your image and you want to use the last context created by FROM base as drop (including the curl+unzip trash) for the final image -> use RUN cp
you want to drop the trash created by curl+unzip -> use new FROM (probably FROM base) to create a new context and finalize the previous one, then copy from the previous image with COPY --from=drop amui <dest>
Optionally COPY accepts a flag --from=<name> that can be used to set the source location to a previous build stage (created with FROM .. AS <name>) that will be used instead of a build context sent by the user. In case a build stage with a specified name can't be found an image with the same name is attempted to be used instead. (source)
Order of the FROM directives matters. If you want to copy to base image from drop, then FROM ... AS drop needs to be built prior to the FROM ... AS base. You are basically using one image for building and then you want to continue building upon it:
FROM [...] AS base # creates context for "base"
...
<base image created>
FROM base AS drop # creates context for "drop"
<download>
COPY ...
<drop image created>
but you haven't started a new context (as you want to copy from the previous context - and you're still either building it or simply misusing COPY for RUN cp) for the final image, therefore even if you use COPY --from=... correctly, you're still copying to the wrong context.
Try this:
FROM [...] AS base # creates context for "base"
...
<base image created>
FROM base AS drop # creates context for "drop"
<download>
<drop image created>
FROM base # creates a new, unnamed context
COPY --from=drop ...
<final image created>
The last FROM context is used for the final image built with:
docker build --tag <name> [other options] <context path>
Example:
Sending build context to Docker daemon 2.048kB
Step 1/7 : FROM alpine as base
---> 6dbb9cc54074
Step 2/7 : RUN mkdir content;echo "hello" > content/file.txt
---> Running in 1f1a82201436
Removing intermediate container 1f1a82201436
---> 35b7a54e6952
Step 3/7 : FROM base as drop
---> 35b7a54e6952
Step 4/7 : RUN echo "world" > content/file.txt
---> Running in e5b214cad371
Removing intermediate container e5b214cad371
---> 51a3a090f43a
Step 5/7 : FROM base
---> 35b7a54e6952
Step 6/7 : COPY --from=drop content content
---> e4280a26c86f
Step 7/7 : RUN cat content/file.txt
---> Running in d71a121a7ff9
world
Removing intermediate container d71a121a7ff9
---> 760e756c4c11
Successfully built 760e756c4c11

To change files that are inside the image you should use:
RUN cp filename path
you can "debug" using RUN echo "your path:" pwd and RUN echo "folders:" ls, and iteratively navigate and check your path to see if it is correct. Just remember to erase these lines from your Dockerfile and build again.
You also can make it after build with:
docker images
get your image name and tag
docker run --privileged -i -t image_name:image_tag bash
navigate trough the image, copy, modify, git clone etc ...
exit container and run:
docker ps -a
to get the image id from the container you just leaved. Then run:
docker commit [image id] image_name_you_choose:tag
to save the images changes.

Related

Dockerfile: changes made to filesystem via RUN do not persist

I could not find that spoecifics via web search for site:stackoverflow.com dockerfile RUN fs changes not persisted.
I made Dockerfile and wanted to make some changes in image via RUN. Firstly I wanted to change file attributes, but changes were not there in started container. I've found this post taking about docker bug for chmod and workarounds: https://serverfault.com/questions/772227/chmod-not-working-correctly-in-docker. However, now I just try to create a file via RUN touch /path/file in Dockerfile and already on next command (next layer for docker as I understood the docs) changes (that file) are gone. As far as I see it is strange, otherwise how apt install works then because it will make changes to file system in the image... Why results of that particular RUN do not persist? Docs below tell opposite (or I misunderstand meaning of commit here):
https://docs.docker.com/engine/reference/builder/ :
The RUN instruction will execute any commands in a new layer on top of
the current image and commit the results. The resulting committed
image will be used for the next step in the Dockerfile.
Here is output of docker build --no-cache -t yandex:user5 yandex2/ (see steps 6 and 7; dockeruser is created, btw):
Step 1/8 : FROM artifactory.dev.foo.org:5000/yandex-tank:jmeter
---> b8286a9220ca
Step 2/8 : LABEL maintainer="foo#foo.org"
---> Running in 7cfde9a90bf2
Removing intermediate container 7cfde9a90bf2
---> b5acd9d55f9c
Step 3/8 : WORKDIR /var/loadteest
---> Running in 47e9adc401bb
Removing intermediate container 47e9adc401bb
---> 103f158e0be3
Step 4/8 : USER root
---> Running in 9923d71f7b08
Removing intermediate container 9923d71f7b08
---> bb3aa8672bc6
Step 5/8 : RUN groupadd -r dockeruser && useradd -r -g dockeruser -d /var/loadtest -s /sbin/nologin -c "Docker image user" dockeruser
---> Running in 48c89f33d750
Removing intermediate container 48c89f33d750
---> 5000afa7698d
Step 6/8 : RUN touch /var/loadtest/chmodtest.txt
---> Running in 00b2d1ccad75
Removing intermediate container 00b2d1ccad75
---> c35808f13344
Step 7/8 : RUN ls -al /var/loadtest
---> Running in cc08d129eeb3
total 8
drwxr-xr-x 2 root root 4096 Nov 20 12:19 .
drwxr-xr-x 1 root root 4096 Nov 29 06:15 ..
Removing intermediate container cc08d129eeb3
---> 842678ca5d49
Step 8/8 : ENTRYPOINT /bin/bash
---> Running in 20b92a97c8a8
Removing intermediate container 20b92a97c8a8
---> fefd0d665677
Successfully built fefd0d665677
Successfully tagged yandex:user5
The Problem is using the volumes in the base image:
Changing the volume from within the Dockerfile: If any build steps
change the data within the volume after it has been declared, those
changes will be discarded.
see This
Workaround is to use COPY docker doc
COPY path/to/local/file /var/loadtest/chmodtest.txt

In Docker, can't cd into directory installed with "go get"?

I'm trying to build a Docker container which downloads the source of https://github.com/micromdm/scep and using the go get command and cds into the resulting directory in order to perform some follow-up commands (namely, make deps, make build, and COPYing the relevant resulting binary into the container's PATH).
So far I've tried this Dockerfile:
FROM golang:latest
ENV GO111MODULE on
RUN ["go", "get", "github.com/micromdm/scep"]
RUN cd $GOPATH/src/github.com/micromdm/scep
However, if I try to run this I get the following error:
> docker build . --tag loadtest
Sending build context to Docker daemon 4.608kB
Step 1/4 : FROM golang:latest
---> 52b59e9ead8e
Step 2/4 : ENV GO111MODULE on
---> Using cache
---> 28335bf0142b
Step 3/4 : RUN ["go", "get", "github.com/micromdm/scep"]
---> Using cache
---> 86760bf0c490
Step 4/4 : RUN cd $GOPATH/src/github.com/micromdm/scep
---> Running in b86fc3ab0ab8
/bin/sh: 1: cd: can't cd to /go/src/github.com/micromdm/scep
The command '/bin/sh -c cd $GOPATH/src/github.com/micromdm/scep' returned a non-zero code: 2
If I try the command without setting the GO111MODULE environment variable to on, I get his error:
> docker build . --tag loadtest
Sending build context to Docker daemon 4.608kB
Step 1/3 : FROM golang:latest
---> 52b59e9ead8e
Step 2/3 : RUN ["go", "get", "github.com/micromdm/scep"]
---> Running in 8cb54311a416
package github.com/micromdm/scep: no Go files in /go/src/github.com/micromdm/scep
The command 'go get github.com/micromdm/scep' returned a non-zero code: 1
Following https://github.com/ponzu-cms/ponzu/issues/204, I also tried running it with a ... at the end,
FROM golang:latest
RUN ["go", "get", "github.com/micromdm/scep/..."]
RUN cd $GOPATH/src/github.com/micromdm/scep \
but this results in
> docker build . --tag loadtest
Sending build context to Docker daemon 4.608kB
Step 1/3 : FROM golang:latest
---> 52b59e9ead8e
Step 2/3 : RUN ["go", "get", "github.com/micromdm/scep/..."]
---> Running in 961bae3bb455
# github.com/micromdm/scep/scep
src/github.com/micromdm/scep/scep/scep.go:318:17: p7.EncryptionAlgorithm undefined (type *pkcs7.PKCS7 has no field or method EncryptionAlgorithm)
src/github.com/micromdm/scep/scep/scep.go:449:26: too many arguments in call to pkcs7.Encrypt
src/github.com/micromdm/scep/scep/scep.go:449:53: undefined: pkcs7.WithEncryptionAlgorithm
src/github.com/micromdm/scep/scep/scep.go:542:26: too many arguments in call to pkcs7.Encrypt
src/github.com/micromdm/scep/scep/scep.go:542:54: undefined: pkcs7.WithEncryptionAlgorithm
The command 'go get github.com/micromdm/scep/...' returned a non-zero code: 2
Any ideas about how I could achieve downloading the package and cding into the resulting directory?
First of all, in docker you are building a container, so trying to cd into a directory in your pc its not possible. Use the WORKDIR command, also id recomend to git clone into a repository and there create the Dockerfile, and then COPY everything in there to a directory inside the docker for example:
COPY . /app
WORKDIR /app/where_you_want_to_cd
RUN whatever_you_want_to_run
You can set this path to be your WORKDIR, and the follow up command would be easy.
From the docker builder reference, each RUN command is run independently. So doing RUN cd does not have any effect on the next RUN command.
The following Dockerfile works:
FROM golang:latest
ENV GO111MODULE on
RUN go get github.com/micromdm/scep
WORKDIR /go/src/github.com/micromdm/scep
You need here the GO111MODULE since in the go.mod of that module isn't defined the go version, so you need to activate it yourself.
It turns out that the resulting code is located not in /go/src, but in /go/pkg.

docker /bin/sh: 1: .: Can't open /path

I have an sbt project projectA under home/demo/projectA my Dockerfile resides in /home/demo/ for some reason i don't want it to be inside projectA
so hierarchy looks like this
home/demo
Dockerfile
projectA
here i am trying to run sbt command in the image build process here is the contents of my Dockerfile
FROM hseeberger/scala-sbt:11.0.2_2.12.8_1.2.8 as stripecommon
MAINTAINER sara <sarawaheed3191#gmail.com>
WORKDIR /aa
RUN \
. /home/demo/projectA sbt
I am getting this error when building the image
:~/home/demo$ docker build -t testapp .
Sending build context to Docker daemon 1.297GB
Step 1/4 : FROM hseeberger/scala-sbt:11.0.2_2.12.8_1.2.8 as stripecommon
---> 349a7e4f4029
Step 2/4 : MAINTAINER sara <sarawaheed3191#gmail.com>
---> Using cache
---> 8603662d3730
Step 3/4 : WORKDIR /aa
---> Using cache
---> f07ec5bb4d34
Step 4/4 : RUN . /home/demo/projectA sbt
---> Running in 7509ee45f622
/bin/sh: 1: .: Can't open /home/demo/projectA
The command '/bin/sh -c . /home/demo/projectA sbt' returned a non-zero code: 2
what is the right way to do this also i am a beginner in docker help will be appreciated
You need to make sure that projectA exists inside the container. so for this either you pick code from github or copy it using COPY or ADD command. After that you can build it using sbt.

Docker build failed to copy a file

Hi I am new to Docker and trying to wrap around my head on how to clone a private repo from github and found some interesting link issues/6396
I followed one of the post and my dockerfile looks like
FROM python:2.7 as builder
# Deploy app's code
#RUN set -x
RUN mkdir /code
RUN mkdir /root/.ssh/
RUN ls -l /root/.ssh/
# The GITHUB_SSH_KEY Build Argument must be a path or URL
# If it's a path, it MUST be in the docker build dir, and NOT in .dockerignore!
ARG SSH_PRIVATE_KEY=C:\\Users\\MyUser\\.ssh\\id_rsa
RUN echo "${SSH_PRIVATE_KEY}"
# Set up root user SSH access for GitHub
ADD ${SSH_PRIVATE_KEY} /root/.ssh/id_rsa
RUN ssh -o StrictHostKeyChecking=no -vT git#github.com 2>&1 | grep -i auth
# Test SSH access (this returns false even when successful, but prints results)
RUN git clone git#github.com:***********.git
COPY . /code
WORKDIR /code
ENV PYTHONPATH /datawarehouse_process
# Setup app's virtualenv
RUN set -x \
&& pip install tox \
&& tox -e luigi
WORKDIR /datawarehouse_process
# Finally, remove the $GITHUB_SSH_KEY if it was a file, so it's not in /app!
# It can also be removed from /root/.ssh/id_rsa, but you're probably not
going
# to COPY that directory into the runtime image.
RUN rm -vf ${GITHUB_SSH_KEY} /root/.ssh/id*
#FROM python:2.7 as runtime
#COPY --from=builder /code /code
When I run docker build . from the correct location I get this error below. Any clue will be appreciated.
c:\Domain\Project\Docker-Images\datawarehouse_process>docker build .
Sending build context to Docker daemon 281.7MB
Step 1/15 : FROM python:2.7 as builder
---> 43c5f3ee0928
Step 2/15 : RUN mkdir /code
---> Running in 841fadc29641
Removing intermediate container 841fadc29641
---> 69fdbcd34f12
Step 3/15 : RUN mkdir /root/.ssh/
---> Running in 50199b0eb002
Removing intermediate container 50199b0eb002
---> 6dac8b120438
Step 4/15 : RUN ls -l /root/.ssh/
---> Running in e15040402b79
total 0
Removing intermediate container e15040402b79
---> 65519edac99a
Step 5/15 : ARG SSH_PRIVATE_KEY=C:\\Users\\MyUser\\.ssh\\id_rsa
---> Running in 10e0c92eed4f
Removing intermediate container 10e0c92eed4f
---> 707279c92614
Step 6/15 : RUN echo "${SSH_PRIVATE_KEY}"
---> Running in a9f75c224994
C:\Users\MyUser\.ssh\id_rsa
Removing intermediate container a9f75c224994
---> 96e0605d38a9
Step 7/15 : ADD ${SSH_PRIVATE_KEY} /root/.ssh/id_rsa
ADD failed: stat /var/lib/docker/tmp/docker-
builder142890167/C:\Users\MyUser\.ssh\id_rsa: no such file or
directory
From the Documentation:
ADD obeys the following rules:
The path must be inside the context of the build; you cannot ADD
../something /something, because the first step of a docker build is
to send the context directory (and subdirectories) to the docker
daemon.
You are passing an absolute path to ADD, but you can see from the error:
/var/lib/docker/tmp/docker-builder142890167/C:\Users\MyUser\.ssh\id_rsa:
no such file or directory
It is being looked for within the build context. Again from the documentation:
Traditionally, the Dockerfile is called Dockerfile and located in the
root of the context.
So, you need to place the RSA key somewhere in the directory tree which has it's root at the path that you specify in your Docker build command, so if you are entering docker build . your ARG statement would change to something like:
ARG SSH_PRIVATE_KEY = .\.ssh\id_rsa

Dockerfile: mkdir and COPY commands run fine but I can't see the directory and file

I am using jenkins image to create a docker container. For now I am just trying to create a new directory and copy a couple of files. The image build process runs fine but when I start the container I cannot see the files and the directory.
Here is my dockerfile
FROM jenkins:2.46.1
MAINTAINER MandeepSinghGulati
USER jenkins
RUN mkdir /var/jenkins_home/aws
COPY aws/config /var/jenkins_home/aws/
COPY aws/credentials /var/jenkins_home/aws/
I found a similar question here but it seems different because I am not creating the jenkins user. It already exists with home directory /var/jenkins_home/. Not sure what I am doing wrong
Here is how I am building my image and starting the container:
➜ jenkins_test docker build -t "test" .
Sending build context to Docker daemon 5.632 kB
Step 1/6 : FROM jenkins:2.46.1
---> 04c1dd56a3d8
Step 2/6 : MAINTAINER MandeepSinghGulati
---> Using cache
---> 7f76c0f7fc2d
Step 3/6 : USER jenkins
---> Running in 5dcbf4ef9f82
---> 6a64edc2d2cb
Removing intermediate container 5dcbf4ef9f82
Step 4/6 : RUN mkdir /var/jenkins_home/aws
---> Running in 1eb86a351beb
---> b42587697aec
Removing intermediate container 1eb86a351beb
Step 5/6 : COPY aws/config /var/jenkins_home/aws/
---> a9d9a28fd777
Removing intermediate container ca4a708edc6e
Step 6/6 : COPY aws/credentials /var/jenkins_home/aws/
---> 9f9ee5a603a1
Removing intermediate container 592ad0031f49
Successfully built 9f9ee5a603a1
➜ jenkins_test docker run -it -v $HOME/jenkins:/var/jenkins_home -p 8080:8080 --name=test-container test
If I run the command without the volume mount, I can see the copied files and the directory. However with the volume mount I cannot see the same. Even if I empty the directory on the host machine. Is this the expected behaviour? How can I copy over files to the directory being used as a volume ?
Existing volumes can be mounted with
docker container run -v MY-VOLUME:/var/jenkins_home ...
Furthermore, the documentation of COPY states:
All new files and directories are created with a UID and GID of 0.
So COPY does not reflect your USER directive. This seems to be the second part of your problem.

Resources