private static async Task <int> RunDocker(IDockerClient client, RunDockerCommand command, string callingContainerId, IOutputObserver outputObserver, CancellationToken cancellationToken) { var allowedMounts = await GetMounts(client, callingContainerId, cancellationToken); if (!(ValidateDockerCommand(command) && ValidateMounts(command.BindMounts, allowedMounts) is {} mounts)) { await Console.Error.WriteLineAsync("Could not validate docker command."); return(1); } var response = await client.Containers.CreateContainerAsync( new Docker.DotNet.Models.CreateContainerParameters { Image = command.ImageName, Env = command.Environment.Select(env => $"{env.Key}={env.Value}").ToList(), AttachStderr = true, AttachStdout = true, ArgsEscaped = false, Cmd = command.Command.ToList(), WorkingDir = command.CurrentDirectory, HostConfig = new Docker.DotNet.Models.HostConfig { AutoRemove = true, NetworkMode = "none", Isolation = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "process" : null, Mounts = mounts, }, }, cancellationToken ); using var stream = await client.Containers.AttachContainerAsync( response.ID, tty : false, new Docker.DotNet.Models.ContainerAttachParameters { Stream = true, Stderr = true, Stdout = true, }, cancellationToken ); await client.Containers.StartContainerAsync( response.ID, new Docker.DotNet.Models.ContainerStartParameters { }, cancellationToken ); await DockerHelpers.PipeContainerOutput(outputObserver, stream, cancellationToken); var waitResponse = await client.Containers.WaitContainerAsync(response.ID, cancellationToken); return((int)waitResponse.StatusCode); }
private async Task <string> HandleRunCommandCommon(BuildState state, string proxyNetworkId, ReadOnlyDictionary <string, string> buildArgs, IReadOnlyList <string> command, IOutputObserver outputObserver, CancellationToken cancellationToken) { var nonEnvArgs = buildArgs.Where(arg => !state.Environment.ContainsKey(arg.Key)).ToList(); var response = await docker.Containers.CreateContainerAsync( new Docker.DotNet.Models.CreateContainerParameters { Image = state.Id, Env = nonEnvArgs.Select(env => $"{env.Key}={env.Value}").Concat(proxyEnv).ToList(), AttachStderr = true, AttachStdout = true, Cmd = command.ToList(), HostConfig = new Docker.DotNet.Models.HostConfig { NetworkMode = proxyNetworkId, Isolation = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "process" : null, }, }, cancellationToken ); try { using var stream = await docker.Containers.AttachContainerAsync( response.ID, tty : false, new Docker.DotNet.Models.ContainerAttachParameters { Stream = true, Stderr = true, Stdout = true, }, cancellationToken ); await docker.Containers.StartContainerAsync( response.ID, new Docker.DotNet.Models.ContainerStartParameters { }, cancellationToken ); await DockerHelpers.PipeContainerOutput(outputObserver, stream, cancellationToken); var waitResponse = await docker.Containers.WaitContainerAsync(response.ID, cancellationToken); int exitCode = (int)waitResponse.StatusCode; if (exitCode != 0) { throw new RunCommandFailedException($"Command failed with exit code {exitCode}.", exitCode); } var image = await docker.Images.CommitContainerChangesAsync(new CommitContainerChangesParameters { ContainerID = response.ID, Config = new Config { Env = nonEnvArgs.Select(env => env.Key).ToList(), }, }, cancellationToken); return(image.ID); } finally { await docker.Containers.RemoveContainerAsync(response.ID, new Docker.DotNet.Models.ContainerRemoveParameters(), cancellationToken); } }