12

It seems that docker build won't overwrite a file it has previously copied. I have a dockerfile with several copy instructions, and files touched in earlier COPY directives don't get overwritten by later ones.

A simplified example (although it also happens if the first copy is an entire directory that happens to contain the file in question):

COPY docker/config/file1.yml $BASE/config/thatfile.yml
COPY docker/config/file2.yml $BASE/config/thatfile.yml

After building this, $BASE/config/thatfile.yml contains the contents of file1.yml. Is there a way to get it to contain the contents of file2.yml?

My primary use case here is copying a whole folder of config files, and then replacing select config files for specific builds.

fields
  • 690
  • 1
  • 10
  • 21
  • 1
    I am unable to reproduce this issue in a recent stable release of docker-ce (19.03.2). I tried both with and without buildkit enabled. – BMitch Sep 26 '19 at 19:13

3 Answers3

7

I experienced this too, but after much testing discovered that I had a typo in one of my COPY directives' destination paths.

Double-check where those files are really going

-COPY nginx.conf /etc/ngnix/nginx.conf
+COPY nginx.conf /etc/nginx/nginx.conf
ti7
  • 205
  • 2
  • 9
1

Maybe you have mounted volume?

COPY local_file.txt /directory-in-container/

Above does not work, if /directory-in-container is a mounted volume.

guettli
  • 3,113
  • 14
  • 59
  • 110
1

I can't understand the behavior of your question. You must have a typo, use a different version, or you have a docker-compose volume which mounts something over something?

https://github.com/bor8/lolquadrat

git clone https://github.com/bor8/lolquadrat
cd lolquadrat/
docker build --no-cache .

Last output:

Step 1/6 : FROM busybox:latest
 ---> 19485c79a9bb
Step 2/6 : ARG BASE=/opt/hihi
 ---> Running in e4a01850931e
Removing intermediate container e4a01850931e
 ---> 193009cc4df9
Step 3/6 : COPY docker/config/file1.yml $BASE/config/thatfile.yml
 ---> bea7783ade65
Step 4/6 : RUN echo 'first thatfile:' && cat ${BASE}/config/thatfile.yml
 ---> Running in 201e86de06bc
first thatfile:
file1content
Removing intermediate container 201e86de06bc
 ---> ca7676a83a16
Step 5/6 : COPY docker/config/file2.yml $BASE/config/thatfile.yml
 ---> da5985cd90fb
Step 6/6 : RUN echo 'second thatfile:' && cat ${BASE}/config/thatfile.yml
 ---> Running in f70153917070
second thatfile:
file2content
Removing intermediate container f70153917070
 ---> 5a4b17a1e77e
Successfully built 5a4b17a1e77e

It can be clearly seen that the file thatfile.yml has the contents of the second file (file2content) after the second COPY command.

The running container shows file2content also. To test this, you can make a CMD tail -f /dev/null in the last line of your Dockerfile and then go in with docker exec -it <CONTAINER_ID_VIA_DOCKER_PS> /bin/sh. And show the content with cat thatfile.yml.

What I haven't fully tested yet is whether the same behavior exists for a folder (instead of file1.yml).

uav
  • 494
  • 3
  • 16