Browse Source

Improve container base image detection (#234)

* Improve container base image detection
- Improve ASP.NET project detection to work with netcoreapp2.1 applications
- Grab the target framework name and version from the project separately so we can use the vesion to determine the base image
- Updated Dockerfile generation and tye run --docker to work with different container versions based on the TFM version.
pull/242/head
David Fowler 6 years ago
committed by GitHub
parent
commit
2a0ffaf88c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      src/Microsoft.Tye.Core/ApplicationFactory.cs
  2. 13
      src/Microsoft.Tye.Core/DockerfileGenerator.cs
  3. 8
      src/Microsoft.Tye.Core/ProjectReader.cs
  4. 22
      src/Microsoft.Tye.Core/ProjectServiceBuilder.cs
  5. 16
      src/Microsoft.Tye.Hosting/DockerRunner.cs
  6. 5
      src/Microsoft.Tye.Hosting/Model/ProjectRunInfo.cs
  7. 7
      src/Microsoft.Tye.Hosting/TransformProjectsIntoContainers.cs

2
src/Microsoft.Tye.Core/ApplicationFactory.cs

@ -99,7 +99,7 @@ namespace Microsoft.Tye
// If there are no bindings and we're in ASP.NET Core project then add an HTTP and HTTPS binding
if (configService.Bindings.Count == 0 &&
service is ProjectServiceBuilder project2 &&
project2.Frameworks.Any(f => f.Name == "Microsoft.AspNetCore.App"))
project2.IsAspNet)
{
// HTTP is the default binding
service.Bindings.Add(new BindingBuilder()

13
src/Microsoft.Tye.Core/DockerfileGenerator.cs

@ -92,8 +92,7 @@ namespace Microsoft.Tye
throw new ArgumentNullException(nameof(container));
}
if (container.BaseImageName == null &&
project.Frameworks.Any(f => f.Name == "Microsoft.AspNetCore.App"))
if (container.BaseImageName == null && project.IsAspNet)
{
container.BaseImageName = "mcr.microsoft.com/dotnet/core/aspnet";
}
@ -102,15 +101,9 @@ namespace Microsoft.Tye
container.BaseImageName = "mcr.microsoft.com/dotnet/core/runtime";
}
if (container.BaseImageTag == null &&
project.TargetFramework == "netcoreapp3.1")
if (container.BaseImageTag == null && project.TargetFrameworkName == "netcoreapp")
{
container.BaseImageTag = "3.1";
}
else if (container.BaseImageTag == null &&
project.TargetFramework == "netcoreapp3.0")
{
container.BaseImageTag = "3.0";
container.BaseImageTag = project.TargetFrameworkVersion;
}
if (container.BaseImageTag == null)

8
src/Microsoft.Tye.Core/ProjectReader.cs

@ -219,10 +219,18 @@ namespace Microsoft.Tye
project.TargetFramework = targetFramework;
output.WriteDebugLine($"Found target framework: {targetFramework}");
// TODO: Parse the name and version manually out of the TargetFramework field if it's non-null
project.TargetFrameworkName = projectInstance.GetPropertyValue("_ShortFrameworkIdentifier");
project.TargetFrameworkVersion = projectInstance.GetPropertyValue("_ShortFrameworkVersion") ?? projectInstance.GetPropertyValue("_TargetFrameworkVersionWithoutV");
var sharedFrameworks = projectInstance.GetItems("FrameworkReference").Select(i => i.EvaluatedInclude).ToList();
project.Frameworks.AddRange(sharedFrameworks.Select(s => new Framework(s)));
output.WriteDebugLine($"Found shared frameworks: {string.Join(", ", sharedFrameworks)}");
project.IsAspNet = project.Frameworks.Any(f => f.Name == "Microsoft.AspNetCore.App") ||
projectInstance.GetPropertyValue("MicrosoftNETPlatformLibrary") == "Microsoft.AspNetCore.App" ||
projectInstance.GetPropertyValue("_AspNetCoreAppSharedFxIsEnabled") is string s && !string.IsNullOrEmpty(s) && bool.Parse(s);
output.WriteDebugLine($"Evaluation Took: {sw.Elapsed.TotalMilliseconds}ms");
// The Microsoft.Build.Locator doesn't handle the loading of other assemblies

22
src/Microsoft.Tye.Core/ProjectServiceBuilder.cs

