Skip to content

Instantly share code, notes, and snippets.

@ptupitsyn
Created August 24, 2023 14:19
Show Gist options
  • Save ptupitsyn/84f2fdc989b2391ca501eaeaaf8de85c to your computer and use it in GitHub Desktop.
Save ptupitsyn/84f2fdc989b2391ca501eaeaaf8de85c to your computer and use it in GitHub Desktop.
.NET attach to Docker container and execute commands
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