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

dotnet isolated docker: docker run -e PORT=80 messes with the function host command line arguments #524

Closed
metoule opened this issue Jul 1, 2021 · 8 comments · Fixed by #583
Assignees

Comments

@metoule
Copy link

metoule commented Jul 1, 2021

When a Linux function app uses a custom docker image, the docker container is ran with the -e PORT=80 option.
That creates an issue with the gRPC configuration, that ALSO uses the Port variable, and which is passed as a command line parameter.

We therefore have two conflicting Port options:

  • the one from the environment variable
  • the one from the command line

That's an issue, because the environment variable value takes precedence over the command line value, and therefore the gRPC connection tries to connect to port 80 instead of the actual gRPC port.

@metoule
Copy link
Author

metoule commented Jul 1, 2021

I have a workaround: remove the configuration sources, and re-add them in the proper order, but something should be done to avoid having multiple meanings for the same option name.

public static void Main(string[] args)
{
    // Linux: remove the first argument if it's the executable name
    var newArgs = args;
    if (args.Length > 0 && args[0] == typeof(Program).Assembly.Location)
    {
        newArgs = new string[args.Length - 1];
        Array.Copy(args, 1, newArgs, 0, args.Length - 1);
    }

    var host = Host
        .CreateDefaultBuilder()
        .ConfigureFunctionsWorkerDefaults()
        .ConfigureAppConfiguration(builder => 
        {
            // reorder the configuration source, so that the command line arguments take precedences over the env variables
            var sources = builder.Sources;
            var toRemoves = sources
                .Where(s => (s is EnvironmentVariablesConfigurationSource env && env.Prefix == null) 
                            || (s is CommandLineConfigurationSource)
                ).ToList();

            foreach(var toRemove in toRemoves)
            {
                sources.Remove(toRemove);
            }

            builder.AddEnvironmentVariables();
            builder.AddCommandLine(newArgs);
        })
        .Build();

    host.Run();
}

@metoule
Copy link
Author

metoule commented Jul 1, 2021

Interestingly, the -e PORT=80 option is not passed to docker run when appFramework = dotnet-isolated, cf the container logs:

Recycling container because of AppFrameworkChange and appFramework = dotnet-isolated
docker run -d -p 5348:80 --name redacted_11_6170ab1d -e WEBSITE_SITE_NAME=Redacted -e WEBSITE_AUTH_ENABLED=False -e WEBSITE_ROLE_INSTANCE_ID=0 -e WEBSITE_HOSTNAME=redacted.azurewebsites.net -e WEBSITE_INSTANCE_ID=bc66ade853a254eacbfacac63b6e3b49a221c65b1ac0a5bcaf857411df74dd87 mcr.microsoft.com/azure-functions/dotnet-isolated:3.0-dotnet-isolated5.0-appservice-stage4

When appFramework = DOCKER, then the option is set:

Recycling container because of AppFrameworkChange and appFramework = DOCKER
docker run -d -p 6391:80 --name redacted_12_48111735 -e WEBSITE_SITE_NAME=Redacted -e WEBSITE_AUTH_ENABLED=False -e PORT=80 -e WEBSITE_ROLE_INSTANCE_ID=0 -e WEBSITE_HOSTNAME=redacted.azurewebsites.net -e WEBSITE_INSTANCE_ID=bc66ade853a254eacbfacac63b6e3b49a221c65b1ac0a5bcaf857411df74dd87 mcr.microsoft.com/azure-functions/dotnet-isolated:3.0-dotnet-isolated5.0-appservice-stage4

@brettsam
Copy link
Member

brettsam commented Jul 6, 2021

Yeah, this is a bug. We meant for the command line arguments to be applied last, as you have done in your workaround.

Even though this is technically a breaking change, we agree that it will have minimal impact and it's worth it for us to swap this to make it correct.

@dfibuch
Copy link

dfibuch commented Aug 12, 2021

Interestingly, the -e PORT=80 option is not passed to docker run when appFramework = dotnet-isolated, cf the container logs:

Recycling container because of AppFrameworkChange and appFramework = dotnet-isolated
docker run -d -p 5348:80 --name redacted_11_6170ab1d -e WEBSITE_SITE_NAME=Redacted -e WEBSITE_AUTH_ENABLED=False -e WEBSITE_ROLE_INSTANCE_ID=0 -e WEBSITE_HOSTNAME=redacted.azurewebsites.net -e WEBSITE_INSTANCE_ID=bc66ade853a254eacbfacac63b6e3b49a221c65b1ac0a5bcaf857411df74dd87 mcr.microsoft.com/azure-functions/dotnet-isolated:3.0-dotnet-isolated5.0-appservice-stage4

When appFramework = DOCKER, then the option is set:

Recycling container because of AppFrameworkChange and appFramework = DOCKER
docker run -d -p 6391:80 --name redacted_12_48111735 -e WEBSITE_SITE_NAME=Redacted -e WEBSITE_AUTH_ENABLED=False -e PORT=80 -e WEBSITE_ROLE_INSTANCE_ID=0 -e WEBSITE_HOSTNAME=redacted.azurewebsites.net -e WEBSITE_INSTANCE_ID=bc66ade853a254eacbfacac63b6e3b49a221c65b1ac0a5bcaf857411df74dd87 mcr.microsoft.com/azure-functions/dotnet-isolated:3.0-dotnet-isolated5.0-appservice-stage4

Sorry for the stupid question but how do you set the appFramework on a Azure Function?

@metoule
Copy link
Author

metoule commented Aug 12, 2021

You can't directly: for my tests, I started with a brand new Azure function created via the Azure portal, and then I changed the docker image to a custom one.
The default Azure function used the dotnet-isolated appFramework, while my custom docker image made Azure to switch to the DOCKER appFramework, which I saw in the logs.

I don't know how to switch it back to the dotnet-isolated appFramework.

@dfibuch
Copy link

dfibuch commented Aug 12, 2021

I just applied your code to change the command line arguments and this has fixed my issue. Thank you! I am talking to Microsoft Technical support and linked them to this issue so hopefully someone will pick it up and get it fixed

Azure/azure-functions-docker#441

@dfibuch
Copy link

dfibuch commented Aug 20, 2021

@fabiocav Is there any change required on our end to get this update? Or is it a case of removing the workaround and see if it now works?

@pgombar
Copy link

pgombar commented Aug 21, 2021

Hi @dfibuch, you should be able to remove the workaround and update this reference in your .csproj to point to 1.5.1:
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.5.1" />

Redeploying after the update should do it!

@ghost ghost locked as resolved and limited conversation to collaborators Sep 20, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
6 participants