Is it possible to optionally use the docker COPY instruction? - docker

I'm using the docker COPY instruction to copy files from <src> to <dest> as described in the documentation. However it is possible that there will be no <src> file which causes docker-compose build to fail. Like so:
Step 7 : COPY cts/application.properties /cts/
ERROR: Service 'redirector' failed to build: lstat cts/application.properties: no such file or directory
Is there a way to only copy the file if it's there or turn off the errors?

The only way to do that, is copying all files inside cts folder, for that, you can user COPY with a wildcard.
COPY cts/* /cts/
Or set your WORKDIR as cts, copy all files, and then set back your WORKDIR
WORKDIR cts/
ADD . /cts/
WORKDIR old_workdir_path
But, if you want to copy conditionally one file using COPY command, you can't.

Related

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

How can I get the current date in a Dockerfile?

I'm not sure if this approach is the best so I'm open to suggestions.
My code is structured as follows:
src/
program1.py
util.py
jarfile.jar
Dockerfile
The Dockerfile looks like this:
WORKDIR /app
COPY src /app
COPY jarfile.jar /app
WORKDIR /app/src
RUN python program1.py
The main program being invoked is program1.py which generates a directory at the same level of src of the format data_{today-date}, so data_20200122 for example. The JAR file is to be invoked by passing this data directory as a command line argument, such as java -jar jarfile.jar -inputData /app/data/data_20200122
Since the data directory is dynamic, how can I have Docker generate the dir name? I thought about using a shell script instead but I'm new to Docker and wanted to know if there's a better approach.

Multi-stage build cannot copy from previous stage - File not found

I have the docker file as follows:
FROM node:8 as builder
WORKDIR /usr/src/app
COPY ./src/register_form/package*.json .
RUN npm install
COPY ./src/register_form .
RUN yarn build
FROM tensorflow/tensorflow:1.10.0-gpu-py3
COPY --from=builder /usr/src/app/register_form/build/index.html /app/src/
WORKDIR /app
ENTRYPOINT ["python3"]
CMD ["/app/src/main.pyc"]
However, it cannot copy the index.html from the builder stage. Although when I list the folder in the first stage, the files are there.
The error is:
Step 8/22 : COPY --from=builder ./register_form/build/ /app/src/
COPY failed: stat /var/lib/docker/overlay2/5470e05501898502b3aa437639f975ca3e4bfb5a1e897281e62e07ab89866304/merged/register_form/build: no such file or directory
How can I fix this problem - the COPY --from=builder docker command?
I think you are misusing COPY command. As it is told in docs:
If src is a directory, the entire contents of the directory are
copied, including filesystem metadata.
Note: The directory itself is not copied, just its contents.
So your command COPY ./src/register_form . does NOT create register_form folder in container, but instead copies all contents. You can try adding:
RUN ls .
to your Dockerfile to make sure.
As noticed by #BMitch in comments, you can explicitly set destination folder name to achieve expected results:
COPY ./src/register_form/ register_form/

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.

What is the easiest method to copy files and directories in dockerfile

I tried to copy some files from source to destination (flask app) in a dockerfile but it seems things are not working as expected when building the image. With last 2 line showing:
Step 3 : COPY pkl_objects/* /home/jovyan/work/movieclassifier/pkl_objects/
No source files were specified
This is the docker file.
FROM jupyter/datascience-notebook
RUN pip install flask flask-wtf
COPY pkl_objects/* /home/jovyan/work/movieclassifier/pkl_objects/
COPY static/* /home/jovyan/work/movieclassifier/static/
COPY templates/* /home/jovyan/work/movieclassifier/templates/
COPY app.py /home/jovyan/work/movieclassifier
COPY reviews.sqlite /home/jovyan/work/movieclassifier
COPY vectorizer.py /home/jovyan/work/movieclassifier
WORKDIR /home/jovyan/work/movieclassifier
ENV FLASK_APP=app.py
# ENV FLASK_DEBUG=0
CMD ["flask", "run", "--host=0.0.0.0"]
Looks like there are no files in the pkl_objects folder, and when the wildcard (*) is expanded, it results in no source files being specified.
Maybe you could add an empty file in there, so that when the wildcard picks up files, you at least get one source file.
Example file could be: .nonempty or something like that.

Resources