How to COPY/ADD file into current WORKDIR in Dockerfile - docker

COPY/ADD statement requires 2 parameters. How can I add any file to current workdir that has been set in base image?
FROM company/app
COPY local.conf
Sure I can add WORKDIR statement before COPY to explicitly declare it. But that would be problematic if the workdir in company/app changes.

It turns out to be very simple. I just need to use dot to copy to current workdir.
COPY local.conf .
Still cannot figure out if this has some gotchas. But it just work as intended.

But that would be problematic if the workdir in company/app changes.
Then you would need to pass that workdir as build-time parameter in order to be able to change it from one docker build to the next.
See docker build --build-arg
You would need first to docker inspect company/app (inspec the image) to see if there are any changes.

Related

setting correct WORKDIR in a multi-stage build for docker

I wish to build a docker image that can start a container where I can use both node version 14 and lz4. The dockerfile I have so far is:
FROM node:14-alpine
WORKDIR /app
RUN apk update
RUN apk add --upgrade lz4
node --version and lz4 --help seem to run ok with the docker run command - but I wanted to ask whether there is a specific WORKDIR I should be using in the dockerfile to follow any best practices (if any exist), or does it not matter what I set the WORKDIR to? Note I'm not sure of all my future requirements, but I may need to use this image to build other images in the future, so I want to ensure WORKDIR is set appropriately.
WORKDIR should be set to set the working directory for the subsequent docker commands in dockerfile, which makes things a little easy to understand as the paths will be relative to the working directory.
By default, / root dir is the set working directory. Without setting any other workdir, all the commands can have absolute paths which make it even more easy to understand.
It doesn't really matter much. Besides, you could always change it for your future builds.

does dockerfile's instruction execute in order?

I'm a newbie to docker, sorry if my question is too basic. I saw dockerfile like this:
FROM diamol/maven AS builder
WORKDIR /usr/src/iotd
COPY pom.xml .
RUN mvn -B dependency:go-offline
COPY . .
RUN mvn package
FROM diamol/openjdk
WORKDIR /app
COPY --from=builder /usr/src/iotd/target/iotd-service-0.1.0.jar .
EXPOSE 80
ENTRYPOINT ["java", "-jar", "/app/iotd-service-0.1.0.jar"]
I'm confused about COPY . . instruction, what does the first period and second period COPY . . mean?
Also, if I want to copy all files of the current working directory from my host machine into the image, then how can I modify COPY . . so that the first period means currenty directory of my machine?
In the Dockerfile COPY directive, the last argument is the path inside the container, relative to the current WORKDIR. All of the preceding arguments are paths inside the build context, the host directory passed as an argument to docker build.
I want to copy all files of the current working directory from my host machine into the image, then how can I modify COPY . . ...?
You probably don't need to. So long as you docker build . naming the current directory . as the last argument, that's exactly what COPY . . does. That instruction means to copy . – the entirety of the build context, from the original host system – to . – the current directory, inside the image.
WORKDIR /usr/src/iotd # `COPY anything .` will put it here inside the image
COPY pom.xml . # Copy a single file into that WORKDIR
COPY . . # Copy the entire build context into the WORKDIR
I've mentioned "build context" a couple of times. That is the directory argument to docker build
docker build \
-t myname/some-image: tag \
. # <--- the build context directory
or that you specify in a docker-compose.yml file
version: '3.8'
services:
one:
build: ./one # <-- this directory
two:
build:
context: ./two # <-- this directory
except that the files mentioned in a .dockerignore file are removed first.
In the question title you also ask
does dockerfile's instruction execute in order?
They do. The newer BuildKit backend has some capability to execute build stages not necessarily in the order they're written, but it ensures that you get the same results as if all of the COPY and RUN instructions from a previous stage had run before a COPY --from=... in a later stage happens.
From my perspective, one of the best ways to know all the details for COPY and WORKDIR docker commands is to go through following official documentation.
You can either search for COPY and WORKDIR keywords on the home page at below first link or please refer to last two links and find all the details including examples.
https://docs.docker.com/engine/reference/builder/
https://docs.docker.com/engine/reference/builder/#copy
https://docs.docker.com/engine/reference/builder/#workdir

Can i reference a Dockerfile in a Dockerfile?

I have a Dockerfile that creates the build image I want to use here: ~/build/Dockerfile then I use a standard image to deploy
The image built from ~/build/Dockerfile is not Published anywhere, I know I can simply copy paste the one Dockerfile into the other, however it would be better if I could simply reference it so..
Is it possible to somehow reference the Dockerfile itself when deploying?
like so:
FROM [insert something that creates an image using ~/build/Dockerfile] as build-env
... build operations ....
FROM some-image
COPY --from=build-env /built .
ENTRYPOINT [blah]
This won't work but is there some other way to accomplish this?
No you can't do it because you have to provide an image to FROM.
Change the COPY line to
COPY --from=step1 /built .
And write a script to build your image:
cd path1
docker build -t step1 .
cd path2
docker build -t final_image .
(if you don't want to hard code step1 in the Dockerfile, replace it with a var and call with ARG)
Generally things in Docker space like the docker run command and the FROM directive will use a local image if it exists; it doesn't need to be pushed to a repository. That means you can build your first image and refer to it in the later Dockerfile by name. (There's no way to refer to the other Dockerfile per se.)
Newer versions of Docker have an extended form of the Dockerfile COPY command which
accepts a flag --from=<name|index>.... 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.
So if you ahead of time run
docker build -t build-env ~/build
then the exact syntax you show in your proposed Dockerfile will work
FROM some-image
COPY --from=build-env /built .
and it doesn't matter that the intermediate build image isn't actually pushed anywhere.

Copy specific file first and the copy all in Dockerfile

The following is what I have for my Dockerfile:
FROM node:4.6.0
WORKDIR /src
COPY node_modules/ /src/node_modules
COPY . /src/
CMD ["/bin/bash"]
I wanted to make it efficient such that node modules are copied only when there's any change in the directory. Otherwise, I want only the source files are copied into the image.
Would this work as intended?
This will copy twice. Docker cache looks at the current command and previous layer. If something has changed in the Docker context for the current command it will run. It does not use a partial cache to run.

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