@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
namespace Microsoft.Tye
@ -26,32 +25,19 @@ namespace Microsoft.Tye
public FrameworkCollection Frameworks { get; } = new FrameworkCollection();
// This is always set on the ApplicationFactory codepath.
// These is always set on the ApplicationFactory codepath.
public string TargetFrameworkName { get; set; } = default!;
public string TargetFrameworkVersion { get; set; } = default!;
public string TargetFramework { get; set; } = default!;
// This is always set on the ApplicationFactory codepath.
public string[] TargetFrameworks { get; set; } = default!;
// This is always set on the ApplicationFactory codepath.
public string Version { get; set; } = default!;
// This is always set on the ApplicationFactory codepath.
public string TargetPath { get; set; } = default!;
// This is always set on the ApplicationFactory codepath.
public string RunCommand { get; set; } = default!;
// This is always set on the ApplicationFactory codepath.
public string RunArguments { get; set; } = default!;
// This is always set on the ApplicationFactory codepath.
public string AssemblyName { get; set; } = default!;
// This is always set on the ApplicationFactory codepath.
public string PublishDir { get; set; } = default!;
// This is always set on the ApplicationFactory codepath.
public string IntermediateOutputPath { get; set; } = default!;
public bool IsAspNet { get; set; }
// Data used for building containers
public ContainerInfo? ContainerInfo { get; set; }

16
src/Microsoft.Tye.Hosting/DockerRunner.cs

@ -99,7 +99,8 @@ namespace Microsoft.Tye.Hosting
// Default to development environment
["DOTNET_ENVIRONMENT"] = "Development",
// Remove the color codes from the console output
["DOTNET_LOGGING__CONSOLE__DISABLECOLORS"] = "true"
["DOTNET_LOGGING__CONSOLE__DISABLECOLORS"] = "true",
["ASPNETCORE_LOGGING__CONSOLE__DISABLECOLORS"] = "true"
};
var portString = "";
@ -203,6 +204,19 @@ namespace Microsoft.Tye.Hosting
errorDataReceived: data => service.Logs.OnNext($"[{replica}]: {data}"),
throwOnError: false,
cancellationToken: dockerInfo.StoppingTokenSource.Token);
if (!dockerInfo.StoppingTokenSource.IsCancellationRequested)
{
try
{
// Avoid spamming logs if restarts are happening
await Task.Delay(5000, dockerInfo.StoppingTokenSource.Token);
}
catch (OperationCanceledException)
{
break;
}
}
}
_logger.LogInformation("docker logs collection for {ContainerName} complete with exit code {ExitCode}", replica, result.ExitCode);

5
src/Microsoft.Tye.Hosting/Model/ProjectRunInfo.cs

@ -15,6 +15,8 @@ namespace Microsoft.Tye.Hosting.Model
Args = project.Args;
Build = project.Build;
TargetFramework = project.TargetFramework;
TargetFrameworkName = project.TargetFrameworkName;
TargetFrameworkVersion = project.TargetFrameworkVersion;
Version = project.Version;
AssemblyName = project.AssemblyName;
TargetAssemblyPath = project.TargetPath;
@ -26,7 +28,8 @@ namespace Microsoft.Tye.Hosting.Model
public string? Args { get; }
public bool Build { get; }
public FileInfo ProjectFile { get; }
public string TargetFrameworkName { get; set; } = default!;
public string TargetFrameworkVersion { get; set; } = default!;
public string TargetFramework { get; }
public string Version { get; }

7
src/Microsoft.Tye.Hosting/TransformProjectsIntoContainers.cs

@ -64,7 +64,7 @@ namespace Microsoft.Tye.Hosting
// We transform the project information into the following docker command:
// docker run -w /app -v {publishDir}:/app -it {image} dotnet {outputfile}.dll
var containerImage = DetermineContainerImage(targetFramework);
var containerImage = DetermineContainerImage(project);
var outputFileName = project.AssemblyName + ".dll";
var dockerRunInfo = new DockerRunInfo(containerImage, $"dotnet {outputFileName} {project.Args}")
{
@ -83,10 +83,9 @@ namespace Microsoft.Tye.Hosting
serviceDescription.RunInfo = dockerRunInfo;
}
private static string DetermineContainerImage(string targetFramework)
private static string DetermineContainerImage(ProjectRunInfo project)
{
// TODO: Determine the base image from the tfm
return "mcr.microsoft.com/dotnet/core/sdk:3.1-buster";
return $"mcr.microsoft.com/dotnet/core/sdk:{project.TargetFrameworkVersion}";
}
public Task StopAsync(Application application)

Loading…
Cancel
Save