Skip to content

Commit

Permalink
Support generating portable Containerfiles. (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
tmds authored Oct 27, 2022
1 parent 0d89f8c commit 11eb369
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 18 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,13 @@ Arguments:
Options:
-b, --base <base> Flavor of the base image
-t, --tag <tag> Name for the built image [default: dotnet-app]
-a, --arch <arch> Target architecture ('x64'/'arm64'/'s390x')
The base image needs to support the selected architecture
--push After the build, push the image to the repository
--portable Avoid using features that make the Containerfile not portable
--context <context> Context directory for the build [default: .]
--as-file <as-file> Generates a Containerfile with the specified name
--print Print the Containerfile
--arch <arch> Target architecture ('x64'/'arm64'/'s390x')
The base image needs to support the selected architecture
--context <context> Context directory for the build [default: .]
--version Show version information
-?, -h, --help Show help and usage information
```
Expand Down
32 changes: 22 additions & 10 deletions src/build-image/BuildCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,40 @@ public BuildCommand() :
var asfileOption = new Option<string>( "--as-file", "Generates a Containerfile with the specified name");
var printOption = new Option<bool>("--print", "Print the Containerfile") { Arity = ArgumentArity.Zero };
var pushOption = new Option<bool>("--push", "After the build, push the image to the repository") { Arity = ArgumentArity.Zero };
var archOption = new Option<string>(new[] { "--arch" }, $"Target architecture ('x64'/'arm64'/'s390x')\nThe base image needs to support the selected architecture");
var archOption = new Option<string>(new[] { "--arch", "-a" }, $"Target architecture ('x64'/'arm64'/'s390x')\nThe base image needs to support the selected architecture");
var contextOption = new Option<string>(new[] { "--context" }, getDefaultValue: () => ".", "Context directory for the build");
var portableOption = new Option<bool>("--portable", "Avoid using features that make the Containerfile not portable") { Arity = ArgumentArity.Zero };

var projectArg = new Argument<string>("PROJECT", getDefaultValue: () => ".", ".NET project to build");
Add(projectArg);

// note: order determines the help order
Add(baseOption);
Add(tagOption);
Add(pushOption);
Add(asfileOption);
Add(printOption);
Add(archOption);

Add(pushOption);

Add(portableOption);
Add(contextOption);

var projectArg = new Argument<string>("PROJECT", getDefaultValue: () => ".", ".NET project to build");
Add(projectArg);
Add(asfileOption);
Add(printOption);

this.SetHandler((IConsole console,
string? os, string tag, string? asfile, string project, bool push, bool print, string? arch, string? context) => Handle(console, os, tag, asfile, project, push, print, arch, context),
baseOption, tagOption, asfileOption, projectArg, pushOption, printOption, archOption, contextOption);
string? os, string tag, string? asfile, string project, bool push, bool print, string? arch, string? context, bool portable) => Handle(console, os, tag, asfile, project, push, print, arch, context, portable),
baseOption, tagOption, asfileOption, projectArg, pushOption, printOption, archOption, contextOption, portableOption);
}

public static int Handle(IConsole console, string? baseFlavor, string? tag, string? asfile, string project, bool push, bool print, string? arch, string? contextDir)
public static int Handle(IConsole console, string? baseFlavor, string? tag, string? asfile, string project, bool push, bool print, string? arch, string? contextDir, bool portable)
{
ContainerEngine? containerEngine = ContainerEngine.TryCreate();
ContainerEngineFeature disabledFeatures = ContainerEngineFeature.None;
if (portable)
{
disabledFeatures = ContainerEngineFeature.All;
}

ContainerEngine? containerEngine = ContainerEngine.TryCreate(disabledFeatures);
if (containerEngine is null && asfile is null)
{
console.Error.WriteLine("Install podman or docker to build images.");
Expand Down
26 changes: 21 additions & 5 deletions src/build-image/ContainerEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,33 @@
using System.Diagnostics;
using System.Text;

[Flags]
enum ContainerEngineFeature
{
None = 0,
CacheMounts,
All = CacheMounts
}

class ContainerEngine
{
public const string Docker = "docker";
public const string Podman = "podman";

public string Command { get; }
public Version Version { get; }
private ContainerEngineFeature _disabledFeatures;

private bool IsDisabled(ContainerEngineFeature feature) => (_disabledFeatures & ContainerEngineFeature.CacheMounts) != 0;

public bool SupportsCacheMount
{
get
{
if (IsDisabled(ContainerEngineFeature.CacheMounts))
{
return false;
}
if (Command == Podman)
{
return Version.Major >= 4;
Expand All @@ -31,13 +46,14 @@ public bool SupportsCacheMountSELinuxRelabling
}
}

private ContainerEngine(string command, Version version)
private ContainerEngine(string command, Version version, ContainerEngineFeature disabledFeatures)
{
Command = command;
Version = version;
_disabledFeatures = disabledFeatures;
}

public static ContainerEngine? TryCreate()
public static ContainerEngine? TryCreate(ContainerEngineFeature disableFeatures = ContainerEngineFeature.None)
{
string? command = null;
Version? version = null;
Expand Down Expand Up @@ -67,7 +83,7 @@ private ContainerEngine(string command, Version version)
return null;
}

return new ContainerEngine(command, version ?? new Version());
return new ContainerEngine(command, version ?? new Version(), disableFeatures);
}

public bool TryBuild(IConsole console, string dockerFileName, string tag, string contextDir)
Expand All @@ -90,9 +106,9 @@ private ProcessCommand GetBuildCommand(string dockerFileName, string tag, string
Arguments = { "build", "-f", dockerFileName, "-t", tag, contextDir }
};

if (Command == Docker)
if (Command == Docker && !IsDisabled(ContainerEngineFeature.CacheMounts))
{
// Support cache mounts.
// Enable cache mount support.
command.EnvironmentVariables.Add(("DOCKER_BUILDKIT", "1"));
}

Expand Down

0 comments on commit 11eb369

Please sign in to comment.