Skip to content
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

Add more flexible Dockerfile #4387

Closed
wants to merge 1 commit into from
Closed

Conversation

richlander
Copy link
Member

@richlander richlander commented Feb 3, 2023

This Dockerfile has two basic modes:

For x64, by default:

docker build -t aspnetapp -f Dockerfile.debian .

For Arm64:

docker build -t aspnetapp -f Dockerfile.debian --build-arg ARCH=arm64v8 --build-arg RID=linux-arm64 .

This isn't super pretty, but it works. Also, this is showing the model. Clearly, you can pivot between x64 and Arm64 being the default.

One option is to make one symbol work for both ARCH and RID. That's part of what makes this super ugly. I think the easiest thing might be to push x64 and arm64 tags to align with our RIDs, as they are amd64 and arm64v8, today.

@mthalman
Copy link
Member

mthalman commented Feb 3, 2023

I'd prefer a solution that made use of docker's --platform option rather than inventing new ARGs. I think it's better to try to find a solution that can fit with that option to better integrate with the ecosystem, especially buildx and building multi-arch images.

e.g. if somebody ran a build like this:
docker build --platform linux/arm64 .

But that still requires emulation if using a multi-arch tag for the sdk stage. Because if you had FROM mcr.microsoft.com/dotnet/sdk:7.0, you'd end up with an arm64 sdk image which may not match the arch of the machine it's being run on. This really demonstrates the need for emulation to work in the scenario of building a project.

An alternative is to explicitly set the architecture of the sdk tag:

FROM mcr.microsoft.com/dotnet/sdk:7.0-jammy-amd64 AS build

ARG TARGETARCH

RUN arch=$TARGETARCH \
    && if [ "$arch" = "amd64" ]; then arch="x64"; fi \
    && echo "linux-$arch" > /tmp/rid

WORKDIR /source

COPY *.csproj .
RUN dotnet restore -r $(cat /tmp/rid)

COPY . .
RUN dotnet publish -c Release -f net7.0 -o /app -r $(cat /tmp/rid) --self-contained false

Of course, that limits the cross-platform nature of the Dockerfile wrt to the build machine: it can only be built on an x64 machine. But on the other hand, it can be used to produce images for multiple architectures.

@richlander
Copy link
Member Author

That brings us back to the base issue. We don't support the --platform tag, at least not in a way that results in using QEMU.

I still claim that my proposal, with the secondary proposal of moving to a single ARG` is the best option. The bash-foo is inventive, but pretty hostile to the UX. I think we either have to create aliases in our container images or the RID graph. I believe that the former is far easier.

@mthalman
Copy link
Member

mthalman commented Feb 3, 2023

That brings us back to the base issue. We don't support the --platform tag, at least not in a way that results in using QEMU.

Yes, as long as you avoid executing dotnet, using --platform is fine. I used the pattern I proposed above at https://github.com/mthalman/dredge/blob/main/src/Valleysoft.Dredge/Dockerfile. That works fine for me because I don't use the Dockerfile for developer scenarios, meaning that I don't need to worry about supporting different architecture hosts; I only care about the architecture of the build machine. This lets me set the platforms of my target images idiomatically: https://github.com/mthalman/dredge/blob/b4e91e40384a186a843d09707f62ac4c91602a36/.github/workflows/release.yml#L150. Most importantly, this usage allows me to get multi-arch tags for free by using the --platform option. With your custom ARGs proposal, you're on your own for producing multi-arch tags.

@richlander
Copy link
Member Author

I think I'm conflating things. Is --platform only used for MA tags to select the right concrete tag? If so (and your example suggests that), then I misunderstood what was happening. I thought --platform was causing QEMU to kick in, but I can see that --platform is a step earlier in the causal chain.

I think you are saying:

  • Use --platform + our MA tags to determine the final image being produced.
  • Use an actual build-arg only if you want to pivot the SDK from one native tag to another.

I can change the sample after you validate my understanding.

That still leaves the question of how to make the Dockerfile prettier. My proposal still has better UX. Disagree? I'm not enthusiastic about getting people to adopt your (clever) pattern as general guidance.

@richlander
Copy link
Member Author

OK. I need to play with this more.

@richlander
Copy link
Member Author

richlander commented Feb 4, 2023

I didn't realize these ENVs were set.

https://docs.docker.com/build/building/multi-platform/

$ cat Dockerfile
FROM debian

ARG TARGETPLATFORM
ARG TARGETARCH
ARG TARGETOS
ARG BUILDPLATFORM
ARG BUILDARCH
ARG BUILDOS
RUN echo "I am building on $BUILDPLATFORM, targeting $TARGETPLATFORM"
RUN echo "I am building on ${BUILDOS} and ${BUILDARCH}"
RUN echo "I am targeting ${TARGETOS} and ${TARGETARCH}"
$ $ docker build -t app --platform linux/arm64 .
[+] Building 6.5s (9/9) FINISHED
 => [internal] load build definition from Dockerfile                                                               0.0s
 => => transferring dockerfile: 38B                                                                                0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [internal] load metadata for docker.io/library/debian:latest                                                   2.8s
 => [auth] library/debian:pull token for registry-1.docker.io                                                      0.0s
 => [1/4] FROM docker.io/library/debian@sha256:92277f7108c432febe41beffd367dbb6dac60b9fbfe517c77208e6457eafe22b    1.8s
 => => resolve docker.io/library/debian@sha256:92277f7108c432febe41beffd367dbb6dac60b9fbfe517c77208e6457eafe22b    0.0s
 => => sha256:acd40516036b5b8bda9c0b171922c9720e3438aeb621ac66fe51bb35e2e615c9 529B / 529B                         0.0s
 => => sha256:e2e67f3d9c8ebadc3bea4ce11c1cd4f71fc8801cf98d053b9532a4faa1a45cbf 1.48kB / 1.48kB                     0.0s
 => => sha256:fac7262b6510529638951e16807cf1758f42c892ed924e334c27bb8bbcf7d7c2 53.68MB / 53.68MB                   0.7s
 => => sha256:92277f7108c432febe41beffd367dbb6dac60b9fbfe517c77208e6457eafe22b 1.85kB / 1.85kB                     0.0s
 => => extracting sha256:fac7262b6510529638951e16807cf1758f42c892ed924e334c27bb8bbcf7d7c2                          0.9s
 => [2/4] RUN echo "I am building on linux/amd64, targeting linux/arm64"                                         0.5s
 => [3/4] RUN echo "I am building on linux and amd64"                                                              0.6s
 => [4/4] RUN echo "I am targeting linux and arm64"                                                                0.6s
 => exporting to image                                                                                             0.1s
 => => exporting layers                                                                                            0.1s
 => => writing image sha256:a3416190b8ab161b2d6786f4dc9f54d638180dd669c2a987a0abd6d18386a7ab                       0.0s
 => => naming to docker.io/library/app

Grab Dockerfile from https://gist.github.com/richlander/70cde3f0176d36862af80c41722acd47

@richlander
Copy link
Member Author

I am going to start this over again.

@richlander richlander closed this Feb 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants