зеркало из https://github.com/dotnet/tye.git
Use same directory for Dockerfile and app
Fixes: #189 Fixes: #153 This change rejiggers the docker build infrastructure to publish the project and generate a Dockerfile in the same directory. This way they can't be on separate drives! Also added some focused tests for single-phase docker build.
This commit is contained in:
Родитель
944027b30c
Коммит
97e2c6c0ba
|
@ -34,55 +34,93 @@ namespace Microsoft.Tye
|
|||
throw new ArgumentNullException(nameof(container));
|
||||
}
|
||||
|
||||
using var tempFile = TempFile.Create();
|
||||
|
||||
var dockerFilePath = Path.Combine(project.ProjectFile.DirectoryName, "Dockerfile");
|
||||
if (File.Exists(dockerFilePath))
|
||||
{
|
||||
output.WriteDebugLine($"Using existing Dockerfile '{dockerFilePath}'.");
|
||||
}
|
||||
else
|
||||
{
|
||||
await DockerfileGenerator.WriteDockerfileAsync(output, application, project, container, tempFile.FilePath);
|
||||
dockerFilePath = tempFile.FilePath;
|
||||
}
|
||||
|
||||
// We need to know if this is a single-phase or multi-phase Dockerfile because the context directory will be
|
||||
// different depending on that choice.
|
||||
string contextDirectory;
|
||||
if (container.UseMultiphaseDockerfile ?? true)
|
||||
var dockerFilePath = Path.Combine(project.ProjectFile.DirectoryName, "Dockerfile");
|
||||
|
||||
TempFile? tempFile = null;
|
||||
TempDirectory? tempDirectory = null;
|
||||
|
||||
try
|
||||
{
|
||||
contextDirectory = ".";
|
||||
}
|
||||
else
|
||||
{
|
||||
var publishOutput = project.Outputs.OfType<ProjectPublishOutput>().FirstOrDefault();
|
||||
if (publishOutput is null)
|
||||
// We need to know if this is a single-phase or multi-phase Dockerfile because the context directory will be
|
||||
// different depending on that choice.
|
||||
//
|
||||
// For the cases where generate a Dockerfile, we have the constraint that we need
|
||||
// to place it on the same drive (Windows) as the docker context.
|
||||
if (container.UseMultiphaseDockerfile ?? true)
|
||||
{
|
||||
throw new InvalidOperationException("We should have published the project for a single-phase Dockerfile.");
|
||||
// For a multi-phase Docker build, the context is always the project directory.
|
||||
contextDirectory = ".";
|
||||
|
||||
if (File.Exists(dockerFilePath))
|
||||
{
|
||||
output.WriteDebugLine($"Using existing Dockerfile '{dockerFilePath}'.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// We need to write the file, let's stick it under obj.
|
||||
Directory.CreateDirectory(Path.Combine(project.ProjectFile.DirectoryName, "obj"));
|
||||
dockerFilePath = Path.Combine(project.ProjectFile.DirectoryName, "obj", "Dockerfile");
|
||||
|
||||
// Clean up file when done building image
|
||||
tempFile = new TempFile(dockerFilePath);
|
||||
|
||||
await DockerfileGenerator.WriteDockerfileAsync(output, application, project, container, tempFile.FilePath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// For a single-phase Docker build the context is always the directory containing the publish
|
||||
// output. We need to put the Dockerfile in the context directory so it's on the same drive (Windows).
|
||||
var publishOutput = project.Outputs.OfType<ProjectPublishOutput>().FirstOrDefault();
|
||||
if (publishOutput is null)
|
||||
{
|
||||
throw new InvalidOperationException("We should have published the project for a single-phase Dockerfile.");
|
||||
}
|
||||
|
||||
contextDirectory = publishOutput.Directory.FullName;
|
||||
|
||||
// Clean up directory when done building image
|
||||
tempDirectory = new TempDirectory(publishOutput.Directory);
|
||||
|
||||
if (File.Exists(dockerFilePath) & container.UseMultiphaseDockerfile == false)
|
||||
{
|
||||
output.WriteDebugLine($"Using existing Dockerfile '{dockerFilePath}'.");
|
||||
File.Copy(dockerFilePath, Path.Combine(contextDirectory, "Dockerfile"));
|
||||
dockerFilePath = Path.Combine(contextDirectory, "Dockerfile");
|
||||
}
|
||||
else
|
||||
{
|
||||
// No need to clean up, it's in a directory we're already cleaning up.
|
||||
dockerFilePath = Path.Combine(contextDirectory, "Dockerfile");
|
||||
await DockerfileGenerator.WriteDockerfileAsync(output, application, project, container, dockerFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
contextDirectory = publishOutput.Directory.FullName;
|
||||
output.WriteDebugLine("Running 'docker build'.");
|
||||
output.WriteCommandLine("docker", $"build \"{contextDirectory}\" -t {container.ImageName}:{container.ImageTag} -f \"{dockerFilePath}\"");
|
||||
var capture = output.Capture();
|
||||
var exitCode = await Process.ExecuteAsync(
|
||||
$"docker",
|
||||
$"build \"{contextDirectory}\" -t {container.ImageName}:{container.ImageTag} -f \"{dockerFilePath}\"",
|
||||
project.ProjectFile.DirectoryName,
|
||||
stdOut: capture.StdOut,
|
||||
stdErr: capture.StdErr);
|
||||
|
||||
output.WriteDebugLine($"Done running 'docker build' exit code: {exitCode}");
|
||||
if (exitCode != 0)
|
||||
{
|
||||
throw new CommandException("'docker build' failed.");
|
||||
}
|
||||
|
||||
output.WriteInfoLine($"Created Docker Image: '{container.ImageName}:{container.ImageTag}'");
|
||||
project.Outputs.Add(new DockerImageOutput(container.ImageName!, container.ImageTag!));
|
||||
}
|
||||
|
||||
output.WriteDebugLine("Running 'docker build'.");
|
||||
output.WriteCommandLine("docker", $"build \"{contextDirectory}\" -t {container.ImageName}:{container.ImageTag} -f \"{dockerFilePath}\"");
|
||||
var capture = output.Capture();
|
||||
var exitCode = await Process.ExecuteAsync(
|
||||
$"docker",
|
||||
$"build \"{contextDirectory}\" -t {container.ImageName}:{container.ImageTag} -f \"{dockerFilePath}\"",
|
||||
project.ProjectFile.DirectoryName,
|
||||
stdOut: capture.StdOut,
|
||||
stdErr: capture.StdErr);
|
||||
|
||||
output.WriteDebugLine($"Done running 'docker build' exit code: {exitCode}");
|
||||
if (exitCode != 0)
|
||||
finally
|
||||
{
|
||||
throw new CommandException("'docker build' failed.");
|
||||
tempDirectory?.Dispose();
|
||||
tempFile?.Dispose();
|
||||
}
|
||||
|
||||
output.WriteInfoLine($"Created Docker Image: '{container.ImageName}:{container.ImageTag}'");
|
||||
project.Outputs.Add(new DockerImageOutput(container.ImageName!, container.ImageTag!));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,14 +30,16 @@ namespace Microsoft.Tye
|
|||
return;
|
||||
}
|
||||
|
||||
var outputDirectory = Path.Combine(project.ProjectFile.DirectoryName, "bin", "Release", project.TargetFramework, "publish");
|
||||
// NOTE: we're intentionally not cleaning up here. It's the responsibility of whomever consumes
|
||||
// the publish output to do cleanup.
|
||||
var outputDirectory = TempDirectory.Create();
|
||||
|
||||
output.WriteDebugLine("Running 'dotnet publish'.");
|
||||
output.WriteCommandLine("dotnet", $"publish \"{project.ProjectFile.FullName}\" -c Release -o \"{outputDirectory}\"");
|
||||
output.WriteCommandLine("dotnet", $"publish \"{project.ProjectFile.FullName}\" -c Release -o \"{outputDirectory.DirectoryPath}\"");
|
||||
var capture = output.Capture();
|
||||
var exitCode = await Process.ExecuteAsync(
|
||||
$"dotnet",
|
||||
$"publish \"{project.ProjectFile.FullName}\" -c Release -o \"{outputDirectory}\"",
|
||||
$"publish \"{project.ProjectFile.FullName}\" -c Release -o \"{outputDirectory.DirectoryPath}\"",
|
||||
project.ProjectFile.DirectoryName,
|
||||
stdOut: capture.StdOut,
|
||||
stdErr: capture.StdErr);
|
||||
|
@ -45,11 +47,12 @@ namespace Microsoft.Tye
|
|||
output.WriteDebugLine($"Done running 'dotnet publish' exit code: {exitCode}");
|
||||
if (exitCode != 0)
|
||||
{
|
||||
outputDirectory.Dispose();
|
||||
throw new CommandException("'dotnet publish' failed.");
|
||||
}
|
||||
|
||||
output.WriteInfoLine($"Created Publish Output: '{outputDirectory}'");
|
||||
service.Outputs.Add(new ProjectPublishOutput(new DirectoryInfo(outputDirectory)));
|
||||
output.WriteDebugLine($"Created Publish Output: '{outputDirectory}'");
|
||||
service.Outputs.Add(new ProjectPublishOutput(outputDirectory.DirectoryInfo));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,20 +20,21 @@ namespace Microsoft.Tye
|
|||
|
||||
var directoryPath = Path.Combine(baseDirectory, Path.GetRandomFileName());
|
||||
var directoryInfo = Directory.CreateDirectory(directoryPath);
|
||||
return new TempDirectory(directoryPath, directoryInfo);
|
||||
return new TempDirectory(directoryInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
var directoryPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||
var directoryInfo = Directory.CreateDirectory(directoryPath);
|
||||
return new TempDirectory(directoryPath, directoryInfo);
|
||||
return new TempDirectory(directoryInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private TempDirectory(string directoryPath, DirectoryInfo directoryInfo)
|
||||
internal TempDirectory(DirectoryInfo directoryInfo)
|
||||
{
|
||||
DirectoryPath = directoryPath;
|
||||
DirectoryInfo = directoryInfo;
|
||||
|
||||
DirectoryPath = directoryInfo.FullName;
|
||||
}
|
||||
|
||||
public string DirectoryPath { get; }
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace Microsoft.Tye
|
|||
File.Delete(FilePath);
|
||||
}
|
||||
|
||||
private TempFile(string filePath)
|
||||
public TempFile(string filePath)
|
||||
{
|
||||
FilePath = filePath;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Content Include="testassets\**\*" CopyToOutputDirectory="PreserveNewest" />
|
||||
<Compile Remove="testassets\**\*" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -6,6 +6,8 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Microsoft.Tye;
|
||||
using Xunit;
|
||||
|
||||
namespace E2ETest
|
||||
{
|
||||
|
@ -33,5 +35,34 @@ namespace E2ETest
|
|||
|
||||
throw new Exception($"Solution file {solution}.sln could not be found in {applicationBasePath} or its parent directories.");
|
||||
}
|
||||
|
||||
public static DirectoryInfo GetTestAssetsDirectory()
|
||||
{
|
||||
return new DirectoryInfo(Path.Combine(
|
||||
TestHelpers.GetSolutionRootDirectory("tye"),
|
||||
"test",
|
||||
"E2ETest",
|
||||
"testassets"));
|
||||
}
|
||||
|
||||
public static DirectoryInfo GetTestProjectDirectory(string projectName)
|
||||
{
|
||||
var directory = new DirectoryInfo(Path.Combine(
|
||||
TestHelpers.GetSolutionRootDirectory("tye"),
|
||||
"test",
|
||||
"E2ETest",
|
||||
"testassets",
|
||||
"projects",
|
||||
projectName));
|
||||
Assert.True(directory.Exists, $"Project {projectName} not found.");
|
||||
return directory;
|
||||
}
|
||||
|
||||
internal static TempDirectory CopyTestProjectDirectory(string projectName)
|
||||
{
|
||||
var temp = TempDirectory.Create();
|
||||
DirectoryCopy.Copy(GetTestProjectDirectory(projectName).FullName, temp.DirectoryPath);
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Tye;
|
||||
using Xunit;
|
||||
using static E2ETest.TestHelpers;
|
||||
|
||||
namespace E2ETest
|
||||
{
|
||||
// Tests permutations of our Dockerfile-related behaviors.
|
||||
public partial class TyeBuildTests
|
||||
{
|
||||
[ConditionalFact]
|
||||
[SkipIfDockerNotRunning]
|
||||
public async Task TyeBuild_SinglePhase_GeneratedDockerfile()
|
||||
{
|
||||
var projectName = "single-phase-dockerfile";
|
||||
var environment = "production";
|
||||
var imageName = "test/single-phase-dockerfile";
|
||||
|
||||
await DockerAssert.DeleteDockerImagesAsync(output, imageName);
|
||||
|
||||
using var projectDirectory = CopyTestProjectDirectory(projectName);
|
||||
File.Delete(Path.Combine(projectDirectory.DirectoryPath, "Dockerfile"));
|
||||
Assert.False(File.Exists(Path.Combine(projectDirectory.DirectoryPath, "Dockerfile")), "Dockerfile should be gone.");
|
||||
|
||||
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
|
||||
|
||||
var outputContext = new OutputContext(sink, Verbosity.Debug);
|
||||
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
|
||||
|
||||
application.Registry = new ContainerRegistry("test");
|
||||
|
||||
try
|
||||
{
|
||||
await BuildHost.ExecuteBuildAsync(outputContext, application, environment, interactive: false);
|
||||
|
||||
var publishOutput = Assert.Single(application.Services.Single().Outputs.OfType<ProjectPublishOutput>());
|
||||
Assert.False(Directory.Exists(publishOutput.Directory.FullName), $"Directory {publishOutput.Directory.FullName} should be deleted.");
|
||||
|
||||
await DockerAssert.AssertImageExistsAsync(output, imageName);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await DockerAssert.DeleteDockerImagesAsync(output, imageName);
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[SkipIfDockerNotRunning]
|
||||
public async Task TyeBuild_SinglePhase_ExistingDockerfile()
|
||||
{
|
||||
var projectName = "single-phase-dockerfile";
|
||||
var environment = "production";
|
||||
var imageName = "test/single-phase-dockerfile";
|
||||
|
||||
await DockerAssert.DeleteDockerImagesAsync(output, imageName);
|
||||
|
||||
using var projectDirectory = CopyTestProjectDirectory(projectName);
|
||||
Assert.True(File.Exists(Path.Combine(projectDirectory.DirectoryPath, "Dockerfile")), "Dockerfile should exist.");
|
||||
|
||||
|
||||
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
|
||||
|
||||
var outputContext = new OutputContext(sink, Verbosity.Debug);
|
||||
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
|
||||
|
||||
application.Registry = new ContainerRegistry("test");
|
||||
|
||||
try
|
||||
{
|
||||
await BuildHost.ExecuteBuildAsync(outputContext, application, environment, interactive: false);
|
||||
|
||||
var publishOutput = Assert.Single(application.Services.Single().Outputs.OfType<ProjectPublishOutput>());
|
||||
Assert.False(Directory.Exists(publishOutput.Directory.FullName), $"Directory {publishOutput.Directory.FullName} should be deleted.");
|
||||
|
||||
await DockerAssert.AssertImageExistsAsync(output, imageName);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await DockerAssert.DeleteDockerImagesAsync(output, imageName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ using Xunit.Abstractions;
|
|||
|
||||
namespace E2ETest
|
||||
{
|
||||
public class TyeBuildTests
|
||||
public partial class TyeBuildTests
|
||||
{
|
||||
private readonly ITestOutputHelper output;
|
||||
private readonly TestOutputLogEventSink sink;
|
||||
|
|
|
@ -226,7 +226,7 @@ namespace E2ETest
|
|||
await host.StartAsync();
|
||||
try
|
||||
{
|
||||
// Make sure we're runningn containers
|
||||
// Make sure we're running containers
|
||||
Assert.True(host.Application.Services.All(s => s.Value.Description.RunInfo is DockerRunInfo));
|
||||
|
||||
var handler = new HttpClientHandler
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace multi_phase_dockerfile
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:39765",
|
||||
"sslPort": 44389
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"multi_phase_dockerfile": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:5001;http://localhost:5000",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace multi_phase_dockerfile
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapGet("/", async context =>
|
||||
{
|
||||
await context.Response.WriteAsync("Hello World!");
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<RootNamespace>multi_phase_dockerfile</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,10 @@
|
|||
# tye application configuration file
|
||||
# read all about it at https://github.com/dotnet/tye
|
||||
#
|
||||
# when you've given us a try, we'd love to know what you think:
|
||||
# https://aka.ms/AA7q20u
|
||||
#
|
||||
name: multi-phase-dockerfile
|
||||
services:
|
||||
- name: multi-phase-dockerfile
|
||||
project: multi-phase-dockerfile.csproj
|
|
@ -0,0 +1,4 @@
|
|||
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
|
||||
WORKDIR /app
|
||||
COPY . /app
|
||||
ENTRYPOINT ["dotnet", "single-phase-dockerfile.dll"]
|
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace single_phase_dockerfile
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:15313",
|
||||
"sslPort": 44306
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"single_phase_dockerfile": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:5001;http://localhost:5000",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace single_phase_dockerfile
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapGet("/", async context =>
|
||||
{
|
||||
await context.Response.WriteAsync("Hello World!");
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<RootNamespace>single_phase_dockerfile</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,10 @@
|
|||
# tye application configuration file
|
||||
# read all about it at https://github.com/dotnet/tye
|
||||
#
|
||||
# when you've given us a try, we'd love to know what you think:
|
||||
# https://aka.ms/AA7q20u
|
||||
#
|
||||
name: single-phase-dockerfile
|
||||
services:
|
||||
- name: single-phase-dockerfile
|
||||
project: single-phase-dockerfile.csproj
|
Загрузка…
Ссылка в новой задаче