Why is docker not completely deleting my file?

I am trying to build using:

FROM AS builder

COPY pythonnet/src/ pythonnet/src
WORKDIR /pythonnet/src/runtime
RUN dotnet build -f netstandard2.0 -p:DefineConstants="MONO_LINUX;XPLAT;PYTHON3;PYTHON37;UCS4;NETSTANDARD" Python.Runtime.15.csproj

# copy myApp csproj and restore
COPY src/myApp/*.csproj /src/myApp/
WORKDIR /src/myApp
RUN dotnet restore

# now copy everything else as separate docker step
# (copy to staging folder, remove csproj, and copy down - so we don't overwrite project above)
COPY src/myApp/ ./staging/src/myApp
RUN rm ./staging/src/myApp/*.csproj 
    && cp -r ./staging/* ./ 
    && rm -rf ./staging

This was working fine, and in Windows 10 still does, but in CentOS 7 I get:

Step 10/40 : RUN rm ./staging/src/myApp/*.csproj  && cp -r ./staging/* ./ && rm -rf ./staging
 ---> Running in 6b17ae0fae89
cp: cannot stat './staging/src/myApp/myApp.csproj': No such file or directory

Using ls instead of cp throws a similar file not found error, so it looks like Docker still knows about myApp.csproj but cannot see it since it has been removed.

Is there a way around this? I have tried using rsync but similar problems.

Stack Overflow Asked by schoon on November 15, 2021

4 Answers

4 Answers

You've very likely encountered a kernel bug that has been fixed a long time ago in more recent kernels. As of, CentOS 7 is based on the Linux Kernel 3.10, which is pretty old already and does not have good Docker support in regard to the storage backend (overlay filesystem).

CentOS tried to backport needed fixes and features into 3.10, but seems to not have succeeded fully when it comes to overlay support. There are multiple (slightly different) issues regarding this which you can find when searching for "CentOS 7 overlay driver" on the internet. All of them have in common that removing of files from parent overlays does not work as expected.

For me it looks like rm calls on files return success, even though the files are not fully removed. Directory listings (e.g. by ls or shell expansion as in your case) then still list the file, while accessing the file then fails (no matter if read, write or deletion of the file).

I assume that what you've seen is just another incarnation of these issues. You should either switch to CentOS 8 or upgrade your Kernel (which is not officially supported by CentOS as far as I understand). Or even more radical, switch to a distribution which is used more often in combination with Docker and generally offers more recent Kernels, e.g. Debian or Ubuntu.

Answered by Alexander Block on November 15, 2021

I simply ignored the issue by tacking on ;exit 0 on the offending lines. Not great, but does the job.

EDIT: This worked for me as I cannot upgrade the version of CemtOS. If you can, check out Alexander Block's answer.

Answered by schoon on November 15, 2021

cp -r will stop and fail with that cannot stat <file> message whenever the source is a symbolic link and the target of the link does not exist. It will not copy links to non-existent files.

So my guess is that after you run COPY src/myApp/ ./staging/src/myApp your file ./staging/src/myApp/myApp.csproj is a symbolic link to a non-existent file. Why the following RUN rm ./staging/src/*.csproj doesn't remove it and stays silent about that, I don't know the answer to that.

To help demonstrate my theory, see below showing cp failing on a symlink on Centos 7.

[547] $ docker run --rm -it centos:7
Unable to find image 'centos:7' locally
7: Pulling from library/centos
524b0c1e57f8: Pull complete 
Digest: sha256:e9ce0b76f29f942502facd849f3e468232492b259b9d9f076f71b392293f1582
Status: Downloaded newer image for centos:7
[[email protected] /]# ln -s /tmp/foo /tmp/bar 
[[email protected] /]# ls -l /tmp/foo
ls: cannot access /tmp/foo: No such file or directory
[[email protected] /]# ls -l /tmp/bar
lrwxrwxrwx 1 root root 8 Jul  6 05:44 /tmp/bar -> /tmp/foo
[[email protected] /]# cp /tmp/foo /tmp/1 
cp: cannot stat '/tmp/foo': No such file or directory
[[email protected] /]# cp /tmp/bar /tmp/2
cp: cannot stat '/tmp/bar': No such file or directory

Notice how you copy reports that it cannot stat either the source or destination of the symbolic link. It's the exact symptom you are seeing.

If you just want to get past this, you can try tar instead of cp or rsync.

Instead of

cp -r ./staging/* ./

use this instead:

tar -C ./staging -cf - . | tar -xf -

tar will happily copy symlinks that don't exist.

Answered by Brian Onn on November 15, 2021

I don't know specifically how to solve this problem as there's a lot of context in the filesystem that you haven't (and probably can't) share with us.

My suggestion on a strategy is that you:

  1. comment out all lines from the failing one 'til the end of the Dockerfile
  2. build the partial image
  3. docker exec -it [image] bash to jump into the image
  4. poke around and figure out what's going wrong
  5. repeat 1-4 until things work as expected

It's not as fun as a perfectly insightful answer of course but this is a relentlessly effective algorithm even if it's tedious and annoying.


My wild guess is that somehow, someway the linux machine doesn't have the file where it's expected for some reason and so it doesn't get copied into the image at all and that's why the docker build process can't find it. But there's no way to know without debugging the build process.

Answered by Mike Sandford on November 15, 2021

Add your own answers!

Related Questions

Function composition using Go syntax

1  Asked on July 28, 2020 by overexchange


Replacement to getch based code block in cpp

1  Asked on July 24, 2020 by sonu-ishaq


Combining if let statements in Rust

1  Asked on July 24, 2020 by deniz-basgoren


Ask a Question

Get help from others!

© 2021 All rights reserved.