Created
August 24, 2023 14:19
-
-
Save ptupitsyn/84f2fdc989b2391ca501eaeaaf8de85c to your computer and use it in GitHub Desktop.
.NET attach to Docker container and execute commands
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Docker.DotNet; | |
using Docker.DotNet.Models; | |
var client = new DockerClientConfiguration(new Uri("unix:///var/run/docker.sock")).CreateClient(); | |
await client.System.PingAsync(); | |
var imagesCreateParameters = new ImagesCreateParameters | |
{ | |
FromImage = "alpine/git", | |
Tag = "v2.36.3" | |
}; | |
Console.WriteLine("Creating image..."); | |
await client.Images.CreateImageAsync(imagesCreateParameters, null, new DockerProgress()); | |
Console.WriteLine("Finding image..."); | |
var imageId = await FindImageWithRetryAsync(imagesCreateParameters.FromImage, imagesCreateParameters.Tag, client); | |
Console.WriteLine("Image created: " + imageId); | |
var container = await client.Containers.CreateContainerAsync(new CreateContainerParameters | |
{ | |
Image = imageId, | |
Name = "DELME_" + DateTime.Now.Ticks, | |
Tty = false, | |
Entrypoint = new[] { "tail", "-f" } // Make it wait forever. | |
}); | |
Console.WriteLine("Container created: " + container.ID); | |
var startRes = await client.Containers.StartContainerAsync(container.ID, new ContainerStartParameters()); | |
Console.WriteLine("Container started: " + startRes); | |
while (true) | |
{ | |
Console.WriteLine("Input command to run in container: "); | |
var cmd = Console.ReadLine()!.Split(' '); | |
await ExecuteCommandInRunningContainer(client, container, cmd); | |
} | |
static async Task<string?> FindImageWithRetryAsync( | |
string image, | |
string tag, | |
DockerClient client) | |
{ | |
var timeout = DateTime.Now.AddSeconds(2); | |
while (true) | |
{ | |
var res = await FindImageAsync(image, tag, client); | |
if (res != null || DateTime.Now > timeout) | |
{ | |
return res; | |
} | |
await Task.Delay(TimeSpan.FromMilliseconds(300)); | |
} | |
} | |
static async Task<string?> FindImageAsync(string image, string tag, DockerClient client) | |
{ | |
var key = $"{image}:{tag}"; | |
var images = await client.Images.ListImagesAsync(new ImagesListParameters | |
{ | |
Filters = new Dictionary<string, IDictionary<string, bool>> | |
{ | |
{ | |
"reference", | |
new Dictionary<string, bool> | |
{ | |
{key, true} | |
} | |
} | |
} | |
}); | |
if (images.Count == 0) | |
{ | |
throw new Exception($"Failed to find image '{image}:{tag}'"); | |
} | |
var imageId = images.FirstOrDefault(x => x.RepoTags.Contains(key, StringComparer.Ordinal))?.ID; | |
if (imageId == null) | |
{ | |
var imageStr = images.Select(x => $"{x.ID} ({string.Join(", ", x.RepoTags)})"); | |
throw new Exception($"Failed to find image '{image}:{tag}'. None of the returned images match: {imageStr}."); | |
} | |
return imageId; | |
} | |
async Task ExecuteCommandInRunningContainer( | |
DockerClient dockerClient, | |
CreateContainerResponse createContainerResponse, | |
string[] cmd) | |
{ | |
var exec = await dockerClient.Exec.ExecCreateContainerAsync(createContainerResponse.ID, | |
new ContainerExecCreateParameters | |
{ | |
AttachStderr = true, | |
AttachStdout = true, | |
AttachStdin = false, | |
Cmd = cmd | |
}); | |
Console.WriteLine("Exec created: " + exec.ID); | |
using var stream = await dockerClient.Exec.StartAndAttachContainerExecAsync(exec.ID, tty: false); | |
var output = await stream.ReadOutputToEndAsync(CancellationToken.None); | |
Console.WriteLine("STDOUT: " + output.stdout); | |
Console.WriteLine("STDERR: " + output.stderr); | |
// await stream.CopyOutputToAsync( | |
// stdin: null, | |
// stdout: Console.OpenStandardOutput(), | |
// stderr: Console.OpenStandardError(), | |
// cancellationToken: CancellationToken.None); | |
} | |
class DockerProgress : IProgress<JSONMessage> | |
{ | |
public void Report(JSONMessage value) | |
{ | |
// Console.WriteLine(value); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment