Dockerfile change file permission during COPY - docker

I'd like to change permissions on certificates that I'm coping into image filesystem. What's the easiest way?
FROM ubuntu:22.04
COPY assets/ /usr/share/ca-certificates/orsted/

Just add --chmod=644 flag to COPY or ADD instruction as on the example below.
FROM ubuntu:22.04
COPY --chmod=644 assets/certs /usr/share/ca-certificates/acme/
If you need to change owner of the files as well, then add --chown=nobody:nogroup flag.
FROM ubuntu:22.04
COPY --chmod=644 --chown=nobody:nogroup assets/certs /usr/share/ca-certificates/acme/
Important:
the --chmod option requires BuildKit. Refer to https://docs.docker.com/go/buildkit/ to learn how to build images with BuildKit enabled

Related

Can someone explain what does 5th line mean . i.e ADD . $HOME_DIR mean in docker file?

I have a problem with 5th line of my Dockerfile. I couldn't figure out what that means.
FROM python:3.7-alpine
LABEL author= APPLE
LABEL company= PINEAPPLE
ARG HOME_DIR='/schooldata'
ADD . $HOME_DIRECT ##[ this line ]
EXPOSE 5000
WORKDIR $HOME_DIRECT
RUN pip install -r requirements.txt
ENTRYPOINT ["python", "app.py"]
Here :
ADD . $HOME_DIRECT
ADD performs a resource copy from a source to the current built image with the following specificity : if that is recognized as an archive (tar,zip...), it copies its content, otherwise it copies the contained files/directories such as.
The two next arguments are the source resource and the target resource of ADD.
. means that the source is the build context. Build context is the last argument of the docker build command : often we specify . such as docker build FooTag . to represent the current directory where the docker build command is executed but that may be different.
$HOME_DIRECT is the target directory of the copy inside the built image.
As a side note, ADD has a quite complex behavior (it also may accept URL as source, so it should be favored over COPY only for special cases (URL and copy archive's content).
In most of cases that is indeed better :
COPY . $HOME_DIRECT
It will add the content of your working directory (where the build command has been executed) into you image in the location defined in environment variable HOME_DIRECT
More details: here

How to copy multiple files in one layer using a Docker file to different locations?

Is it possible to copy multiple files to different locations in a Dockerfile?
I'm looking to go from:
COPY outputs/output/build/.tools /root/.tools
COPY outputs/output/build/configuration /root/configuration
COPY outputs/output/build/database/postgres /root/database/postgres
I have tried the following, but no joy:
COPY ["outputs/output/build/.tools /root/.tools","outputs/output/build/configuration /root/configuration","outputs/output/build/database/postgres /root/database/postgres"]
Not sure if this is even possible.
Create a file .dockerignore in your docker build context directory. Create a soft link (ln) of the root directory you want to copy and exclude the directories you don't want in your .dockerignore.
In your case, you don't need the soft link as the directory is already in the docker build context. Now, add the directories in the .dockerignore file that you don't want eg. if you don't want bin directory you can do that as,
# this is .dockerignore file
outputs/output/build/bin*
Finally in your Dockerfile,
COPY outputs/output/build/ /root/
Details are here.
it looks like you are trying to do bash style [] brace expansion
RUN command uses sh NOT bash
see this SO article discussing it
Bash brace expansion not working on Dockerfile RUN command
or the docker reference
https://docs.docker.com/engine/reference/builder/#/run

How to use big file only to build the container without adding it?

I have a big tar/executable (over 30GB) I COPY/ADD it but this is used only for the installation. Once the application is installed I don't need it anymore.
How can I do? I am trying to use it but:
Everytime I run a build, it takes minutes to define the build context.
I'd like to share this image, if I create a tar with docker save, Is the final version or each layer included in it?
I found some solutions that said I can use RUN wget tar ... && rm tar but I don't want to create webserver for that.
Why isn't possible to mount a volume during build process?! It would be very useful.
Use Docker's multi-stage builds. This mechanism allows you to drop intermediate artifacts and therefore achieve a lightweight image.
Example:
FROM alpine:latest as build
# copy large file
# build
FROM alpine:latest as output
# copy necessary files built in the previous stage
COPY --from=build app /app
Anything built in the build stage will not be included in the final image, unless you explicitly COPY them.
Docs: https://docs.docker.com/develop/develop-images/multistage-build/
This is solvable using 2 different context.
Please follow these steps as mentioned below.
Objective is to create a
docker image that will have you large-build file.
docker image that will have you real codebase/executables.
For this you have to create 2 folders (Build & CodeBase) as follow.
Application<br/>
|---> BUILD <br/>
|======|--->Large-File<br/>
|======|--->Dockerfile<br/>
|--->CodeBase<br/>
|======|--->SRC+Other stuff<br/>
|======|--->Dockerfile<br/>
Build & Codebase both folders will have individual Dockerfile and arrange files accordingly.
Dockerfile(Build)
FROM **Base-Image**
COPY Large-File /tmp/Large-File
Build this and tag it with some name like (base-build-app-image)
#>cd Application <==Application root folder as mentioned above==>
#>docker build -t base-build-app-image BUILD <==path of your build-folder==>
Dockerfile(Codebase)
FROM base-build-app-image
RUN *****
CMD *****
RUN rm -f **/tmp/Large-File**
RUN rm -f **Remove installation files that is not required**
ENTRYPOINT *****
Build this-code-base and base-build-app-image is already in your local docker-repository and your large iso file is not in the current-buid-context
#>cd Application <==Application root folder as mentioned above==>
#>docker build CodeBase <==path of your code-base==>
This time since the context size is only your code base and since this doesn't include that Large file - it will definitely reduce your build time.
You can also take an advance of using docker-compose to do both operations together so you will not have to execute 2 separate commands.
If you need help on preparing this docker-compose file then do let me know in comments.
If anything is not clear then leave a comment or come over chat to fix this issue.

docker add "requires at least one argument" error

I have a folder which contains all the necessary components for an app, which I want to make a container of. I have everything set up so far, with the directory /home/user/Documents/App in the Dockerfile under the ADD heading. Then when Idocker build . in the App directory I get this
ADD /home/user/Documents/App
ADD requires at least one argument
I realize that this is probably a simple fix but I am new to this so any help would be greatly appreciated. Thank you
FROM alpine
ADD </home/user/Documents/App> </home/user/Documents/DockerApp>
WORKDIR /code
RUN pip install -r requirements.txt
EXPPOSE 8080
CMD ["python", "app.py"]
You need a source and destination for the ADD command. The source here is the app folder path. The destination should be where you want the dockerfile is run.
Try this I think it might work
ADD defined in Dockerfile has the following structure
ADD sourceJarName destinationJarName
e.g.
ADD target/spring-boot-rest-docker-example-0.0.1-SNAPSHOT.jar app.jar
change your ADD likewise and try it will work

Copy directory to another directory using ADD command

I have read http://docs.docker.com/engine/reference/builder/#add however I met a problem. I want to copy the local directory go to docker /user/local/
I tried:
ADD go /usr/local/
and:
ADD /go/ /usr/local/
also:
RUN chmod 0755 /usr/local/go/src/make.bash
However, I see the following error message:
/usr/local/go/src/make.bash: No such file or directory
but the local go directory does contain make.bash.
ADD go /usr/local/
will copy the contents of your local go directory in the /usr/local/ directory of your docker image.
To copy the go directory itself in /usr/local/ use:
ADD go /usr/local/go
or
COPY go /usr/local/go
Indeed ADD go /usr/local/ will add content of go folder and not the folder itself, you can use Thomasleveil solution or if that did not work for some reason you can change WORKDIR to /usr/local/ then add your directory to it like:
WORKDIR /usr/local/
COPY go go/
or
WORKDIR /usr/local/go
COPY go ./
But if you want to add multiple folders, it will be annoying to add them like that, the only solution for now as I see it from my current issue is using COPY . . and exclude all unwanted directories and files in .dockerignore, let's say I got folders and files:
- src
- tmp
- dist
- assets
- go
- justforfun
- node_modules
- scripts
- .dockerignore
- Dockerfile
- headache.lock
- package.json
and I want to add src assets package.json justforfun go so:
in Dockerfile:
FROM galaxy:latest
WORKDIR /usr/local/
COPY . .
in .dockerignore file:
node_modules
headache.lock
tmp
dist
In this way, you ignore node_modules headache.lock tmp dist so they will not be added!
Or for more fun (or you like to confuse more people make them suffer as well :P) can be:
*
!src
!assets
!go
!justforfun
!scripts
!package.json
In this way you ignore everything, but exclude what you want to be copied or added only from the "ignore list".
It is a late answer but adding more ways to do the same covers even more cases.
You can use COPY. You need to specify the directory explicitly. It won't be created by itself
COPY go /usr/local/go
Reference: Docker CP reference
As the official docs state:
The directory itself is not copied, just its contents.
The trick is to concat in the <dest> path also the folder name, like this:
COPY src ./src
Even if ./src does not exist in the container yet, the command COPY internally creates it and copies the content of src into the new folder (which is ./src).
This can help if you want to add all files to a specified location
#ADD XML SUITE files
ADD src/test/resources/xmls/* /usr/share/tag/

Resources