diff --git a/DockerfileTemplate.cs b/DockerfileTemplate.cs index 943c2af..219bde3 100644 --- a/DockerfileTemplate.cs +++ b/DockerfileTemplate.cs @@ -1,15 +1,22 @@ -namespace Brthor.Dockerize +using System.Linq; + +// ReSharper disable once CheckNamespace +namespace Brthor.Dockerize { public static class DockerfileTemplate { public static string Generate(DockerizeConfiguration config, string outputBinaryName) { - var addUser = config.Username == null + var addUser = string.IsNullOrWhiteSpace(config.Username) ? "" : $@"RUN groupadd -r {config.Username} && useradd --no-log-init -r -g {config.Username} {config.Username} RUN chown {config.Username}:{config.Username} /projectBinaries USER {config.Username}:{config.Username}"; + var ports = config.ExposedPorts == null + ? "" + : string.Join("\n", config.ExposedPorts.Select(port => $"EXPOSE {port}")); + var chownOnAdd = config.Username == null ? "" : $"--chown={config.Username}:{config.Username} "; @@ -22,6 +29,8 @@ RUN mkdir /projectBinaries ADD {chownOnAdd}./publish/ /projectBinaries/ WORKDIR /projectBinaries/ +{ports} + CMD /projectBinaries/{outputBinaryName} "; return dockerfileContent; diff --git a/DockerizeConfiguration.cs b/DockerizeConfiguration.cs index 4ad338f..b30180e 100644 --- a/DockerizeConfiguration.cs +++ b/DockerizeConfiguration.cs @@ -1,5 +1,7 @@ -using Microsoft.DotNet.Cli.Utils; +using System.Collections.Generic; +using Microsoft.DotNet.Cli.Utils; +// ReSharper disable once CheckNamespace namespace Brthor.Dockerize { public class DockerizeConfiguration @@ -22,22 +24,36 @@ public class DockerizeConfiguration public string BuildConfiguration { get; } public string Username { get; } + + public List ExposedPorts { get; } + + public bool DryRun { get; } - public DockerizeConfiguration(string projectName, string configuration, string tag, string baseRid, string baseImage, - string username=null) + public DockerizeConfiguration( + string projectName, + string configuration, + string tag, + string baseRid, + string baseImage, + bool dryRun, + string username, + List exposedPorts) { GeneratedImageTag = tag ?? projectName; BaseRid = baseRid ?? "linux-x64"; BaseImage = baseImage ?? "microsoft/dotnet:2.0-runtime"; BuildConfiguration = configuration ?? "Release"; + + DryRun = dryRun; Username = username; + ExposedPorts = exposedPorts; Reporter.Output.WriteLine($"Dockerize.NET".Blue()); Reporter.Output.WriteLine("Base Docker Image: ".White() + $"{BaseImage}".Green()); Reporter.Output.WriteLine("Base Rid of Docker Image: ".White() + $"{BaseRid}".Green()); Reporter.Output.WriteLine("Tag: ".White() + $"{GeneratedImageTag}".Green()); - if (Username != null) + if (!string.IsNullOrWhiteSpace(Username)) Reporter.Output.WriteLine("Username: ".White() + $"{Username}".Green()); } } diff --git a/Program.cs b/Program.cs index 9915f0d..efac5b0 100644 --- a/Program.cs +++ b/Program.cs @@ -5,11 +5,12 @@ using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.CommandLineUtils; +// ReSharper disable once CheckNamespace namespace Brthor.Dockerize { - class Program + public static class Program { - static int Main(string[] args) + public static int Main(string[] args) { var commandLineApplication = new CommandLineApplication(throwOnUnexpectedArg: false); @@ -49,11 +50,29 @@ static int Main(string[] args) "It is recommended to run production containers not as root for security.", CommandOptionType.SingleValue); + var exposedPorts = commandLineApplication.Option( + "-p |--port ", + "Expose one or more ports in your docker container. Expose multiple by passing `-p` multiple times.", + CommandOptionType.MultipleValue); + + var dryRun = commandLineApplication.Option( + "-n |--dry-run", + "Outputs the generated dockerfile to stdout. Does not call `docker build`. Still calls `dotnet publish`", + CommandOptionType.NoValue); + commandLineApplication.HelpOption("-? | -h | --help"); commandLineApplication.OnExecute(() => { var projectName = GetProjectName(Environment.CurrentDirectory, project); - var config = new DockerizeConfiguration(projectName, configuration.Value(), tag.Value(), baseRid.Value(), baseImage.Value(), username.Value()); + var config = new DockerizeConfiguration( + projectName, + configuration.HasValue() ? configuration.Value() : null, + tag.HasValue() ? tag.Value() : null, + baseRid.HasValue() ? baseRid.Value() : null, + baseImage.HasValue() ? baseImage.Value() : null, + dryRun.HasValue(), + username.HasValue() ? username.Value() : null, + exposedPorts.HasValue() ? exposedPorts.Values : null); return Run(config); }); @@ -83,8 +102,8 @@ private static string GetProjectName(string currentDirectory, CommandOption proj return Path.GetFileNameWithoutExtension(projectFilePath); } - static int Run(DockerizeConfiguration config){ - + private static int Run(DockerizeConfiguration config) + { var projectDirectory = Environment.CurrentDirectory; var dockerizeBaseDir = Path.Combine(projectDirectory, "bin", "dockerize"); var publishOutDirectory = Path.Combine(dockerizeBaseDir, "publish"); @@ -121,6 +140,12 @@ static int Run(DockerizeConfiguration config){ Path.GetFileNameWithoutExtension(publishOutputDepsJsons.Single()).Replace(".deps", ""); var dockerfile = DockerfileTemplate.Generate(config, outputBinaryName); + + if (config.DryRun) + { + Console.WriteLine(dockerfile); + return 0; + } File.WriteAllText(dockerfilePath, dockerfile);