-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Packages overwrite symlinked directories #53
Comments
I've had success with some modifications to existing logic:
And slapping the
|
this sounds like ubuntu does something that is not standard because we don't do any remapping of the files that comes with the deb packages? Do you how does apt handle this case (debian distribution of apt)? |
I'm not sure what would be considered "standard", but it definitely seems strange that e.g. in the So I would assume that apt/dpkg always resolves symlinks in their actions, and packages have been defined with this assumption. This also means that the symlink tree workaround that @alexconrey described wouldn't work in this case, since then the files that the package wanted to put in I'm wondering if the only way to solve this would be to be able to define symlinks like this on the |
Something along the lines of this yes, however i'd like to know how dpkg handles this. |
I think the problem here is that we are unaware of symlinks on any lower layers in a container. dpkg doesn't have to deal with this because you can tell tar to preserve symlinks |
Symlink tree as suggested by @alexconrey did not work for us unfortunately. I came up with this horrific workaround that at least works for our use case. # The tars created by rules_distroless have proper directories instead of symlinks
# which overwrite the symlinks in the base image. This will result in a broken image.
# To counter this, we move the contents of the supposedly symlinked sources to the
# symlink target directories, remove the source directories and create symlinks to the
# target directories.
#
# See: https://github.com/GoogleContainerTools/rules_distroless/issues/53
native.genrule(
name = "tester_layer_deb_remapped",
srcs = ["tester_layer_deb"],
outs = ["tester_layer_deb_remapped.tar"],
cmd = " ; ".join([
"SCRATCH=$$(mktemp -d )",
"REALOUT=$$(realpath $@)",
"mkdir -p $$SCRATCH/bundle",
"echo $$SCRATCH/bundle",
"tar -xf $(location :tester_layer_deb) -C $$SCRATCH/bundle",
"cd $$SCRATCH/bundle",
"[ -e bin ] && rsync -av bin/ usr/bin/ && rm -rf bin && ln -s /usr/bin bin || true",
"[ -e sbin ] && rsync -av sbin/ usr/sbin/ && rm -rf sbin && ln -s /usr/sbin sbin || true",
"[ -e lib ] && rsync -av lib/ usr/lib/ && rm -rf lib && ln -s /usr/lib lib || true",
"[ -e lib64 ] && rsync -av lib64/ usr/lib64/ && rm -rf lib64 && ln -s /usr/lib64 lib64 || true",
"[ -e var/run ] && rsync -av var/run/ run/ && rm -rf var/run && ln -s /run var/run || true",
"[ -e var/lock ] && rsync -av var/lock/ run/lock/ && rm -rf var/lock && ln -s /run/lock var/lock || true",
"tar -cf $$REALOUT .",
"rm -rf $$SCRATCH"
]),
) |
Same issue for Debian, which has /bin symlinked to /usr/bin. To show the problem, you can add the package "iproute2" on Debian 12 which has files /bin/ip /bin/ss. That breaks the /bin symlink, and we end up with a real /bin directory with only "ip" and "ss". |
I just tried this on a Debian 12 and the end result is the symlink bin -> usr/bin got removed, and a new bin directory is created with a single file in it (sh symlink). |
Not just Ubuntu, Debian 12 (bookworm) has it too:
You can see bin links to usr/bin, lib links to usr/lib, etc.
If you use debian apt install, it won't break those directory symlinks. Only rules_distroless does. |
I found a workaround. Create
|
I like this workaround. The library still remains pretty brittle in this respect, and I think without knowledge of the underlying filesystem, users still need to be a little careful. |
This doesn't seem to work. If I put If I put BTW, I did a manual test with a test tar file that has ./bin/test. I then use bsdtar -P option to exact this tar file to the skeleton symlinked directory structure. This is able to preserved the /bin symlink, and the file were ended up in /usr/bin. I am wondering if there is anything we can do to flatten multiple tar files into
|
I tried pkg_tar to flatten the tar files as suggested in bazel-contrib/rules_oci#23 I created 2 test tar files:
If I manually untar file1 and then file2, I get correct result:
If I use pkg_tar:
The resulting flatten.tar file looks like this:
If I extract the flatten.tar (tar -xvf ...), I get
As you can see, the symlink /bin got deleted, so pkg_tar doesn't seem to create the correct flatten tar file. BTW, if I use -P option with bsdtar, |
I am able to make my above flatten pkg_tar test work by setting the new pkg_tar create_parents attribute to False. This is because in my test file2.tar, I didn't include the parent directory:
If I were to include the parent directory in the file2.tar, setting create_parents to False won't be able to help :(
It's unfortunately that most of the tar files from deb packages includes the parent directory. eg: on Debian 12:
Checking data.tar.xz of iproute2:
My guess is the parent directory ./bin/ in the tar file caused symlinked "bin->usr/bin" got removed and actual "bin" directory being created. I don't know what's the best way to fix this. A few thoughts:
|
We had the same problem when our external image was upgraded from debian bullseye to bookworm, however we had some extra difficulties since 2 packages from Debian was put into the We had to combine both workarounds from this thread:
@oncilla thanks for your suggestion, to return the favor, add |
Maybe we can improve the "flatten" rule to add a new attribute flag to handle the Debian directory symlinks. For now, based on discussions in this thread, I created a custom flatten_debs rule:
Then in my BUILD file, I can use this custom rule:
|
I was informed by an Apple user that the workaround doesn't work on a MacBook.
|
I'm using a "clobber the symlinks in the ubuntu base image" recipe on the ubuntu base:
I've thought about re-assembling the ubuntu container's rootfs, but the clobbering layers work OK for now. Not relevant to this particular issue, but while I have a like minded audience: using an ubuntu base image with |
I found myself needing this as well, if anybody is willing to file an issue and send a reasonable PR, i'd be happy review and try to get it landed. As for the symlink case, i believe we could implement a mode where we ensure that no entry in the debian packages override these symlinks by rewriting some paths, like in the workarounds above. |
I'd be happy to review a PR if anyone is willing to send one. |
I'm not sure if this is a valid issue, perhaps it's a "wont fix", but I figured it's worth opening an issue for visibility in case other people run into it and perhaps to discuss workarounds.
When using
ubuntu:22.04
as a base image, a lot of the directories are symlinks, e.g./lib -> /usr/lib
, which is quite common. However the packages in the ubuntu repositories don't map into the target directories of the symlinks, but into the symlink itself. For example libc6 maps some .so libraries into/lib
and/lib64
.Because of this, when installing a package using
deb_index
the package will overwrite the/lib
symlink with a directory, breaking the connection to the libs that come with the base image, causing strange issues.I tried using
remap_paths
inpkg_tar
like this, but doesn't seem to do the trick:The text was updated successfully, but these errors were encountered: