Repository navigation
Very specific set of circumstances leads to zero-byte (empty) file being created #1015
Description
- This is a bug report
- This is a feature request
- I searched existing issues before opening this one
The story
A few weeks ago, a bunch of tests in Rails code I have started failing in my Docker development environment. My dev environment is Arch so the actual set of libraries and things installed is very much a moving target.
Lots of digging around led me to create a repo that can reproduce the issue using only Ruby (no gems at all), at the lowest level possible. And it's really really weird. More information below.
Expected behavior
When copying a file in Ruby using the IO.copy_stream method, the file should be an identical copy.
Actual behavior
Under a very specific set of circumstances, the resulting file is 0 bytes.
I'm reasonably certain this is a Docker issue, because one of the conditions that needs to be true is that the source file is located on a mounted volume.
The conditions that need to be true for the IO.copy_stream operation to fail are:
- The source file is located on a Docker mounted volume and not the Docker container's own filesystem.
- The file is first copied into a Tempfile using the low-level Tempfile library.
- The tempfile is not touched (e.g. by utime or chmod) after the copy happens.
- That tempfile is then copied to another location using
IO.copy_stream. Copying it usingFile.writeandtempfile.readdoes not cause the issue.
Steps to reproduce the behavior
Please check out this repo: https://github.com/fishpercolator/reproduce-copystream and run the command in the README.
The output of this command on my env is:
open, local, File.write: 6744
open, local, IO.copy_stream: 6744
open, mounted, File.write: 6744
open, mounted, IO.copy_stream: 6744
tempfile + copy_file, local, File.write: 6744
tempfile + copy_file, local, IO.copy_stream: 6744
tempfile + copy_file, mounted, File.write: 6744
tempfile + copy_file, mounted, IO.copy_stream: 0
tempfile + copy_file + noop utime, mounted, File.write: 6744
tempfile + copy_file + noop utime, mounted, IO.copy_stream: 6744
tempfile + copy_file + noop chmod, mounted, File.write: 6744
tempfile + copy_file + noop chmod, mounted, IO.copy_stream: 6744
As you can see, the file is copied successfully if it is:
- copied directly from the mounted filesystem (not via a tempfile)
- copied via a tempfile from the container's own filesystem
- copied via a tempfile that has been touched with utime or chmod after the contents were inserted
- I do this same operation on an Ubuntu machine running Docker 19.03.9 ... i.e. it seems to be specific to something about my development machine
If any of the 4 statements above are true, the file copies fine. If all 4 are false, the file is created but it has a 0-byte size.
I've checked to see if the source filesystem of the mounted volume makes any difference but I get the same effect with eCryptfs, ext4 and tmpfs mountpoints.
Likewise I've tried different versions of Ruby to see if it was a regression in Ruby, but I can still reproduce the issue with the official Docker images of much older versions where I was certain it worked.
Does anyone have any ideas? Can anyone else reproduce this using my repo?
Output of docker version:
Client:
Version: 19.03.9-ce
API version: 1.40
Go version: go1.14.3
Git commit: 9d988398e7
Built: Tue May 19 22:11:18 2020
OS/Arch: linux/amd64
Experimental: false
Server:
Engine:
Version: 19.03.9-ce
API version: 1.40 (minimum version 1.12)
Go version: go1.14.3
Git commit: 9d988398e7
Built: Tue May 19 22:11:01 2020
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: v1.3.4.m
GitCommit: d76c121f76a5fc8a462dc64594aea72fe18e1178.m
runc:
Version: 1.0.0-rc10
GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd
docker-init:
Version: 0.18.0
GitCommit: fec3683
Output of docker info:
Client:
Debug Mode: false
Server:
Containers: 317
Running: 0
Paused: 0
Stopped: 317
Images: 415
Server Version: 19.03.9-ce
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: d76c121f76a5fc8a462dc64594aea72fe18e1178.m
runc version: dc9208a3303feef5b3839f4323d9beb36df0a9dd
init version: fec3683
Security Options:
seccomp
Profile: default
Kernel Version: 5.6.13-arch1-1
Operating System: Arch Linux
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 15.53GiB
Name: hulat
ID: G7VK:VZOA:T4LI:ATNZ:G55B:TDEA:23J2:YM2A:MOLK:U5QY:5MVT:CU7P
Docker Root Dir: /var/lib/docker
Debug Mode: false
Username: pedanticgit
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
Additional environment details (AWS, VirtualBox, physical, etc.)
It's a physical Dell XPS-13 9360 running Arch Linux. Arch doesn't have version numbers but all packages are up to date. Docker was installed from the Arch package with is built using this PKGBUILD script from the official Docker sources.
Activity
sarna commentedon May 22, 2020
I can reproduce this on current Manjaro (
5.6.12-1-MANJARO), getting the exact same output.docker versionoutput:docker infooutput:thaJeztah commentedon May 27, 2020
Both Arch linux and Manjaro are distributions that are not officially supported. Packages distributed by those distributions are maintained by those distributions and use differences in both the build process, build-time dependencies, as well as different versions of (e.g.) containerd and runc.
I'd recommend opening a ticket in the corresponding distribution's issue tracker for that reason.
I'm closing this issue because of the above, but feel free to continue the conversation
kthibodeaux commentedon Jun 23, 2020
@pedantic-git have you resolved this? did you create an issue elsewhere that I can follow? I'm seeing the same issue with the official ruby 2.6 docker image on an up to date manjaro install (updating an existing install doesnt seem to trigger the error)
pedantic-git commentedon Jun 23, 2020
@kthibodeaux I didn't create an issue anywhere else because I didn't have time to test it with the official build of Docker - have you been able to do that? It seems like even though it's happening to everyone on Arch/Manjaro it won't be supported here if it's only the Arch build of Docker.
ttrmw commentedon Dec 2, 2020
Did either of you get anywhere with this @pedantic-git @kthibodeaux? Got another example here, also on Arch.
pedantic-git commentedon Dec 2, 2020
Sadly not. I never got past the "Arch isn't supported" message above. I guess taking it up with the maintainers of the Arch package is the way to go.
Looks like that's Morten Linderud foxboron@archlinux.org if you'd like to raise a case and copy me in (quinn at fishpercolator.co.uk) but I'm not really even sure how one goes about doing that.
ahwatts commentedon Jan 21, 2021
I'm able to reproduce this on Fedora 33 using the package
moby-engine-19.03.13-1.ce.git4484c46.fc33.x86_64.I get the exact same output as @pedantic-git
My
docker info:pedantic-git commentedon Jan 23, 2021
@thaJeztah Now that this issue can be reproduced in an official build (albeit of Moby Engine rather than CE) is it possible this issue could warrant reopening?
AlexVKO commentedon Feb 16, 2021
@thaJeztah any chance to reopen this issue?
Same issue here(on ubunto 20.04), running images Ubuntu:18:04, Ubuntu:20.04, and Ruby:3.0.0.
bmhughes commentedon Mar 4, 2021
Same here on Fedora 33
makmic commentedon Mar 16, 2021
I just encountered the same issue and hope that it will be reopened and addressed here as it was far from easy to debug.
In the meantime I'll have to add this (Ruby) monkey patch to my docker setup:
pedantic-git commentedon Mar 20, 2021
@makmic There's actually no need to shell out to a separate and heavyweight
cpbinary to work around this issue. Even doing a no-op chmod or utime on the file before it is copied as in my example prevents this issue from occurring. Why, I have no idea, but it reliably does!ngoan98tv commentedon Mar 29, 2021
I'm facing to the same issue on CentOS.
dwarburt commentedon Mar 31, 2021
@pedantic-git I don't suppose you have an example no-op chmod or utime that's effective? and do you think they'd be faster than my current workaround?
Could this be an interaction with LUKS Full Disk Encryption? That's the main disk related difference on the affected system I have, when the same project is fine on all others.
43 remaining items
smartygus commentedon Mar 16, 2022
@emanuelhfarias this is great news!! Thanks for the heads up! :)
stanhu commentedon Mar 17, 2022
Yes, I think we can close this issue. I see that upgrading Docker for Mac to v4.6.0 upgraded the kernel to
5.10.104-linuxkitfrom5.10.76-linuxkit.stanhu commentedon Mar 17, 2022
Other related distribution notes:
RedHat: According to the bug report I filed, RedHat Enterprise 8 will see the fix in
kernel-4.18.0-368.el8. I've confirmed that as writen in the RHEL 8.5 release notes,kernel-4.18.0-348is the latest version available as of this writing.Google: Container OS 97 (https://cloud.google.com/container-optimized-os/docs/release-notes/m93) has upgraded to
5.10.90Ubuntu: No updates. When in doubt, use Ubuntu 20.04 instead of 18.04.
stanhu commentedon May 3, 2022
According to https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8-beta/html/8.6_release_notes/new-features#enhancement_kernel, RedHat 8.6 will be released on May 22, 2022 with
kernel-4.18.0-369, so this should fix it. RedHat 8.5 still has this issue.Fix tests in Docker dev environment
Fix tests in Docker dev environment
Fix tests in Docker dev environment
Fix tests in Docker dev environment
Fix tests in Docker dev environment
Fix tests in Docker dev environment
Fix tests in Docker dev environment
Fix tests in Docker dev environment
(RE-14082) Monkey-patch docker ezbake build Ruby
Use bit.ly to work around bug with htmlpreview where link with anchor…