diff --git a/.vscode/settings.json b/.vscode/settings.json
index 415e575..088f113 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -36,5 +36,34 @@
"sudoer",
"typeof",
"wdlp"
+ ],
+ "yaml.customTags": [
+ "!And",
+ "!And sequence",
+ "!If",
+ "!If sequence",
+ "!Not",
+ "!Not sequence",
+ "!Equals",
+ "!Equals sequence",
+ "!Or",
+ "!Or sequence",
+ "!FindInMap",
+ "!FindInMap sequence",
+ "!Base64",
+ "!Join",
+ "!Join sequence",
+ "!Cidr",
+ "!Ref",
+ "!Sub",
+ "!Sub sequence",
+ "!GetAtt",
+ "!GetAZs",
+ "!ImportValue",
+ "!ImportValue sequence",
+ "!Select",
+ "!Select sequence",
+ "!Split",
+ "!Split sequence"
]
}
\ No newline at end of file
diff --git a/Ductus.FluentDocker.MsTest/Ductus.FluentDocker.MsTest.csproj b/Ductus.FluentDocker.MsTest/Ductus.FluentDocker.MsTest.csproj
index cab05c3..8fc1816 100644
--- a/Ductus.FluentDocker.MsTest/Ductus.FluentDocker.MsTest.csproj
+++ b/Ductus.FluentDocker.MsTest/Ductus.FluentDocker.MsTest.csproj
@@ -33,7 +33,7 @@ Documentation: https://github.com/mariotoffia/FluentDocker
-
+
diff --git a/Ductus.FluentDocker.Tests/Ductus.FluentDocker.Tests.csproj b/Ductus.FluentDocker.Tests/Ductus.FluentDocker.Tests.csproj
index ec1dc0d..d53b7a9 100644
--- a/Ductus.FluentDocker.Tests/Ductus.FluentDocker.Tests.csproj
+++ b/Ductus.FluentDocker.Tests/Ductus.FluentDocker.Tests.csproj
@@ -41,7 +41,7 @@
-
+
PreserveNewest
@@ -60,6 +60,12 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
diff --git a/Ductus.FluentDocker.Tests/FluentApiTests/FluentContainerBasicTests.cs b/Ductus.FluentDocker.Tests/FluentApiTests/FluentContainerBasicTests.cs
index 12a8ae5..572e441 100644
--- a/Ductus.FluentDocker.Tests/FluentApiTests/FluentContainerBasicTests.cs
+++ b/Ductus.FluentDocker.Tests/FluentApiTests/FluentContainerBasicTests.cs
@@ -24,13 +24,6 @@ public static void Initialize(TestContext ctx)
Utilities.EnsureImage("postgres:9.6-alpine", TimeSpan.FromMinutes(1.0));
}
- [TestMethod]
- [TestCategory("CI")]
- public void VersionInfoShallBePossibleToRetrieve()
- {
- var v = Fd.Version();
- Assert.IsTrue(v != null && v.Length > 0);
- }
[TestMethod]
[TestCategory("CI")]
public void BuildContainerRenderServiceInStoppedMode()
@@ -500,6 +493,31 @@ public void ReuseOfExistingContainerShallWork()
}
}
+ [TestMethod]
+ [TestCategory("CI")]
+ public void DeleteIfExistsWithContainerShallWork()
+ {
+ var name = Guid.NewGuid().ToString();
+
+ var container = Fd.UseContainer()
+ .UseImage("postgres:9.6-alpine")
+ .WithName($"name-{name}")
+ .Build();
+
+ var id = container.Id;
+
+ using (var c = Fd
+ .UseContainer()
+ .DeleteIfExists()
+ .UseImage("postgres:9.6-alpine")
+ .WithName($"name-{name}")
+ .Build())
+ {
+ // Ids should not be equal - since deleted and then created.
+ AreNotEqual(id, c.Id);
+ }
+ }
+
[TestMethod]
[TestCategory("CI")]
public void PullContainerBeforeRunningShallWork()
diff --git a/Ductus.FluentDocker.Tests/FluentApiTests/FluentDockerComposeTests.cs b/Ductus.FluentDocker.Tests/FluentApiTests/FluentDockerComposeTests.cs
index 0be6b37..2f7fa45 100644
--- a/Ductus.FluentDocker.Tests/FluentApiTests/FluentDockerComposeTests.cs
+++ b/Ductus.FluentDocker.Tests/FluentApiTests/FluentDockerComposeTests.cs
@@ -335,5 +335,23 @@ public void Issue94()
Assert.AreEqual("1", zookeeper.InstanceId);
}
}
+
+ [TestMethod]
+ public void Issue190()
+ {
+ var file = Path.Combine(Directory.GetCurrentDirectory(),
+ (TemplateString)"Resources/hellotest/docker-compose.yml");
+
+ using (var svc = Fd.UseContainer()
+ .FromComposeFile(file)
+ .RemoveNonTaggedImages()
+ .ForceBuild()
+ .Build()
+ .Start())
+ {
+ }
+
+ // Now the custom build image should be removed!
+ }
}
}
diff --git a/Ductus.FluentDocker.Tests/Model/Containers/ContainerTests.cs b/Ductus.FluentDocker.Tests/Model/Containers/ContainerTests.cs
new file mode 100644
index 0000000..6f408cb
--- /dev/null
+++ b/Ductus.FluentDocker.Tests/Model/Containers/ContainerTests.cs
@@ -0,0 +1,22 @@
+using Ductus.FluentDocker.Model.Common;
+using Ductus.FluentDocker.Extensions;
+using Ductus.FluentDocker.Model.Containers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Newtonsoft.Json;
+
+namespace Ductus.FluentDocker.Tests.Model.Containers
+{
+ [TestClass]
+ public class ContainerTests
+ {
+ [TestMethod]
+ public void TestWithNoCreated()
+ {
+ var data = ((TemplateString)"Model/Containers/inspect_no_create.json").FromFile();
+ var obj = JsonConvert.DeserializeObject(data);
+
+ Assert.AreEqual(obj.Created, default(System.DateTime));
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Ductus.FluentDocker.Tests/Model/Containers/inspect.json b/Ductus.FluentDocker.Tests/Model/Containers/inspect.json
new file mode 100644
index 0000000..9af9287
--- /dev/null
+++ b/Ductus.FluentDocker.Tests/Model/Containers/inspect.json
@@ -0,0 +1,269 @@
+{
+ "Id": "490c464c0c10754e8cb898efa3021a637b7a5db720a178c96c4bbb5c0a3ade9e",
+ "Created": "2021-08-17T06:10:47.5281411Z",
+ "Path": "nginx",
+ "Args": [
+ "-g",
+ "daemon off;"
+ ],
+ "State": {
+ "Status": "running",
+ "Running": true,
+ "Paused": false,
+ "Restarting": false,
+ "OOMKilled": false,
+ "Dead": false,
+ "Pid": 1147,
+ "ExitCode": 0,
+ "Error": "",
+ "StartedAt": "2021-08-17T06:10:47.9763392Z",
+ "FinishedAt": "0001-01-01T00:00:00Z",
+ "Health": {
+ "Status": "healthy",
+ "FailingStreak": 0,
+ "Log": [
+ {
+ "Start": "2021-08-17T06:13:48.2680847Z",
+ "End": "2021-08-17T06:13:48.3372753Z",
+ "ExitCode": 0,
+ "Output": ""
+ },
+ {
+ "Start": "2021-08-17T06:14:18.3483842Z",
+ "End": "2021-08-17T06:14:18.3970737Z",
+ "ExitCode": 0,
+ "Output": ""
+ },
+ {
+ "Start": "2021-08-17T06:14:48.4063015Z",
+ "End": "2021-08-17T06:14:48.4489393Z",
+ "ExitCode": 0,
+ "Output": ""
+ },
+ {
+ "Start": "2021-08-17T06:15:18.4597211Z",
+ "End": "2021-08-17T06:15:18.5093092Z",
+ "ExitCode": 0,
+ "Output": ""
+ },
+ {
+ "Start": "2021-08-17T06:15:48.5184818Z",
+ "End": "2021-08-17T06:15:48.5734845Z",
+ "ExitCode": 0,
+ "Output": ""
+ }
+ ]
+ }
+ },
+ "Image": "sha256:5dd0c746427b76deb84066cb02175d3ba20d6ca45242abe7c130edf319f29bf9",
+ "ResolvConfPath": "/var/lib/docker/containers/490c464c0c10754e8cb898efa3021a637b7a5db720a178c96c4bbb5c0a3ade9e/resolv.conf",
+ "HostnamePath": "/var/lib/docker/containers/490c464c0c10754e8cb898efa3021a637b7a5db720a178c96c4bbb5c0a3ade9e/hostname",
+ "HostsPath": "/var/lib/docker/containers/490c464c0c10754e8cb898efa3021a637b7a5db720a178c96c4bbb5c0a3ade9e/hosts",
+ "LogPath": "/var/lib/docker/containers/490c464c0c10754e8cb898efa3021a637b7a5db720a178c96c4bbb5c0a3ade9e/490c464c0c10754e8cb898efa3021a637b7a5db720a178c96c4bbb5c0a3ade9e-json.log",
+ "Name": "/excalidraw",
+ "RestartCount": 0,
+ "Driver": "overlay2",
+ "Platform": "linux",
+ "MountLabel": "",
+ "ProcessLabel": "",
+ "AppArmorProfile": "",
+ "ExecIDs": null,
+ "HostConfig": {
+ "Binds": null,
+ "ContainerIDFile": "",
+ "LogConfig": {
+ "Type": "json-file",
+ "Config": {}
+ },
+ "NetworkMode": "default",
+ "PortBindings": {
+ "80/tcp": [
+ {
+ "HostIp": "",
+ "HostPort": "5000"
+ }
+ ]
+ },
+ "RestartPolicy": {
+ "Name": "no",
+ "MaximumRetryCount": 0
+ },
+ "AutoRemove": true,
+ "VolumeDriver": "",
+ "VolumesFrom": null,
+ "CapAdd": null,
+ "CapDrop": null,
+ "CgroupnsMode": "host",
+ "Dns": [],
+ "DnsOptions": [],
+ "DnsSearch": [],
+ "ExtraHosts": null,
+ "GroupAdd": null,
+ "IpcMode": "private",
+ "Cgroup": "",
+ "Links": null,
+ "OomScoreAdj": 0,
+ "PidMode": "",
+ "Privileged": false,
+ "PublishAllPorts": false,
+ "ReadonlyRootfs": false,
+ "SecurityOpt": null,
+ "UTSMode": "",
+ "UsernsMode": "",
+ "ShmSize": 67108864,
+ "Runtime": "runc",
+ "ConsoleSize": [
+ 0,
+ 0
+ ],
+ "Isolation": "",
+ "CpuShares": 0,
+ "Memory": 0,
+ "NanoCpus": 0,
+ "CgroupParent": "",
+ "BlkioWeight": 0,
+ "BlkioWeightDevice": [],
+ "BlkioDeviceReadBps": null,
+ "BlkioDeviceWriteBps": null,
+ "BlkioDeviceReadIOps": null,
+ "BlkioDeviceWriteIOps": null,
+ "CpuPeriod": 0,
+ "CpuQuota": 0,
+ "CpuRealtimePeriod": 0,
+ "CpuRealtimeRuntime": 0,
+ "CpusetCpus": "",
+ "CpusetMems": "",
+ "Devices": [],
+ "DeviceCgroupRules": null,
+ "DeviceRequests": null,
+ "KernelMemory": 0,
+ "KernelMemoryTCP": 0,
+ "MemoryReservation": 0,
+ "MemorySwap": 0,
+ "MemorySwappiness": null,
+ "OomKillDisable": false,
+ "PidsLimit": null,
+ "Ulimits": null,
+ "CpuCount": 0,
+ "CpuPercent": 0,
+ "IOMaximumIOps": 0,
+ "IOMaximumBandwidth": 0,
+ "MaskedPaths": [
+ "/proc/asound",
+ "/proc/acpi",
+ "/proc/kcore",
+ "/proc/keys",
+ "/proc/latency_stats",
+ "/proc/timer_list",
+ "/proc/timer_stats",
+ "/proc/sched_debug",
+ "/proc/scsi",
+ "/sys/firmware"
+ ],
+ "ReadonlyPaths": [
+ "/proc/bus",
+ "/proc/fs",
+ "/proc/irq",
+ "/proc/sys",
+ "/proc/sysrq-trigger"
+ ]
+ },
+ "GraphDriver": {
+ "Data": {
+ "LowerDir": "/var/lib/docker/overlay2/453b538e633cc877d18f019ad8b0ff1ca8507e9f918ef5ea62a245f5920d2053-init/diff:/var/lib/docker/overlay2/66233c22cdf3366954300515f99c179c4e23182ade1e7a46e6c130b62b84e64f/diff:/var/lib/docker/overlay2/f547213bae92bdfd0bd904d089f7be0b8a8aff9b0512ecab444a8f74b133b077/diff:/var/lib/docker/overlay2/6b9f5edd88d7953edb06358ff5c6808312cfbfda430287156befea9298a64491/diff",
+ "MergedDir": "/var/lib/docker/overlay2/453b538e633cc877d18f019ad8b0ff1ca8507e9f918ef5ea62a245f5920d2053/merged",
+ "UpperDir": "/var/lib/docker/overlay2/453b538e633cc877d18f019ad8b0ff1ca8507e9f918ef5ea62a245f5920d2053/diff",
+ "WorkDir": "/var/lib/docker/overlay2/453b538e633cc877d18f019ad8b0ff1ca8507e9f918ef5ea62a245f5920d2053/work"
+ },
+ "Name": "overlay2"
+ },
+ "Mounts": [],
+ "Config": {
+ "Hostname": "490c464c0c10",
+ "Domainname": "",
+ "User": "",
+ "AttachStdin": false,
+ "AttachStdout": false,
+ "AttachStderr": false,
+ "ExposedPorts": {
+ "80/tcp": {}
+ },
+ "Tty": true,
+ "OpenStdin": true,
+ "StdinOnce": false,
+ "Env": [
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "NGINX_VERSION=1.17.10",
+ "NJS_VERSION=0.3.9",
+ "PKG_RELEASE=1"
+ ],
+ "Cmd": [
+ "nginx",
+ "-g",
+ "daemon off;"
+ ],
+ "Healthcheck": {
+ "Test": [
+ "CMD-SHELL",
+ "wget -q -O /dev/null http://localhost || exit 1"
+ ]
+ },
+ "Image": "excalidraw/excalidraw:latest",
+ "Volumes": null,
+ "WorkingDir": "",
+ "Entrypoint": null,
+ "OnBuild": null,
+ "Labels": {
+ "desktop.docker.io/wsl-distro": "Ubuntu-18.04",
+ "maintainer": "NGINX Docker Maintainers \u003cdocker-maint@nginx.com\u003e"
+ },
+ "StopSignal": "SIGTERM"
+ },
+ "NetworkSettings": {
+ "Bridge": "",
+ "SandboxID": "a0dbb79456d465b67e98c224ad6ffb7c63e5916a5cc5659076cc97838e20a770",
+ "HairpinMode": false,
+ "LinkLocalIPv6Address": "",
+ "LinkLocalIPv6PrefixLen": 0,
+ "Ports": {
+ "80/tcp": [
+ {
+ "HostIp": "0.0.0.0",
+ "HostPort": "5000"
+ },
+ {
+ "HostIp": "::",
+ "HostPort": "5000"
+ }
+ ]
+ },
+ "SandboxKey": "/var/run/docker/netns/a0dbb79456d4",
+ "SecondaryIPAddresses": null,
+ "SecondaryIPv6Addresses": null,
+ "EndpointID": "2d89f7dce00590293a13ffc1017614c09c22916537bc21be358544dc67580e88",
+ "Gateway": "172.17.0.1",
+ "GlobalIPv6Address": "",
+ "GlobalIPv6PrefixLen": 0,
+ "IPAddress": "172.17.0.2",
+ "IPPrefixLen": 16,
+ "IPv6Gateway": "",
+ "MacAddress": "02:42:ac:11:00:02",
+ "Networks": {
+ "bridge": {
+ "IPAMConfig": null,
+ "Links": null,
+ "Aliases": null,
+ "NetworkID": "55f5721b918cd170cf4b610bc562ff97a29666529f59099c202de64921e13d21",
+ "EndpointID": "2d89f7dce00590293a13ffc1017614c09c22916537bc21be358544dc67580e88",
+ "Gateway": "172.17.0.1",
+ "IPAddress": "172.17.0.2",
+ "IPPrefixLen": 16,
+ "IPv6Gateway": "",
+ "GlobalIPv6Address": "",
+ "GlobalIPv6PrefixLen": 0,
+ "MacAddress": "02:42:ac:11:00:02",
+ "DriverOpts": null
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ductus.FluentDocker.Tests/Model/Containers/inspect_no_create.json b/Ductus.FluentDocker.Tests/Model/Containers/inspect_no_create.json
new file mode 100644
index 0000000..d5f2cd3
--- /dev/null
+++ b/Ductus.FluentDocker.Tests/Model/Containers/inspect_no_create.json
@@ -0,0 +1,268 @@
+{
+ "Id": "490c464c0c10754e8cb898efa3021a637b7a5db720a178c96c4bbb5c0a3ade9e",
+ "Path": "nginx",
+ "Args": [
+ "-g",
+ "daemon off;"
+ ],
+ "State": {
+ "Status": "running",
+ "Running": true,
+ "Paused": false,
+ "Restarting": false,
+ "OOMKilled": false,
+ "Dead": false,
+ "Pid": 1147,
+ "ExitCode": 0,
+ "Error": "",
+ "StartedAt": "2021-08-17T06:10:47.9763392Z",
+ "FinishedAt": "0001-01-01T00:00:00Z",
+ "Health": {
+ "Status": "healthy",
+ "FailingStreak": 0,
+ "Log": [
+ {
+ "Start": "2021-08-17T06:13:48.2680847Z",
+ "End": "2021-08-17T06:13:48.3372753Z",
+ "ExitCode": 0,
+ "Output": ""
+ },
+ {
+ "Start": "2021-08-17T06:14:18.3483842Z",
+ "End": "2021-08-17T06:14:18.3970737Z",
+ "ExitCode": 0,
+ "Output": ""
+ },
+ {
+ "Start": "2021-08-17T06:14:48.4063015Z",
+ "End": "2021-08-17T06:14:48.4489393Z",
+ "ExitCode": 0,
+ "Output": ""
+ },
+ {
+ "Start": "2021-08-17T06:15:18.4597211Z",
+ "End": "2021-08-17T06:15:18.5093092Z",
+ "ExitCode": 0,
+ "Output": ""
+ },
+ {
+ "Start": "2021-08-17T06:15:48.5184818Z",
+ "End": "2021-08-17T06:15:48.5734845Z",
+ "ExitCode": 0,
+ "Output": ""
+ }
+ ]
+ }
+ },
+ "Image": "sha256:5dd0c746427b76deb84066cb02175d3ba20d6ca45242abe7c130edf319f29bf9",
+ "ResolvConfPath": "/var/lib/docker/containers/490c464c0c10754e8cb898efa3021a637b7a5db720a178c96c4bbb5c0a3ade9e/resolv.conf",
+ "HostnamePath": "/var/lib/docker/containers/490c464c0c10754e8cb898efa3021a637b7a5db720a178c96c4bbb5c0a3ade9e/hostname",
+ "HostsPath": "/var/lib/docker/containers/490c464c0c10754e8cb898efa3021a637b7a5db720a178c96c4bbb5c0a3ade9e/hosts",
+ "LogPath": "/var/lib/docker/containers/490c464c0c10754e8cb898efa3021a637b7a5db720a178c96c4bbb5c0a3ade9e/490c464c0c10754e8cb898efa3021a637b7a5db720a178c96c4bbb5c0a3ade9e-json.log",
+ "Name": "/excalidraw",
+ "RestartCount": 0,
+ "Driver": "overlay2",
+ "Platform": "linux",
+ "MountLabel": "",
+ "ProcessLabel": "",
+ "AppArmorProfile": "",
+ "ExecIDs": null,
+ "HostConfig": {
+ "Binds": null,
+ "ContainerIDFile": "",
+ "LogConfig": {
+ "Type": "json-file",
+ "Config": {}
+ },
+ "NetworkMode": "default",
+ "PortBindings": {
+ "80/tcp": [
+ {
+ "HostIp": "",
+ "HostPort": "5000"
+ }
+ ]
+ },
+ "RestartPolicy": {
+ "Name": "no",
+ "MaximumRetryCount": 0
+ },
+ "AutoRemove": true,
+ "VolumeDriver": "",
+ "VolumesFrom": null,
+ "CapAdd": null,
+ "CapDrop": null,
+ "CgroupnsMode": "host",
+ "Dns": [],
+ "DnsOptions": [],
+ "DnsSearch": [],
+ "ExtraHosts": null,
+ "GroupAdd": null,
+ "IpcMode": "private",
+ "Cgroup": "",
+ "Links": null,
+ "OomScoreAdj": 0,
+ "PidMode": "",
+ "Privileged": false,
+ "PublishAllPorts": false,
+ "ReadonlyRootfs": false,
+ "SecurityOpt": null,
+ "UTSMode": "",
+ "UsernsMode": "",
+ "ShmSize": 67108864,
+ "Runtime": "runc",
+ "ConsoleSize": [
+ 0,
+ 0
+ ],
+ "Isolation": "",
+ "CpuShares": 0,
+ "Memory": 0,
+ "NanoCpus": 0,
+ "CgroupParent": "",
+ "BlkioWeight": 0,
+ "BlkioWeightDevice": [],
+ "BlkioDeviceReadBps": null,
+ "BlkioDeviceWriteBps": null,
+ "BlkioDeviceReadIOps": null,
+ "BlkioDeviceWriteIOps": null,
+ "CpuPeriod": 0,
+ "CpuQuota": 0,
+ "CpuRealtimePeriod": 0,
+ "CpuRealtimeRuntime": 0,
+ "CpusetCpus": "",
+ "CpusetMems": "",
+ "Devices": [],
+ "DeviceCgroupRules": null,
+ "DeviceRequests": null,
+ "KernelMemory": 0,
+ "KernelMemoryTCP": 0,
+ "MemoryReservation": 0,
+ "MemorySwap": 0,
+ "MemorySwappiness": null,
+ "OomKillDisable": false,
+ "PidsLimit": null,
+ "Ulimits": null,
+ "CpuCount": 0,
+ "CpuPercent": 0,
+ "IOMaximumIOps": 0,
+ "IOMaximumBandwidth": 0,
+ "MaskedPaths": [
+ "/proc/asound",
+ "/proc/acpi",
+ "/proc/kcore",
+ "/proc/keys",
+ "/proc/latency_stats",
+ "/proc/timer_list",
+ "/proc/timer_stats",
+ "/proc/sched_debug",
+ "/proc/scsi",
+ "/sys/firmware"
+ ],
+ "ReadonlyPaths": [
+ "/proc/bus",
+ "/proc/fs",
+ "/proc/irq",
+ "/proc/sys",
+ "/proc/sysrq-trigger"
+ ]
+ },
+ "GraphDriver": {
+ "Data": {
+ "LowerDir": "/var/lib/docker/overlay2/453b538e633cc877d18f019ad8b0ff1ca8507e9f918ef5ea62a245f5920d2053-init/diff:/var/lib/docker/overlay2/66233c22cdf3366954300515f99c179c4e23182ade1e7a46e6c130b62b84e64f/diff:/var/lib/docker/overlay2/f547213bae92bdfd0bd904d089f7be0b8a8aff9b0512ecab444a8f74b133b077/diff:/var/lib/docker/overlay2/6b9f5edd88d7953edb06358ff5c6808312cfbfda430287156befea9298a64491/diff",
+ "MergedDir": "/var/lib/docker/overlay2/453b538e633cc877d18f019ad8b0ff1ca8507e9f918ef5ea62a245f5920d2053/merged",
+ "UpperDir": "/var/lib/docker/overlay2/453b538e633cc877d18f019ad8b0ff1ca8507e9f918ef5ea62a245f5920d2053/diff",
+ "WorkDir": "/var/lib/docker/overlay2/453b538e633cc877d18f019ad8b0ff1ca8507e9f918ef5ea62a245f5920d2053/work"
+ },
+ "Name": "overlay2"
+ },
+ "Mounts": [],
+ "Config": {
+ "Hostname": "490c464c0c10",
+ "Domainname": "",
+ "User": "",
+ "AttachStdin": false,
+ "AttachStdout": false,
+ "AttachStderr": false,
+ "ExposedPorts": {
+ "80/tcp": {}
+ },
+ "Tty": true,
+ "OpenStdin": true,
+ "StdinOnce": false,
+ "Env": [
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "NGINX_VERSION=1.17.10",
+ "NJS_VERSION=0.3.9",
+ "PKG_RELEASE=1"
+ ],
+ "Cmd": [
+ "nginx",
+ "-g",
+ "daemon off;"
+ ],
+ "Healthcheck": {
+ "Test": [
+ "CMD-SHELL",
+ "wget -q -O /dev/null http://localhost || exit 1"
+ ]
+ },
+ "Image": "excalidraw/excalidraw:latest",
+ "Volumes": null,
+ "WorkingDir": "",
+ "Entrypoint": null,
+ "OnBuild": null,
+ "Labels": {
+ "desktop.docker.io/wsl-distro": "Ubuntu-18.04",
+ "maintainer": "NGINX Docker Maintainers \u003cdocker-maint@nginx.com\u003e"
+ },
+ "StopSignal": "SIGTERM"
+ },
+ "NetworkSettings": {
+ "Bridge": "",
+ "SandboxID": "a0dbb79456d465b67e98c224ad6ffb7c63e5916a5cc5659076cc97838e20a770",
+ "HairpinMode": false,
+ "LinkLocalIPv6Address": "",
+ "LinkLocalIPv6PrefixLen": 0,
+ "Ports": {
+ "80/tcp": [
+ {
+ "HostIp": "0.0.0.0",
+ "HostPort": "5000"
+ },
+ {
+ "HostIp": "::",
+ "HostPort": "5000"
+ }
+ ]
+ },
+ "SandboxKey": "/var/run/docker/netns/a0dbb79456d4",
+ "SecondaryIPAddresses": null,
+ "SecondaryIPv6Addresses": null,
+ "EndpointID": "2d89f7dce00590293a13ffc1017614c09c22916537bc21be358544dc67580e88",
+ "Gateway": "172.17.0.1",
+ "GlobalIPv6Address": "",
+ "GlobalIPv6PrefixLen": 0,
+ "IPAddress": "172.17.0.2",
+ "IPPrefixLen": 16,
+ "IPv6Gateway": "",
+ "MacAddress": "02:42:ac:11:00:02",
+ "Networks": {
+ "bridge": {
+ "IPAMConfig": null,
+ "Links": null,
+ "Aliases": null,
+ "NetworkID": "55f5721b918cd170cf4b610bc562ff97a29666529f59099c202de64921e13d21",
+ "EndpointID": "2d89f7dce00590293a13ffc1017614c09c22916537bc21be358544dc67580e88",
+ "Gateway": "172.17.0.1",
+ "IPAddress": "172.17.0.2",
+ "IPPrefixLen": 16,
+ "IPv6Gateway": "",
+ "GlobalIPv6Address": "",
+ "GlobalIPv6PrefixLen": 0,
+ "MacAddress": "02:42:ac:11:00:02",
+ "DriverOpts": null
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ductus.FluentDocker.Tests/Resources/hellotest/docker-compose.yml b/Ductus.FluentDocker.Tests/Resources/hellotest/docker-compose.yml
new file mode 100644
index 0000000..9c6439e
--- /dev/null
+++ b/Ductus.FluentDocker.Tests/Resources/hellotest/docker-compose.yml
@@ -0,0 +1,8 @@
+version: "3.4"
+
+services:
+ hellotest:
+ image: hellotest:v2
+ build:
+ context: hellotest
+ dockerfile: Dockerfile
\ No newline at end of file
diff --git a/Ductus.FluentDocker.Tests/Resources/hellotest/hellotest/Dockerfile b/Ductus.FluentDocker.Tests/Resources/hellotest/hellotest/Dockerfile
new file mode 100644
index 0000000..a49c427
--- /dev/null
+++ b/Ductus.FluentDocker.Tests/Resources/hellotest/hellotest/Dockerfile
@@ -0,0 +1,3 @@
+FROM scratch
+COPY hello /
+CMD ["/hello"]
\ No newline at end of file
diff --git a/Ductus.FluentDocker.Tests/Resources/hellotest/hellotest/hello b/Ductus.FluentDocker.Tests/Resources/hellotest/hellotest/hello
new file mode 100755
index 0000000..5052f25
Binary files /dev/null and b/Ductus.FluentDocker.Tests/Resources/hellotest/hellotest/hello differ
diff --git a/Ductus.FluentDocker/Builders/ContainerBuilder.cs b/Ductus.FluentDocker/Builders/ContainerBuilder.cs
index b246860..4874dce 100644
--- a/Ductus.FluentDocker/Builders/ContainerBuilder.cs
+++ b/Ductus.FluentDocker/Builders/ContainerBuilder.cs
@@ -35,6 +35,19 @@ public override IContainerService Build()
// Login on private repo if needed.
_repositoryBuilder?.Build(host.Value);
+ // Destroy the container if it already exists (if enabled).
+ if (_config.DestroyIfExists != null &&
+ !string.IsNullOrEmpty(_config.CreateParams.Name))
+ {
+ host.Value.Host.RemoveContainer(
+ _config.CreateParams.Name,
+ _config.DestroyIfExists.Force,
+ _config.DestroyIfExists.RemoveVolumes,
+ _config.DestroyIfExists.LinkToRemove,
+ host.Value.Certificates);
+
+ }
+
if (_config.VerifyExistence && !string.IsNullOrEmpty(_config.CreateParams.Name))
{
// Since filter on docker is only prefix filter
@@ -484,6 +497,27 @@ public ContainerBuilder ReuseIfExists()
return this;
}
+
+ ///
+ /// This will ensure that the *named* container is deleted before the container is created.
+ ///
+ /// Optional. If set to true it will remove all volumes. True by default.
+ /// Optional. Fore will try to force delete the container. False by default.
+ /// Optional. When set to a value other than null it will remove any linkage. Null by default.
+ ///
+ public ContainerBuilder DeleteIfExists(bool removeVolumes = true, bool force = false, string removeLink = null)
+ {
+ _config.DestroyIfExists = new DestroyIfExistParams
+ {
+ Force = force,
+ RemoveVolumes = removeVolumes,
+ LinkToRemove = removeLink
+ };
+
+
+ return this;
+ }
+
///
/// Uses a already pre-existing network service. It will automatically
/// detach this container from the network when the network is disposed.
diff --git a/Ductus.FluentDocker/Ductus.FluentDocker.csproj b/Ductus.FluentDocker/Ductus.FluentDocker.csproj
index 8e6222e..12850f2 100644
--- a/Ductus.FluentDocker/Ductus.FluentDocker.csproj
+++ b/Ductus.FluentDocker/Ductus.FluentDocker.csproj
@@ -34,7 +34,7 @@
latest
-
+
diff --git a/Ductus.FluentDocker/Extensions/FileExtensions.cs b/Ductus.FluentDocker/Extensions/FileExtensions.cs
index ca46ec0..83955f0 100644
--- a/Ductus.FluentDocker/Extensions/FileExtensions.cs
+++ b/Ductus.FluentDocker/Extensions/FileExtensions.cs
@@ -1,5 +1,4 @@
-using System.Collections.Generic;
-using System.IO;
+using System.IO;
using System.Text;
using Ductus.FluentDocker.Model.Common;
diff --git a/Ductus.FluentDocker/Model/Builders/ContainerBuilderConfig.cs b/Ductus.FluentDocker/Model/Builders/ContainerBuilderConfig.cs
index 8386a39..9b188e7 100644
--- a/Ductus.FluentDocker/Model/Builders/ContainerBuilderConfig.cs
+++ b/Ductus.FluentDocker/Model/Builders/ContainerBuilderConfig.cs
@@ -8,10 +8,24 @@
namespace Ductus.FluentDocker.Model.Builders
{
+ public sealed class DestroyIfExistParams {
+ public bool Force { get; set; }
+ public bool RemoveVolumes { get; set; }
+ public string LinkToRemove { get; set; }
+ }
+
public sealed class ContainerBuilderConfig
{
public ContainerBuilderConfig() => CreateParams = new ContainerCreateParams();
+ ///
+ /// When set to true, the container will be removed if it exists before creating it.
+ ///
+ /// true if it shall be destroyed if exists, false if skip checking and destroy.
+ ///
+ /// Default is false.
+ ///
+ public DestroyIfExistParams DestroyIfExists { get; set; }
public bool VerifyExistence { get; set; }
public ContainerCreateParams CreateParams { get; }
public string Image { get; set; }
diff --git a/Ductus.FluentDocker/Model/Containers/Container.cs b/Ductus.FluentDocker/Model/Containers/Container.cs
index c9af716..95dce0a 100644
--- a/Ductus.FluentDocker/Model/Containers/Container.cs
+++ b/Ductus.FluentDocker/Model/Containers/Container.cs
@@ -4,6 +4,7 @@ public sealed class Container
{
public string Id { get; set; }
public string Image { get; set; }
+ public System.DateTime Created { get; set; }
public string ResolvConfPath { get; set; }
public string HostnamePath { get; set; }
public string HostsPath { get; set; }
diff --git a/Examples/.vscode/settings.json b/Examples/.vscode/settings.json
new file mode 100644
index 0000000..73581e1
--- /dev/null
+++ b/Examples/.vscode/settings.json
@@ -0,0 +1,5 @@
+{
+ "cSpell.words": [
+ "Ductus"
+ ]
+}
\ No newline at end of file
diff --git a/Examples/.vscode/tasks.json b/Examples/.vscode/tasks.json
new file mode 100644
index 0000000..31c32bd
--- /dev/null
+++ b/Examples/.vscode/tasks.json
@@ -0,0 +1,24 @@
+{
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
+ // for the documentation about the tasks.json format
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "build",
+ "command": "dotnet",
+ "type": "shell",
+ "args": [
+ "build",
+ // Ask dotnet build to generate full paths for file names.
+ "/property:GenerateFullPaths=true",
+ // Do not generate summary otherwise it leads to duplicate errors in Problems panel
+ "/consoleloggerparameters:NoSummary"
+ ],
+ "group": "build",
+ "presentation": {
+ "reveal": "silent"
+ },
+ "problemMatcher": "$msCompile"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Examples/DockerInDockerLinux/DockerInDockerLinux.csproj b/Examples/DockerInDockerLinux/DockerInDockerLinux.csproj
new file mode 100644
index 0000000..8683037
--- /dev/null
+++ b/Examples/DockerInDockerLinux/DockerInDockerLinux.csproj
@@ -0,0 +1,9 @@
+
+
+ Exe
+ netcoreapp3.1
+
+
+
+
+
\ No newline at end of file
diff --git a/Examples/DockerInDockerLinux/Dockerfile b/Examples/DockerInDockerLinux/Dockerfile
new file mode 100644
index 0000000..9a3c47f
--- /dev/null
+++ b/Examples/DockerInDockerLinux/Dockerfile
@@ -0,0 +1,12 @@
+FROM mcr.microsoft.com/dotnet/sdk:3.1
+
+WORKDIR /App
+COPY bin/Debug/netcoreapp3.1 .
+
+RUN apt-get -qq update && apt-get -qq install wget
+RUN wget --quiet https://download.docker.com/linux/static/stable/x86_64/docker-20.10.8.tgz && \
+ tar -xzf docker-20.10.8.tgz
+
+RUN cp docker/* /usr/bin/ && rm -rf docker
+
+ENTRYPOINT ["dotnet", "DockerInDockerLinux.dll"]
\ No newline at end of file
diff --git a/Examples/DockerInDockerLinux/Program.cs b/Examples/DockerInDockerLinux/Program.cs
new file mode 100644
index 0000000..61e3034
--- /dev/null
+++ b/Examples/DockerInDockerLinux/Program.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Linq;
+using Ductus.FluentDocker.Commands;
+using Ductus.FluentDocker.Services;
+namespace DockerInDockerLinux
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ var hosts = new Hosts().Discover();
+
+ var docker = hosts.FirstOrDefault(x => x.IsNative) ?? hosts.FirstOrDefault(x => x.Name == "default");
+ Console.WriteLine($"Docker host: {docker?.Host.Host}, {docker?.Host.AbsolutePath}, {docker?.Host.AbsoluteUri}");
+
+ var containers = docker?.GetContainers();
+ Console.WriteLine(docker?.Host.Host);
+ Console.WriteLine($"Number of containers: {containers?.Count}");
+ }
+ }
+}
diff --git a/Examples/DockerInDockerLinux/build.sh b/Examples/DockerInDockerLinux/build.sh
new file mode 100755
index 0000000..a070ce7
--- /dev/null
+++ b/Examples/DockerInDockerLinux/build.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+## Builds the docker image
+docker build -t docker-in-docker -f Dockerfile .
diff --git a/Examples/DockerInDockerLinux/run.sh b/Examples/DockerInDockerLinux/run.sh
new file mode 100755
index 0000000..b47fb4a
--- /dev/null
+++ b/Examples/DockerInDockerLinux/run.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+## Will execute the built docker container
+docker run --rm -v /var/run/docker.sock:/var/run/docker.sock docker-in-docker
\ No newline at end of file
diff --git a/Examples/Examples.sln b/Examples/Examples.sln
new file mode 100644
index 0000000..eb3a7ef
--- /dev/null
+++ b/Examples/Examples.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DockerInDockerLinux", "DockerInDockerLinux\DockerInDockerLinux.csproj", "{956E68C4-C0DA-4EEB-BD4F-B19F56A1AC24}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {956E68C4-C0DA-4EEB-BD4F-B19F56A1AC24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {956E68C4-C0DA-4EEB-BD4F-B19F56A1AC24}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {956E68C4-C0DA-4EEB-BD4F-B19F56A1AC24}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {956E68C4-C0DA-4EEB-BD4F-B19F56A1AC24}.Debug|x64.Build.0 = Debug|Any CPU
+ {956E68C4-C0DA-4EEB-BD4F-B19F56A1AC24}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {956E68C4-C0DA-4EEB-BD4F-B19F56A1AC24}.Debug|x86.Build.0 = Debug|Any CPU
+ {956E68C4-C0DA-4EEB-BD4F-B19F56A1AC24}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {956E68C4-C0DA-4EEB-BD4F-B19F56A1AC24}.Release|Any CPU.Build.0 = Release|Any CPU
+ {956E68C4-C0DA-4EEB-BD4F-B19F56A1AC24}.Release|x64.ActiveCfg = Release|Any CPU
+ {956E68C4-C0DA-4EEB-BD4F-B19F56A1AC24}.Release|x64.Build.0 = Release|Any CPU
+ {956E68C4-C0DA-4EEB-BD4F-B19F56A1AC24}.Release|x86.ActiveCfg = Release|Any CPU
+ {956E68C4-C0DA-4EEB-BD4F-B19F56A1AC24}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/Examples/global.json b/Examples/global.json
new file mode 100644
index 0000000..70db897
--- /dev/null
+++ b/Examples/global.json
@@ -0,0 +1,5 @@
+{
+ "sdk": {
+ "version": "3.1.402"
+ }
+}
\ No newline at end of file
diff --git a/appveyor.yml b/appveyor.yml
index cf101a9..fc5dbb6 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -34,6 +34,7 @@ before_build:
- echo good_to_deploy=%good_to_deploy%
build:
+ project: FluentDocker.sln
publish_nuget: true
verbosity: minimal