Skip to content

Commit

Permalink
Added Dockerfile support, closes #57.
Browse files Browse the repository at this point in the history
  • Loading branch information
HofmeisterAn committed May 31, 2019
1 parent c44f6d4 commit 78a5428
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 20 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

.NET Testcontainers is a library to support tests with throwaway instances of Docker containers for all compatible .NET Standard versions. The library is built on top of the .NET Docker remote API and provides a lightweight implementation to support your test environment in all circumstances.

Choose from existing pre-configured configurations and start containers within a second, to support and run your tests.
Choose from existing pre-configured configurations and start containers within a second, to support and run your tests. Or create your own Testcontainers using Dockerfiles.

## Supported commands

Expand All @@ -20,8 +20,11 @@ Choose from existing pre-configured configurations and start containers within a
- `WithExposedPort` exposes a port inside the container e. g. `--expose=80`.
- `WithPortBinding` publishes a container port to the host e. g. `-p, --publish 80:80`.
- `WithMount` mounts a volume into the container e. g. `-v, --volume .:/tmp`.
- `WithCleanUp` removes the stopped container automatically.
- `WithOutputConsumer` redirects `stdout` and `stderr` to capture the Testcontainer output.
- `WithWaitStrategy` sets the wait strategy to complete the Testcontainer start and indicates when it is ready.
- `WithDockerfileDirectory` builds a Docker image based on a Dockerfile (`ImageFromDockerfileBuilder`).
- `WithDeleteIfExists` removes the Docker image before it is rebuilt (`ImageFromDockerfileBuilder`).

## Pre-configured containers

Expand Down
Binary file removed src/DotNet.Testcontainers.Tests/Assets/Dockerfile.tar
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp2.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
Expand All @@ -27,10 +28,5 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<None Include="Assets\Dockerfile.tar">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<Import Project="$(MSBuildThisFileDirectory)../Shared.msbuild" />
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public async Task SimpleDockerfile()
var imageFromDockerfile = await new ImageFromDockerfileBuilder()
.WithName("alpine:custom")
.WithDockerfileDirectory("Assets")
.WithDeleteIfExits(false)
.WithDeleteIfExists(false)
.Build();

Assert.NotEmpty(imageFromDockerfile);
Expand Down
56 changes: 48 additions & 8 deletions src/DotNet.Testcontainers/Clients/TestcontainersClient.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
namespace DotNet.Testcontainers.Clients
{
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
Expand All @@ -10,6 +11,8 @@ namespace DotNet.Testcontainers.Clients
using DotNet.Testcontainers.Core.Mapper;
using DotNet.Testcontainers.Core.Models;
using DotNet.Testcontainers.Diagnostics;
using ICSharpCode.SharpZipLib.Tar;
using ICSharpCode.SharpZipLib.Zip;

internal class TestcontainersClient : DockerApiClient, ITestcontainersClient
{
Expand Down Expand Up @@ -85,25 +88,26 @@ await WaitStrategy.WaitWhile(async () =>

public async Task<string> BuildAsync(ImageFromDockerfileConfiguration config)
{
var dockerfileDirectoryInfo = new DirectoryInfo(config.DockerfileDirectory);
var dockerfileDirectory = new DirectoryInfo(config.DockerfileDirectory);

if (!dockerfileDirectoryInfo.Exists)
if (!dockerfileDirectory.Exists)
{
throw new ArgumentException("Directory does not exist.");
throw new ArgumentException($"Directory '{dockerfileDirectory.FullName}' does not exist.");
}

if (!dockerfileDirectoryInfo.GetFiles().Any(file => "Dockerfile".Equals(file.Name)))
if (!dockerfileDirectory.GetFiles().Any(file => "Dockerfile".Equals(file.Name)))
{
throw new ArgumentException("Dockerfile does not exist.");
throw new ArgumentException($"Dockerfile does not exist in '{dockerfileDirectory.FullName}'.");
}

if (config.DeleteIfExits)
if (config.DeleteIfExists)
{
await Docker.Images.DeleteImageAsync(config.Image, new ImageDeleteParameters { Force = true });
}

// TODO: Create temp archive (tar) of Dockerfile base directory.
using (var stream = new FileStream($"{config.DockerfileDirectory}/Dockerfile.tar", FileMode.Open))
var dockerfileArchive = CreateDockerfileArchive(dockerfileDirectory.FullName);

using (var stream = new FileStream(dockerfileArchive, FileMode.Open))
{
await Docker.Images.BuildImageFromDockerfileAsync(stream, new ImageBuildParameters { Dockerfile = "Dockerfile", Tags = new[] { config.Image } });
}
Expand Down Expand Up @@ -167,5 +171,41 @@ public async Task<string> RunAsync(TestcontainersConfiguration config)

return (await Docker.Containers.CreateContainerAsync(createParameters)).ID;
}

private static string CreateDockerfileArchive(string dockerfileRootDirectory)
{
var dockerfileArchiveFile = $"{Path.GetTempPath()}/Dockerfile.tar";

using (var dockerfileArchiveStream = File.Create(dockerfileArchiveFile))
{
using (var dockerfileArchive = TarArchive.CreateOutputTarArchive(dockerfileArchiveStream))
{
dockerfileArchive.RootPath = dockerfileRootDirectory;

void Tar(string baseDirectory)
{
void WriteEntry(string entry)
{
var tarEntry = TarEntry.CreateEntryFromFile(entry);
tarEntry.Name = entry.Replace(dockerfileRootDirectory, string.Empty);
dockerfileArchive.WriteEntry(tarEntry, File.Exists(entry));
}

if (!dockerfileRootDirectory.Equals(baseDirectory))
{
WriteEntry(baseDirectory);
}

Directory.GetFiles(baseDirectory).ToList().ForEach(WriteEntry);

Directory.GetDirectories(baseDirectory).ToList().ForEach(Tar);
}

Tar(dockerfileRootDirectory);
}
}

return dockerfileArchiveFile;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public interface IImageFromDockerfileBuilder

IImageFromDockerfileBuilder WithDockerfileDirectory(string dockerfileDirectory);

IImageFromDockerfileBuilder WithDeleteIfExits(bool deleteIfExits);
IImageFromDockerfileBuilder WithDeleteIfExists(bool deleteIfExists);

Task<string> Build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ public IImageFromDockerfileBuilder WithDockerfileDirectory(string dockerfileDire
return this;
}

public IImageFromDockerfileBuilder WithDeleteIfExits(bool deleteIfExits)
public IImageFromDockerfileBuilder WithDeleteIfExists(bool deleteIfExists)
{
this.configuration.DeleteIfExits = deleteIfExits;
this.configuration.DeleteIfExists = deleteIfExists;
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ namespace DotNet.Testcontainers.Core.Models

internal class ImageFromDockerfileConfiguration
{
public string Image { get; set; } = Guid.NewGuid().ToString("n");
public string Image { get; set; } = Guid.NewGuid().ToString("n").Substring(0, 12);

public string DockerfileDirectory { get; set; } = ".";

public bool DeleteIfExits { get; set; } = true;
public bool DeleteIfExists { get; set; } = true;
}
}
2 changes: 2 additions & 0 deletions src/DotNet.Testcontainers/DotNet.Testcontainers.csproj
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Docker.DotNet" Version="3.125.2" />
<PackageReference Include="LanguageExt.Core" Version="3.1.24" />
<PackageReference Include="SharpZipLib" Version="1.1.0" />
</ItemGroup>
<Import Project="$(MSBuildThisFileDirectory)../Shared.msbuild" />
</Project>

0 comments on commit 78a5428

Please sign in to comment.