Azure / azure-functions-docker

This repo contains the base Docker images for working with azure functions
MIT License
247 stars 115 forks source link

Request for dotnet alpine based image support #901

Open jlee58tw opened 1 year ago

jlee58tw commented 1 year ago

Issue Description

I am writing to submit a feature request regarding the vulnerability issues present in the current image. As outlined in the following references, there have been concerns raised about vulnerability risks associated with the existing Debian based image.

Building the Custom Alpine based Image

As the previous comment, I believe that publishing alpine based would be a good solution.

To demonstrate the feasibility of this solution, I have successfully built a custom image using the following Dockerfile according to this tutorial.

some highlights:

# Build the runtime from source
ARG HOST_VERSION=4.21.0
FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine3.17 AS runtime-image
ARG HOST_VERSION

ENV PublishWithAspNetCoreTargetManifest=false

# install alpine-pkg-glibc to solve dependency issue
# https://github.com/grpc/grpc/issues/18428#issuecomment-535041155
RUN apk add --no-cache curl
RUN curl -s -qL https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub -o /etc/apk/keys/sgerrand.rsa.pub
RUN curl -s -qL https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.32-r0/glibc-2.32-r0.apk -o glibc-2.32-r0.apk
RUN apk add --no-cache --force-overwrite glibc-2.32-r0.apk

RUN BUILD_NUMBER=$(echo ${HOST_VERSION} | cut -d'.' -f 3) && \
    git clone --branch v${HOST_VERSION} https://github.com/Azure/azure-functions-host /src/azure-functions-host && \
    cd /src/azure-functions-host && \
    # dotnet restore src/WebJobs.Script.WebHost/WebJobs.Script.WebHost.csproj /p:IsDockerBuild=true && \
    # dotnet publish src/WebJobs.Script.WebHost/WebJobs.Script.WebHost.csproj -c Release -o /azure-functions-host && \
    dotnet publish -v q /p:BuildNumber=$BUILD_NUMBER /p:CommitHash=$HOST_COMMIT src/WebJobs.Script.WebHost/WebJobs.Script.WebHost.csproj -c Release --output /azure-functions-host --runtime alpine-x64 --self-contained -p:PublishReadyToRun=false && \
    mv /azure-functions-host/workers /workers && mkdir /azure-functions-host/workers && \
    rm -rf /root/.local /root/.nuget /src

RUN apk update && \
    apk add gnupg wget unzip && \
    EXTENSION_BUNDLE_VERSION_V2=2.24.0 && \
    EXTENSION_BUNDLE_FILENAME_V2=Microsoft.Azure.Functions.ExtensionBundle.${EXTENSION_BUNDLE_VERSION_V2}_linux-x64.zip && \
    wget https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V2/$EXTENSION_BUNDLE_FILENAME_V2 && \
    mkdir -p /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V2 && \
    unzip /$EXTENSION_BUNDLE_FILENAME_V2 -d /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V2 && \
    rm -f /$EXTENSION_BUNDLE_FILENAME_V2 &&\
    EXTENSION_BUNDLE_VERSION_V3=3.22.0 && \
    EXTENSION_BUNDLE_FILENAME_V3=Microsoft.Azure.Functions.ExtensionBundle.${EXTENSION_BUNDLE_VERSION_V3}_linux-x64.zip && \
    wget https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V3/$EXTENSION_BUNDLE_FILENAME_V3 && \
    mkdir -p /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V3 && \
    unzip /$EXTENSION_BUNDLE_FILENAME_V3 -d /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V3 && \
    rm -f /$EXTENSION_BUNDLE_FILENAME_V3 &&\
    EXTENSION_BUNDLE_VERSION_V4=4.5.0 && \
    EXTENSION_BUNDLE_FILENAME_V4=Microsoft.Azure.Functions.ExtensionBundle.${EXTENSION_BUNDLE_VERSION_V4}_linux-x64.zip && \
    wget https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V4/$EXTENSION_BUNDLE_FILENAME_V4 && \
    mkdir -p /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V4 && \
    unzip /$EXTENSION_BUNDLE_FILENAME_V4 -d /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V4 && \
    rm -f /$EXTENSION_BUNDLE_FILENAME_V4 &&\
    find /FuncExtensionBundles/ -type f -exec chmod 644 {} \;

