docker / docker/buildx

Windows: buildx breaks symlinks when copying them

Open
#373 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
4.5k
Forks
682
Avg merge
2d 14h
Merged PRs (30d)
29

Description

docker buildx breaks Windows symlinks when copying them over from another Windows image by prepending Files\ to their target. If the original symlink targets are absolute paths, they become unusable.

For example, let's have this Dockerfile and build a Windows image on a Windows node:

FROM mcr.microsoft.com/windows/nanoserver:1809

ADD https://github.com/kubernetes-sigs/windows-testing/raw/master/images/busybox/busybox.exe /bin/busybox.exe
USER ContainerAdministrator
RUN cd C:\bin && FOR /f "tokens=*" %i IN ('.\busybox --list') DO mklink .\%i.exe C:\bin\busybox.exe

The Dockerfile will basically create a C:\bin folder and create symlinks to C:\bin\busybox.exe. We can check that the symlinks are correct:

docker run claudiubelu/sample:1.29.0 cmd /S /C "dir C:\\bin"
 Volume in drive C has no label.
 Volume Serial Number is AEAD-02B2

 Directory of C:\bin

08/31/2020  04:34 PM    <DIR>          .
08/31/2020  04:34 PM    <DIR>          ..
08/31/2020  04:34 PM    <SYMLINK>      ar.exe [C:\bin\busybox.exe]
08/31/2020  04:34 PM    <SYMLINK>      arch.exe [C:\bin\busybox.exe]
...

Then, we're copying C:\bin to another image with docker buildx on a Linux node with the following Dockerfile:

ARG BASEIMAGE
ARG REGISTRY

FROM $REGISTRY/sample:1.29.0 as helper
FROM $BASEIMAGE

COPY --from=helper /bin /bin

# NOTE(claudiub): docker buildx sets the PATH env variable to a Linux-like PATH, which is not desirable.
ENV PATH="C:\bin;C:\Windows\System32;C:\Windows;"

ENTRYPOINT ["cmd.exe", "/s", "/c"]

The command is: docker buildx build --no-cache --pull --output=type=registry --platform windows/amd64 --build-arg BASEIMAGE=mcr.microsoft.com/windows/nanoserver:1809 --build-arg REGISTRY=claudiubelu -t claudiubelu/symlink-sample:1.29 .

Checking the symlinks in the newly image, we notice that Files\ is prepended to their targets:

docker run claudiubelu/symlink-sample:1.29 dir C:\bin
 Volume in drive C has no label.
 Volume Serial Number is AEAD-02B2

 Directory of C:\bin

08/31/2020  04:44 PM    <DIR>          .
08/31/2020  04:44 PM    <DIR>          ..
08/31/2020  04:34 PM    <SYMLINK>      ar.exe [Files\C:\bin\busybox.exe]
08/31/2020  04:34 PM    <SYMLINK>      arch.exe [Files\C:\bin\busybox.exe]
...

One workaround for this is to make the original symlinks with relative paths (to busybox.exe).Files\ will still be prepended to the target paths, but the busybox binary could be copied to C:\bin\Files\busybox.exe, which means that they will point to something that exists:

ARG BASEIMAGE
ARG REGISTRY

FROM $REGISTRY/sample:1.29.0 as helper
FROM $BASEIMAGE

COPY --from=helper /bin /bin

# NOTE(claudiub): Unfortunately, docker buildx has some issues copying over Windows symlinks.
# "Files/" is always prepended to the symlink target. The symlinks themselves are relative paths,
# so, in order to make use of them, we can simply add a busybox binary to C:\bin\Files\busybox.exe.
COPY --from=helper /bin/busybox.exe /bin/Files/

# NOTE(claudiub): docker buildx sets the PATH env variable to a Linux-like PATH, which is not desirable.
ENV PATH="C:\bin;C:\Windows\System32;C:\Windows;"

ENTRYPOINT ["cmd.exe", "/s", "/c"]

Docker buildx version: github.com/docker/buildx v0.4.1-25-ge24e04b e24e04be572034efbcc9e20fcf720d6b10646487

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the issue with the two Dockerfiles, the Windows image, and the documented buildx command. Trace the COPY --from handling of Windows symlink targets and compare the resulting links with the source image; done means absolute targets are preserved without the unwanted Files prefix.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, go
Domain
build-system, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.