FROM mcr.microsoft.com/dotnet/runtime-deps:6.0-alpine3.17
ARG HOST_VERSION

ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    HOME=/home \
    FUNCTIONS_WORKER_RUNTIME=dotnet \
    DOTNET_USE_POLLING_FILE_WATCHER=true \
    HOST_VERSION=${HOST_VERSION} \
    ASPNETCORE_CONTENTROOT=/azure-functions-host

# Fix from https://github.com/GoogleCloudPlatform/google-cloud-dotnet-powerpack/issues/22#issuecomment-729895157
RUN apk update && \
    apk add libc-dev && \
    apk upgrade libssl3 libcrypto3

COPY --from=runtime-image [ "/azure-functions-host", "/azure-functions-host" ]
COPY --from=runtime-image [ "/FuncExtensionBundles", "/FuncExtensionBundles" ]

CMD [ "/azure-functions-host/Microsoft.Azure.WebJobs.Script.WebHost" ]

Feature Request

I kindly request the Azure Functions Docker team to consider integrating support for an alpine based image in the official release. By providing an official alpine based image, developers can benefit from enhanced security and reduced vulnerability risks when deploying Azure Functions in containerized environments.

Regards, Jerry

vijaykumar911 commented 1 year ago

Hi @jlee58tw will update you

vijaykumar911 commented 1 year ago

Alpine Linux is for its focus on security and minimal attack surface. Its small size and approach to reduce the risk of vulnerabilities and make it easier to maintain a secure environment. By leveraging the Alpine base image, developers can benefit from the optimized and hardened packages provided by Alpine Linux. This helps mitigate potential vulnerabilities and ensures a more secure execution environment for Azure Functions

jlee58tw commented 1 year ago

@vijaykumar911 I second with you. alpine is an excellent choice. I'm happy to assist you in supporting it with the dotnet image.

jscottSwift commented 9 months ago

Agreed - they should do this for all of their image offerings. We have been working at my company to eliminate all debian-based images where possible.

SymbioticKilla commented 6 months ago

No christmas miracle? Perhaps as easter miracle 😁

ekbaramundi commented 5 months ago

Yes please.

smolesen commented 5 months ago

@jlee58tw Been trying to use your docker file as basis for one running .net 8 and Azure Durable Function isolated. However when I run the container I get the error:

System.IO.IOException: Error loading native library "/home/site/wwwroot/.azurefunctions/libgrpc_csharp_ext.x64.so". Error loading shared library ld-linux-x86-64.so.2: No such file or directory (needed by /home/site/wwwroot/.azurefunctions/libgrpc_csharp_ext.x64.so)

Any change you have tried the same and found a solution? My dockerfile looks like this:


# Build the runtime from source
ARG HOST_VERSION=4.30.0
FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine3.19 AS runtime-image
ARG HOST_VERSION

ENV PublishWithAspNetCoreTargetManifest=false

# install alpine-pkg-glibc to solve dependency issue
# https://github.com/grpc/grpc/issues/18428#issuecomment-535041155
RUN apk add --no-cache curl
RUN curl -s -qL https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub -o /etc/apk/keys/sgerrand.rsa.pub
RUN curl -s -qL https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.32-r0/glibc-2.32-r0.apk -o glibc-2.32-r0.apk
RUN apk add --no-cache --force-overwrite glibc-2.32-r0.apk

RUN BUILD_NUMBER=$(echo ${HOST_VERSION} | cut -d'.' -f 3) && \
    git clone --branch v${HOST_VERSION} https://github.com/Azure/azure-functions-host /src/azure-functions-host && \
    cd /src/azure-functions-host && \
    # dotnet restore src/WebJobs.Script.WebHost/WebJobs.Script.WebHost.csproj /p:IsDockerBuild=true && \
    # dotnet publish src/WebJobs.Script.WebHost/WebJobs.Script.WebHost.csproj -c Release -o /azure-functions-host && \
    dotnet publish -v q /p:BuildNumber=$BUILD_NUMBER /p:CommitHash=$HOST_COMMIT src/WebJobs.Script.WebHost/WebJobs.Script.WebHost.csproj -c Release --output /azure-functions-host --runtime alpine-x64 --self-contained -p:PublishReadyToRun=false && \
    mv /azure-functions-host/workers /workers && mkdir /azure-functions-host/workers && \
    rm -rf /root/.local /root/.nuget /src

RUN apk update && \
    apk add gnupg wget unzip && \
    EXTENSION_BUNDLE_VERSION_V2=2.24.0 && \
    EXTENSION_BUNDLE_FILENAME_V2=Microsoft.Azure.Functions.ExtensionBundle.${EXTENSION_BUNDLE_VERSION_V2}_linux-x64.zip && \
    wget https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V2/$EXTENSION_BUNDLE_FILENAME_V2 && \
    mkdir -p /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V2 && \
    unzip /$EXTENSION_BUNDLE_FILENAME_V2 -d /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V2 && \
    rm -f /$EXTENSION_BUNDLE_FILENAME_V2 &&\
    EXTENSION_BUNDLE_VERSION_V3=3.22.0 && \
    EXTENSION_BUNDLE_FILENAME_V3=Microsoft.Azure.Functions.ExtensionBundle.${EXTENSION_BUNDLE_VERSION_V3}_linux-x64.zip && \
    wget https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V3/$EXTENSION_BUNDLE_FILENAME_V3 && \
    mkdir -p /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V3 && \
    unzip /$EXTENSION_BUNDLE_FILENAME_V3 -d /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V3 && \
    rm -f /$EXTENSION_BUNDLE_FILENAME_V3 &&\
    EXTENSION_BUNDLE_VERSION_V4=4.12.0 && \
    EXTENSION_BUNDLE_FILENAME_V4=Microsoft.Azure.Functions.ExtensionBundle.${EXTENSION_BUNDLE_VERSION_V4}_linux-x64.zip && \
    wget https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V4/$EXTENSION_BUNDLE_FILENAME_V4 && \
    mkdir -p /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V4 && \
    unzip /$EXTENSION_BUNDLE_FILENAME_V4 -d /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V4 && \
    rm -f /$EXTENSION_BUNDLE_FILENAME_V4 &&\
    find /FuncExtensionBundles/ -type f -exec chmod 644 {} \;

FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-alpine3.19
ARG HOST_VERSION

ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    HOME=/home \
    FUNCTIONS_WORKER_RUNTIME=dotnet \
    DOTNET_USE_POLLING_FILE_WATCHER=true \
    HOST_VERSION=${HOST_VERSION} \
    ASPNETCORE_CONTENTROOT=/azure-functions-host

# Fix from https://github.com/GoogleCloudPlatform/google-cloud-dotnet-powerpack/issues/22#issuecomment-729895157
RUN apk update && \
    apk add libc-dev && \
    apk upgrade libssl3 libcrypto3

COPY --from=runtime-image [ "/azure-functions-host", "/azure-functions-host" ]
COPY --from=runtime-image [ "/FuncExtensionBundles", "/FuncExtensionBundles" ]

CMD [ "/azure-functions-host/Microsoft.Azure.WebJobs.Script.WebHost" ]
danjer2 commented 5 months ago

Struggling with the same problem, staying up do date with MS images and still having critical vulnerabilities. On top of that, I just noticed that there it has the NuGet package marain that uses AGPL license. We're using the NodeJS image, so I'm guessing this package is part of the functions runtime or an extension bundle.

smolesen commented 5 months ago

Came across this PR... will try to see if I can make it work with .net 8 tomorrow... https://github.com/Azure/azure-functions-docker/pull/949/files

smolesen commented 5 months ago

Think I managed to make it work with the above Docker file, and a couple of small changes....

# Build the runtime from source
ARG HOST_VERSION=4.30.0
FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine3.19 AS runtime-image
ARG HOST_VERSION

ENV PublishWithAspNetCoreTargetManifest=false

RUN apk update && apk upgrade && \
    apk --no-cache add git gnupg wget unzip grpc grpc-plugins protobuf protobuf-dev protoc

ENV GRPC_PROTOC_PLUGIN=/usr/bin/grpc_csharp_plugin
ENV PROTOBUF_PROTOC=/usr/bin/protoc

RUN BUILD_NUMBER=$(echo ${HOST_VERSION} | cut -d'.' -f 3) && \
    git clone --branch v${HOST_VERSION} https://github.com/Azure/azure-functions-host /src/azure-functions-host && \
    cd /src/azure-functions-host && \
    HOST_COMMIT=$(git rev-list -1 HEAD) && \
    dotnet publish -v q /p:BuildNumber=$BUILD_NUMBER /p:CommitHash=$HOST_COMMIT src/WebJobs.Script.WebHost/WebJobs.Script.WebHost.csproj -c Release --output /azure-functions-host --runtime linux-musl-x64 && \
    mv /azure-functions-host/workers /workers && mkdir /azure-functions-host/workers && \
    rm -rf /root/.local /root/.nuget /src

RUN EXTENSION_BUNDLE_VERSION_V2=2.27.0 && \
    EXTENSION_BUNDLE_FILENAME_V2=Microsoft.Azure.Functions.ExtensionBundle.${EXTENSION_BUNDLE_VERSION_V2}_linux-x64.zip && \
    wget https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V2/$EXTENSION_BUNDLE_FILENAME_V2 && \
    mkdir -p /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V2 && \
    unzip /$EXTENSION_BUNDLE_FILENAME_V2 -d /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V2 && \
    rm -f /$EXTENSION_BUNDLE_FILENAME_V2 &&\
    EXTENSION_BUNDLE_VERSION_V3=3.26.0 && \
    EXTENSION_BUNDLE_FILENAME_V3=Microsoft.Azure.Functions.ExtensionBundle.${EXTENSION_BUNDLE_VERSION_V3}_linux-x64.zip && \
    wget https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V3/$EXTENSION_BUNDLE_FILENAME_V3 && \
    mkdir -p /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V3 && \
    unzip /$EXTENSION_BUNDLE_FILENAME_V3 -d /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V3 && \
    rm -f /$EXTENSION_BUNDLE_FILENAME_V3 &&\
    EXTENSION_BUNDLE_VERSION_V4=4.12.0 && \
    EXTENSION_BUNDLE_FILENAME_V4=Microsoft.Azure.Functions.ExtensionBundle.${EXTENSION_BUNDLE_VERSION_V4}_linux-x64.zip && \
    wget https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V4/$EXTENSION_BUNDLE_FILENAME_V4 && \
    mkdir -p /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V4 && \
    unzip /$EXTENSION_BUNDLE_FILENAME_V4 -d /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V4 && \
    rm -f /$EXTENSION_BUNDLE_FILENAME_V4 &&\
    find /FuncExtensionBundles/ -type f -exec chmod 644 {} \;

FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-alpine3.19
ARG HOST_VERSION

ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    HOME=/home \
    FUNCTIONS_WORKER_RUNTIME=dotnet \
    DOTNET_USE_POLLING_FILE_WATCHER=true \
    HOST_VERSION=${HOST_VERSION} \
    ASPNETCORE_CONTENTROOT=/azure-functions-host

RUN apk update && \
    apk add libc-dev && \
    apk add libc6-compat && \
    apk upgrade libssl3 libcrypto3
COPY --from=runtime-image [ "/azure-functions-host", "/azure-functions-host" ]
COPY --from=runtime-image [ "/FuncExtensionBundles", "/FuncExtensionBundles" ]

CMD [ "/azure-functions-host/Microsoft.Azure.WebJobs.Script.WebHost" ]
FinVamp1 commented 4 months ago

Struggling with the same problem, staying up do date with MS images and still having critical vulnerabilities. On top of that, I just noticed that there it has the NuGet package marain that uses AGPL license. We're using the NodeJS image, so I'm guessing this package is part of the functions runtime or an extension bundle.

I looked at the AGPL 3.0 package and this comes from Marain.Net (github.com) which we don’t take a dependency on as far as I can tell.

I scanned the latest Node 4 Slim image and the 4.28.4 image for this and I don’t see this as a license issue to be addressed. Do you have steps to reproduce this?

trivy image mcr.microsoft.com/azure-functions/node:4.28.4-node18-slim --scanners license --license-full --license-confidence-level 0.8

If there are other steps I should follow then let me know. I tested also with a JFrog Xray scan using the Docker Desktop extension.

trivy image mcr.microsoft.com/azure-functions/node:4.28.4-node18-slim --scanners license --license-full --license-confidence-level 0.8

berubejp commented 1 month ago

Any news on this? Funcapp docker images have a lot if critical/high known vulnerabilities at anytime. I would appreciate some love from MS :) Still having issues understanding why funcapp docker images are not within the "dotnet/dotnet-docker" repo like the others... Kinda look like they're not as important.

jscott5200 commented 1 month ago

I tried using smolesen's approach above. Seems like it technically works, but the resulting image is huge (a few gbs), and that's before I add in any of the application code.

Had to move on to other priority projects, hope to circle back to this eventually.