public static async Task <string> RunContainer(this DockerClient client, string image, string containerName, string exposedPort, string hostPort) { CreateContainerResponse container = await CreateContainer(client, image, containerName, exposedPort, hostPort); await client.Containers.StartContainerAsync(containerName, new ContainerStartParameters()); return(container.ID); }
private async Task CreateContainerAsync() { var hostConfig = new HostConfig { PublishAllPorts = true }; if (_settings.ExternalPort > 0) { hostConfig.PublishAllPorts = false; hostConfig.PortBindings = new Dictionary <string, IList <PortBinding> > { { _settings.InternalPort + "/tcp", new List <PortBinding> { new PortBinding { HostPort = _settings.ExternalPort.ToString() } } } }; } var startParams = new CreateContainerParameters { Name = _settings.UniqueContainerName, Image = _settings.ImageFullname, AttachStdout = true, AttachStderr = true, AttachStdin = false, Tty = false, HostConfig = hostConfig, Env = _settings.EnvironmentVariables, Cmd = _settings.Cmd }; try { await retryPolicy .ExecuteAsync(async() => { CreateContainerResponse response = await _client .Containers .CreateContainerAsync(startParams); if (string.IsNullOrEmpty(response.ID)) { throw new ContainerException( "Could not create the container"); } Instance.Id = response.ID; }); } catch (Exception ex) { throw new ContainerException( $"Error in CreateContainer: {_settings.UniqueContainerName}", ex); } }
private async Task <string> CriarContainer() { CreateContainerParameters parametros = CriarParametros(); CreateContainerResponse container = await _dockerClient .Containers .CreateContainerAsync(parametros); return(container.ID); }
/// <summary> /// Create a new <see cref="ContainerCreated"/>. /// </summary> /// <param name="correlationId"> /// The message correlation Id that was assigned to the original <see cref="CreateContainer"/> request. /// </param> /// <param name="apiResponse"> /// The response from the Docker API. /// </param> public ContainerCreated(string correlationId, CreateContainerResponse apiResponse) : base(correlationId) { if (apiResponse == null) { throw new ArgumentNullException(nameof(apiResponse)); } ApiResponse = apiResponse; }
private async Task <string> CreateContainer( string imageName, IList <string> environmentVariables, IList <string> volumeBindings, IList <PortMapping> portMappings, IList <string> startCmd, HostConfig hostConfigOverrides, string workingDirectory) { HostConfig hostConfig = hostConfigOverrides ?? new HostConfig(); hostConfig.NetworkMode = SessionHostContainerConfiguration.DockerNetworkName; hostConfig.Binds = volumeBindings; hostConfig.PortBindings = portMappings?.ToDictionary(p => $"{p.GamePort.Number}/{p.GamePort.Protocol}", p => (IList <PortBinding>)(new List <PortBinding>() { new PortBinding() { HostPort = $"{p.NodePort}/{p.GamePort.Protocol}" } })); if (hostConfig.LogConfig == null) { hostConfig.LogConfig = new LogConfig(); hostConfig.LogConfig.Type = "json-file"; hostConfig.LogConfig.Config = new Dictionary <string, string>() { { "max-size", "200m" } }; } CreateContainerParameters containerParams = new CreateContainerParameters { Image = imageName, Env = environmentVariables, ExposedPorts = portMappings?.ToDictionary(p => $"{p.GamePort.Number}/{p.GamePort.Protocol}", p => new EmptyStruct()), HostConfig = hostConfig, WorkingDir = workingDirectory, Cmd = startCmd }; _logger.LogInformation($"Creating container. Image='{imageName}'"); CreateContainerResponse response = await TaskUtil.TimedExecute( async() => await _dockerClient.Containers.CreateContainerAsync(containerParams).ConfigureAwait(false), _logger, MetricConstants.ContainerStats, MetricConstants.ContainerCreationTime); _logger.LogInformation($"Created a container with session host id: {response.ID}"); return(response.ID); }
public async Task <string> StartContainerNode(string ImageName, string NodeName, string DriverPort, string VNCPort) { var CreateParameters = new CreateContainerParameters { Image = ImageName, Name = NodeName, ExposedPorts = new Dictionary <string, EmptyStruct> { { "4444", default(EmptyStruct) }, { "5900", default(EmptyStruct) } }, HostConfig = new HostConfig { ShmSize = 134217728, PortBindings = new Dictionary <string, IList <PortBinding> > { { "4444", new List <PortBinding> { new PortBinding { HostPort = DriverPort } } }, { "5900", new List <PortBinding> { new PortBinding { HostPort = VNCPort } } }, }, }, ArgsEscaped = true, AttachStderr = true, AttachStdin = true, AttachStdout = true, }; CreateContainerResponse response = await client.Containers.CreateContainerAsync(CreateParameters); try { Task t = client.Containers.StartContainerAsync(response.ID, null); t.Wait(); Console.WriteLine($"{NodeName} container created: {DateTime.Now}"); } catch (Exception ex) { Console.WriteLine($"{NodeName} {ex.Message}"); } return(response.ID); }
/// <summary> /// TODO /// </summary> /// <param name="instance"></param> /// <param name="port"></param> /// <param name="sourcePath"></param> /// <returns></returns> private async Task <string> StartImageAsync(string key, int port, string sourcePath, string version) { this._logger.LogInformation("Trying to start image {imageKey} {version} on {port} with {URL}", key, version, port, sourcePath); CreateContainerResponse newContainer = null; try { newContainer = await this._dockerClient.Containers.CreateContainerAsync(new CreateContainerParameters { Labels = new Dictionary <string, string> { { DOCKER_LABEL_KEY, key } }, Volumes = new Dictionary <string, EmptyStruct> { { "/factorio", new EmptyStruct() } }, Image = "factoriotools/factorio:" + version, ExposedPorts = new Dictionary <string, EmptyStruct> { { "34197/udp", new EmptyStruct() } }, Name = "factorio-server-" + key, HostConfig = new HostConfig { PortBindings = new Dictionary <string, IList <PortBinding> > { { "34197/udp", new[] { new PortBinding { HostPort = string.Format("{0}", port) } } } }, Mounts = new List <Mount> { new Mount { Target = "/factorio", Type = "bind", Source = sourcePath } } } }); } catch (DockerApiException e) { throw new Exception("Failed to start instance", e); } await this._dockerClient.Containers.StartContainerAsync(newContainer.ID, new ContainerStartParameters()); return(newContainer.ID); }
public async Task CanAttachContainer() { var sut = new ContainerHelper(); CreateContainerResponse createContainerResponse = await sut.CreateContainer(@"shawnseabrook/build:50", "canattach", new List <string> { "ListTests" }); await sut.StartContainer(createContainerResponse.ID); string res = await sut.AttachContainer(createContainerResponse.ID); Console.WriteLine(res); }
public async Task CreateContainer() { if (await DoesContainerExist(_containerName)) { return; } await _client.Images.CreateImageAsync(new ImagesCreateParameters() { FromImage = _imageName, Tag = _imageTag }, new AuthConfig(), new Progress <JSONMessage>()); var config = new Config() { Hostname = "localhost" }; var hostConfig = new HostConfig() { PortBindings = new Dictionary <string, IList <PortBinding> > { { "1113/tcp", new List <PortBinding> { new PortBinding { HostIP = "127.0.0.1", HostPort = "1113" } } }, { "2113/tcp", new List <PortBinding> { new PortBinding { HostIP = "127.0.0.1", HostPort = "2113" } } } } }; // Create the container try { CreateContainerResponse response = await _client.Containers.CreateContainerAsync( new CreateContainerParameters(config) { Image = _imageName + ":" + _imageTag, Name = _containerName, Tty = false, HostConfig = hostConfig, }); } catch (Exception e) { Console.WriteLine($"Summat went wrong {e.Message}"); } }
public void Create(CreateContainerParameters createParameters) { this.Docker.Images.CreateImageAsync(new ImagesCreateParameters() { FromImage = createParameters.Image }, null, this).GetAwaiter().GetResult(); this.CreateResponse = this.Docker.Containers.CreateContainerAsync(createParameters).GetAwaiter().GetResult(); if (this.CreateResponse.Warnings != null && this.CreateResponse.Warnings.Any()) { throw new InvalidOperationException(string.Join(" | ", this.CreateResponse.Warnings)); } Console.WriteLine($"Container Created {this.CreateResponse.ID}"); }
private static async Task CreateContainer( IImageSettings settings) { CreateContainerResponse response = await _client .Containers .CreateContainerAsync(settings.ToCreateContainerParameters()); if (string.IsNullOrEmpty(response.ID)) { throw new ContainerException( "Could not create the container"); } settings.ContainerId = response.ID; }
public async System.Threading.Tasks.Task InitAsync(string parent, string tag, string containerId) { Console.WriteLine("Pulling image " + parent + ":" + tag); await client.Images.CreateImageAsync(new ImagesCreateParameters() { FromImage = parent, Tag = tag }, null, new Progress()); CreateContainerResponse response = await CreateContainer(parent, containerId, null); await StartContainer(containerId); var buffer = new byte[1024]; using (var stream1 = await client.Containers.AttachContainerAsync(response.ID, false, new ContainerAttachParameters() { Stream = true, Stderr = true, Stdin = false, Stdout = true, Logs = "1" })) { (string output, string stderr) = await stream1.ReadOutputToEndAsync(default(CancellationToken)); Console.WriteLine(output); } Stream stream = await client.Containers.GetContainerLogsAsync(containerId, new ContainerLogsParameters() { ShowStdout = true, ShowStderr = true }); StreamReader streamReader = new StreamReader(stream); Console.WriteLine(streamReader.ReadToEnd()); await StopContainer(containerId); await RemoveContainer(containerId); Console.WriteLine("Done!"); }
public async void Post() { Uri dockerSocket = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? new Uri("npipe://./pipe/docker_engine") : new Uri("unix:///var/run/docker.sock"); DockerClient client = new DockerClientConfiguration(dockerSocket).CreateClient(); await client.Images.CreateImageAsync(new ImagesCreateParameters { FromImage = "containrrr/watchtower:latest", FromSrc = "https://registry-1.docker.io", Repo = "containrrr/watchtower", Tag = "latest" }, null, new Progress <JSONMessage>()); CreateContainerResponse wtcontainer = await client.Containers.CreateContainerAsync(new CreateContainerParameters { Image = "containrrr/watchtower", Name = "watchtower", Cmd = new List <String>() { "wiki", "--cleanup", "--run-once", "--debug" }, HostConfig = new HostConfig { AutoRemove = true, Mounts = new Mount[] { new Mount() { ReadOnly = true, Source = "/var/run/docker.sock", Target = "/var/run/docker.sock", Type = "bind" } } }, AttachStderr = true, AttachStdout = true }); await client.Containers.StartContainerAsync(wtcontainer.ID, new ContainerStartParameters()); }
/// <summary> /// Unmarshaller the response from the service to the response class. /// </summary> /// <param name="context"></param> /// <returns></returns> public override AmazonWebServiceResponse Unmarshall(JsonUnmarshallerContext context) { CreateContainerResponse response = new CreateContainerResponse(); context.Read(); int targetDepth = context.CurrentDepth; while (context.ReadAtDepth(targetDepth)) { if (context.TestExpression("Container", targetDepth)) { var unmarshaller = ContainerUnmarshaller.Instance; response.Container = unmarshaller.Unmarshall(context); continue; } } return(response); }
private static async Task <string> WriteLog(DockerClient client, CreateContainerResponse container, ContainerLogsParameters op, CancellationToken token) { var log = await client.Containers.GetContainerLogsAsync(container.ID, op, token); var sb = new StringBuilder(); using (var reader = new StreamReader(log)) { while (!reader.EndOfStream) { var line = await reader.ReadLineAsync(); if (op.ShowStderr.HasValue && op.ShowStderr.Value) { Console.WriteLine(line); } sb.AppendLine(line.TrimEnd(Environment.NewLine.ToCharArray())); } } return(sb.ToString()); }
public async Task <string> CreateContainer(SandboxCreationConfig sandboxConfig) { CreateContainerResponse response = await client.Containers.CreateContainerAsync(new CreateContainerParameters() { Image = sandboxConfig.Image, Tty = true, // -it HostConfig = new HostConfig { PortBindings = new Dictionary <string, IList <PortBinding> > { { "8080/tcp", new List <PortBinding> { new PortBinding { HostPort = sandboxConfig.Port } } } } }, Volumes = new Dictionary <string, EmptyStruct>() { { $"{sandboxConfig.ConfigDir}:/home/coder/.local/share/code-server", default },
public async void StartContainerHub(string ImageName) { var CreateParameters = new CreateContainerParameters { Image = ImageName, Name = "selenium-hub", ExposedPorts = new Dictionary <string, EmptyStruct> { { "4444", default(EmptyStruct) } }, HostConfig = new HostConfig { PortBindings = new Dictionary <string, IList <PortBinding> > { { "4444", new List <PortBinding> { new PortBinding { HostPort = "4444" } } } }, PublishAllPorts = true }, ArgsEscaped = true, AttachStderr = true, AttachStdin = true, AttachStdout = true, }; try { CreateContainerResponse response = await client.Containers.CreateContainerAsync(CreateParameters); await client.Containers.StartContainerAsync(response.ID, null); } catch (Exception ex) { } }
//MIT License Code from: https://github.com/Activehigh/Atl.GenericRepository/blob/master/Atl.Repository.Standard.Tests/Repositories/ReadRepositoryTestsWithNpgsql.cs //for initializing the docker client public async Task InitializeAsync() { bool isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows); //This is the windows only pipe "npipe://./pipe/docker_engine" //Unix pipe is "unix:///var/run/docker.sock" - don'tmknow if it works for OSX _client = new DockerClientConfiguration(new Uri(isWindows ? "npipe://./pipe/docker_engine" : "unix:///var/run/docker.sock")).CreateClient(); var(containerRespose, port) = await GetContainer(_client, "postgres", "latest"); _containerResponse = containerRespose; var connectionStringBuilder = new NpgsqlConnectionStringBuilder() { ConnectionString = $"User ID=postgres;Password=password;Server=127.0.0.1;Port={port};Database=repotest;Integrated Security=true;Pooling=false;CommandTimeout=300" }; Db = new NpgsqlConnection(connectionStringBuilder.ConnectionString); Db.Open(); await InitializeTableStructure(Db); await PopulateTable(Db); }
public static async Task <IDisposable> StartContainerAsync( string image, IReadOnlyCollection <int> ports = null, IReadOnlyDictionary <string, string> environment = null) { using (var ts = new CancellationTokenSource(TimeSpan.FromMinutes(5))) { var env = environment ?.OrderBy(kv => kv.Key) .Select(kv => $"{kv.Key}={kv.Value}") .ToList(); Log.Info($"Starting container with image '{image}'"); Log.Info($"Pulling image {image}"); var imageAndTag = image.Split(':'); await DockerClient.Images.CreateImageAsync( new ImagesCreateParameters { FromImage = imageAndTag[0], Tag = imageAndTag.Length > 1 ? imageAndTag[1] : null }, null, new Progress <JSONMessage>(m => { Log.Trace($"{m.ProgressMessage} ({m.ID})"); }), ts.Token) .ConfigureAwait(false); while (true) { IList <ImagesListResponse> imagesListResponses = await DockerClient.Images.ListImagesAsync(new ImagesListParameters(), ts.Token).ConfigureAwait(false); if (imagesListResponses.Any(i => i.RepoTags != null && i.RepoTags.Any(t => string.Equals(t, image, StringComparison.OrdinalIgnoreCase)))) { break; } Thread.Sleep(TimeSpan.FromSeconds(1)); } CreateContainerResponse createContainerResponse = await DockerClient.Containers.CreateContainerAsync( new CreateContainerParameters( new Config { Image = image, Env = env, ExposedPorts = ports? .ToDictionary(p => $"{p}/tcp", p => new EmptyStruct()) }) { HostConfig = new HostConfig { PortBindings = ports?.ToDictionary( p => $"{p}/tcp", p => (IList <PortBinding>) new List <PortBinding> { new PortBinding { HostPort = p.ToString() } }) } }, ts.Token) .ConfigureAwait(false); Log.Info($"Successfully created container '{createContainerResponse.ID}'"); await DockerClient.Containers.StartContainerAsync( createContainerResponse.ID, new ContainerStartParameters(), ts.Token) .ConfigureAwait(false); Log.Info($"Successfully started container '{createContainerResponse.ID}'"); return(new DisposableAction(() => StopContainer(createContainerResponse.ID))); } }
/// <summary> /// Run a container. Does NOT pull the container - the assumption is that /// the container already exists.. /// </summary> /// <param name="image"></param> /// <param name="entrypoint"></param> /// <param name="args"></param> /// <param name="volumes"></param> /// <param name="environment"></param> /// <param name="workingDir"></param> /// <param name="cancelToken"></param> /// <returns></returns> public async Task RunContainerAsync(string image, string entrypoint, IEnumerable <string> args, IReadOnlyList <Volume> volumes, Dictionary <string, string> environment, string workingDir, CancellationToken cancelToken) { CreateContainerParameters parameters = new CreateContainerParameters() { Image = image, Entrypoint = entrypoint.ToEnumerable().AppendMany(args).ToList(), Env = environment?.Select((x, y) => $"{x}={y}")?.ToList(), Tty = false, HostConfig = new HostConfig() { Binds = volumes.Select(v => $"{v.SourcePath}:{v.DestinationPath}").ToList() }, WorkingDir = workingDir }; // Create the container. CreateContainerResponse container = await client.Containers.CreateContainerAsync(parameters, cancelToken); try { // Report any warnings from the docker daemon. foreach (string warning in container.Warnings) { warningHandler(warning); } // Start the container, and wait for it to exit. await client.Containers.StartContainerAsync(container.ID, new ContainerStartParameters(), cancelToken); // Watch stdout and/or stderr as necessary. Task stdoutListener = WatchStdoutStreamAsync(container.ID, cancelToken); Task stderrListener = WatchStderrStreamAsync(container.ID, cancelToken); // Wait for the container to exit. ContainerWaitResponse waitResponse = await client.Containers.WaitContainerAsync(container.ID, cancelToken); // Wait for output listeners if cancellation has not been requested. if (!cancelToken.IsCancellationRequested) { await stdoutListener.ConfigureAwait(false); await stderrListener.ConfigureAwait(false); } // If cancellation isn't requested, ensure the container exited gracefully. if (!cancelToken.IsCancellationRequested && waitResponse.StatusCode != 0) { (string stdout, string stderr) = await GetContainerLogsAsync(container.ID, parameters.Tty, cancelToken); StringBuilder output = new StringBuilder(); output.AppendLine(stdout); output.AppendLine(stderr); throw new Exception($"Container exited with non-zero exit code. Container log:\n{output}"); } } finally { ContainerRemoveParameters removeParameters = new ContainerRemoveParameters() { RemoveVolumes = true, Force = true }; ContainerKillParameters killParameters = new ContainerKillParameters() { }; // Only attempt to kill the container if it's still running. if (await IsRunning(container.ID)) { await client.Containers.KillContainerAsync(container.ID, killParameters); } await client.Containers.RemoveContainerAsync(container.ID, removeParameters); } }
private static async Task InitializeDatabaseServer() { const string image = "mcr.microsoft.com/mssql/server:2017-latest"; const string containerName = "dotnet-03-int-tests"; DockerClient dockerClient = new DockerClientConfiguration().CreateClient(); IList <ContainerListResponse> runningContainers = await dockerClient.Containers.ListContainersAsync(new ContainersListParameters()); IEnumerable <ContainerListResponse> testContainers = runningContainers.Where(container => container.Names.Any(name => name.Contains(containerName))); foreach (ContainerListResponse container in testContainers) { await dockerClient.Containers.StopContainerAsync(container.ID, new ContainerStopParameters()); await dockerClient.Containers.RemoveContainerAsync(container.ID, new ContainerRemoveParameters()); } await dockerClient.Images.CreateImageAsync(new ImagesCreateParameters { FromImage = image }, null, new Progress <JSONMessage>()); CreateContainerResponse sqlContainer = await dockerClient .Containers .CreateContainerAsync( new CreateContainerParameters { Name = containerName, Image = image, Env = new List <string> { "ACCEPT_EULA=Y", $"SA_PASSWORD={SqlSaPassword}" }, HostConfig = new HostConfig { PortBindings = new Dictionary <string, IList <PortBinding> > { { "1433/tcp", new[] { new PortBinding { HostPort = SqlPort } } } } } }); await dockerClient.Containers.StartContainerAsync(sqlContainer.ID, new ContainerStartParameters()); await WaitUntilDatabaseAvailableAsync(SqlPort); }
public async Task <ContainerExecutionResult> RunAsync(Command command) { var createContainerParameters = new CreateContainerParameters { Image = _configuration.ImageName, Tty = true, AttachStdin = true, Cmd = command.ProgramNameWithArguments, Env = command.EnvironmentVariables, WorkingDir = command.WorkingDirectory, HostConfig = new HostConfig { Memory = command.Limits.MemoryLimitInBytes } }; if (!string.IsNullOrWhiteSpace(command.MountDirectory)) { createContainerParameters.HostConfig.Mounts = new List <Mount> { new Mount { Type = "bind", Source = command.MountDirectory, Target = _configuration.DockerWorkingDir } }; } _createContainerResponse = await _client.Containers.CreateContainerAsync( createContainerParameters); await _client.Containers.StartContainerAsync(_createContainerResponse.ID, new ContainerStartParameters()); if (await TryKillContainerAfterTimeout(command)) { return(ContainerExecutionResult.KilledByTimeout); } var containerInspection = await _client.Containers.InspectContainerAsync(_createContainerResponse.ID); if (containerInspection.State.OOMKilled) { return(ContainerExecutionResult.KilledByMemoryLimit); } var errorOutputTask = GetContainerLogsAsync(new ContainerLogsParameters { ShowStderr = true }); var standardOutputTask = GetContainerLogsAsync(new ContainerLogsParameters { ShowStdout = true }); return(new ContainerExecutionResult { ExitCode = containerInspection.State.ExitCode, ErrorOutput = await errorOutputTask, StandardOutput = await standardOutputTask }); }
private async Task <bool> StartService(DenService service) { string id = string.Empty; bool started = false; try { if (this.OnLog != null) { this.OnLog($"{service.Name}"); } await service.CreateImage(); CreateContainerResponse ccr = await service.CreateContainer(service.ImageName); if (this.OnLog != null) { this.OnLog($"{service.Name} created"); } id = ccr.ID; if (this.OnLog != null) { this.OnLog($"Starting {service.Name}"); } started = id != string.Empty? await service.StartContainer(id): false; if (!started) { if (this.OnError != null) { this.OnError(new Exception($"Error running {service.Name} container")); } } else { if (this.OnLog != null) { this.OnLog($"{service.Name} started"); } if (service is DenHealthCheckService denHealthCheckService) { if (this.OnLog != null) { this.OnLog($"Waiting for {service.Name} health status"); } started = await service.IsHealthy(); if (started) { if (this.OnLog != null) { this.OnLog($"{service.Name} is healthy"); } } } this.RunningDenServices.Add(service); } } catch (DockerImageNotFoundException e) { this.OnError(e); } catch (DockerApiException e) { this.OnError(e); } return(started); }
/// <summary> /// Execute a deployment. /// </summary> /// <param name="deploymentId"> /// A unique identifier for the deployment. /// </param> /// <param name="templateImageTag"> /// The tag of the Docker image that implements the deployment template. /// </param> /// <param name="templateParameters"> /// A dictionary containing global template parameters to be written to the state directory. /// </param> /// <returns> /// <c>true</c>, if the deployment was started; otherwise, <c>false</c>. /// /// TODO: Consider returning an enum instead. /// </returns> public async Task <bool> DeployAsync(string deploymentId, string templateImageTag, IDictionary <string, string> templateParameters) { if (String.IsNullOrWhiteSpace(templateImageTag)) { throw new ArgumentException("Must supply a valid template image name.", nameof(templateImageTag)); } if (templateParameters == null) { throw new ArgumentNullException(nameof(templateParameters)); } try { Log.LogInformation("Starting deployment '{DeploymentId}' using image '{ImageTag}'...", deploymentId, templateImageTag); Log.LogInformation("Determining deployer's external IP address..."); IPAddress deployerIPAddress = await GetDeployerIPAddressAsync(); Log.LogInformation("Deployer's external IP address is '{DeployerIPAddress}'.", deployerIPAddress); templateParameters["deployment_ip"] = deployerIPAddress.ToString(); DirectoryInfo deploymentLocalStateDirectory = GetLocalStateDirectory(deploymentId); DirectoryInfo deploymentHostStateDirectory = GetHostStateDirectory(deploymentId); Log.LogInformation("Local state directory for deployment '{DeploymentId}' is '{LocalStateDirectory}'.", deploymentId, deploymentLocalStateDirectory.FullName); Log.LogInformation("Host state directory for deployment '{DeploymentId}' is '{LocalStateDirectory}'.", deploymentId, deploymentHostStateDirectory.FullName); WriteTemplateParameters(templateParameters, deploymentLocalStateDirectory); CreateContainerParameters createParameters = new CreateContainerParameters { Name = "deploy-" + deploymentId, Image = templateImageTag, AttachStdout = true, AttachStderr = true, HostConfig = new HostConfig { Binds = new List <string> { $"{deploymentHostStateDirectory.FullName}:/root/state" }, LogConfig = new LogConfig { Type = "json-file", Config = new Dictionary <string, string>() } }, Env = new List <string> { "ANSIBLE_NOCOLOR=1" // Disable coloured output because escape sequences look weird in the log. }, Labels = new Dictionary <string, string> { ["task.type"] = "deployment", ["deployment.id"] = deploymentId, ["deployment.action"] = "Deploy", ["deployment.image.deploy.tag"] = templateImageTag, ["deployment.image.destroy.tag"] = GetDestroyerImageTag(templateImageTag) } }; CreateContainerResponse newContainer = await Client.Containers.CreateContainerAsync(createParameters); string containerId = newContainer.ID; Log.LogInformation("Created container '{ContainerId}'.", containerId); await Client.Containers.StartContainerAsync(containerId, new HostConfig()); Log.LogInformation("Started container: '{ContainerId}'.", containerId); return(true); } catch (Exception unexpectedError) { Log.LogError("Unexpected error while executing deployment '{DeploymentId}': {Error}", deploymentId, unexpectedError); return(false); } }
public PlcOpcUaServer() { Uri dockerUri = null; try { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { dockerUri = new Uri("tcp://localhost:2375"); } if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { dockerUri = new Uri("unix:///var/run/docker.sock"); } if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { dockerUri = new Uri("not supported"); } _dockerClient = new DockerClientConfiguration(dockerUri).CreateClient(); } catch { throw new Exception($"Please adjust your docker deamon endpoint '{dockerUri}' for your configuration."); } // cleanup all PLC containers CleanupContainerAsync().Wait(); // pull the latest image ImagesCreateParameters createParameters = new ImagesCreateParameters(); createParameters.FromImage = _plcImage; createParameters.Tag = "latest"; try { _dockerClient.Images.CreateImageAsync(createParameters, new AuthConfig(), new Progress <JSONMessage>()).Wait(); } catch (Exception) { throw new Exception($"Cannot pull image '{_plcImage}"); } ImageInspectResponse imageInspectResponse = _dockerClient.Images.InspectImageAsync(_plcImage).Result; // create a new container CreateContainerParameters containerParams = new CreateContainerParameters(); containerParams.Image = _plcImage; containerParams.Hostname = "opcplc"; containerParams.Name = "opcplc"; containerParams.Cmd = new string[] { "--aa", "--pn", $"{_plcPort}" }; // workaround .NET2.1 issue for private key access if (imageInspectResponse.Os.Equals("windows", StringComparison.InvariantCultureIgnoreCase)) { containerParams.Cmd.Add("--at"); containerParams.Cmd.Add("X509Store"); } containerParams.ExposedPorts = new Dictionary <string, EmptyStruct>(); containerParams.ExposedPorts.Add(new KeyValuePair <string, EmptyStruct>($"{_plcPort}/tcp", new EmptyStruct())); containerParams.HostConfig = new HostConfig(); PortBinding portBinding = new PortBinding(); portBinding.HostPort = _plcPort; portBinding.HostIP = null; List <PortBinding> portBindings = new List <PortBinding>(); portBindings.Add(portBinding); containerParams.HostConfig.PortBindings = new Dictionary <string, IList <PortBinding> >(); containerParams.HostConfig.PortBindings.Add($"{_plcPort}/tcp", portBindings); CreateContainerResponse response = null; try { response = _dockerClient.Containers.CreateContainerAsync(containerParams).Result; _plcContainerId = response.ID; } catch (Exception) { throw; } try { _dockerClient.Containers.StartContainerAsync(_plcContainerId, new ContainerStartParameters()).Wait(); } catch (Exception) { throw; } }
private async Task <bool> StartContainer(CreateContainerResponse containerResponse) { return(await _repository.StartContainer(containerResponse.ID)); }
/// <summary> /// Destroy a deployment. /// </summary> /// <param name="deploymentId"> /// The deployment Id. /// </param> /// <returns> /// <c>true</c>, if the deployment was started; otherwise, <c>false</c>. /// /// TODO: Consider returning an enum instead. /// </returns> public async Task <bool> DestroyAsync(string deploymentId) { if (String.IsNullOrWhiteSpace(deploymentId)) { throw new ArgumentException("Must supply a valid deployment Id.", nameof(deploymentId)); } Log.LogInformation("Destroy deployment '{DeploymentId}'.", deploymentId); try { IList <ContainerListResponse> matchingContainers = await Client.Containers.ListContainersAsync(new ContainersListParameters { All = true, Filters = new FiltersDictionary { ["label"] = new FilterDictionary { ["deployment.id=" + deploymentId] = true } } }); if (matchingContainers.Count == 0) { Log.LogError("Deployment '{DeploymentId}' not found."); return(false); } string destroyerImageTag = matchingContainers[0].Labels["deployment.image.destroy.tag"]; Log.LogInformation("Starting destruction of deployment '{DeploymentId}' using image '{DestroyerImageTag}'...", deploymentId, destroyerImageTag); DirectoryInfo deploymentLocalStateDirectory = GetLocalStateDirectory(deploymentId); DirectoryInfo deploymentHostStateDirectory = GetHostStateDirectory(deploymentId); Log.LogInformation("Local state directory for deployment '{DeploymentId}' is '{LocalStateDirectory}'.", deploymentId, deploymentLocalStateDirectory.FullName); Log.LogInformation("Host state directory for deployment '{DeploymentId}' is '{LocalStateDirectory}'.", deploymentId, deploymentHostStateDirectory.FullName); CreateContainerParameters createParameters = new CreateContainerParameters { Name = "destroy-" + deploymentId, Image = destroyerImageTag, AttachStdout = true, AttachStderr = true, Tty = false, HostConfig = new HostConfig { Binds = new List <string> { $"{deploymentHostStateDirectory.FullName}:/root/state" }, LogConfig = new LogConfig { Type = "json-file", Config = new Dictionary <string, string>() } }, Env = new List <string> { "ANSIBLE_NOCOLOR=1" // Disable coloured output because escape sequences look weird in the log. }, Labels = new Dictionary <string, string> { ["task.type"] = "deployment", ["deployment.id"] = deploymentId, ["deployment.action"] = "Destroy", ["deployment.image.destroy.tag"] = destroyerImageTag } }; CreateContainerResponse newContainer = await Client.Containers.CreateContainerAsync(createParameters); string containerId = newContainer.ID; Log.LogInformation("Created container '{ContainerId}'.", containerId); await Client.Containers.StartContainerAsync(containerId, new HostConfig()); Log.LogInformation("Started container: '{ContainerId}'.", containerId); return(true); } catch (Exception unexpectedError) { Log.LogError("Unexpected error while destroying deployment '{DeploymentId}': {Error}", deploymentId, unexpectedError); return(false); } }
/// <summary> /// Called when the <see cref="Client"/> is ready to handle requests. /// </summary> void Ready() { // TODO: Handle termination of underlying Connection actor. Receive <ListImages>(listImages => { var executeCommand = new Connection.ExecuteCommand(listImages, async(dockerClient, cancellationToken) => { var parameters = new ImagesListParameters { MatchName = listImages.MatchName, All = listImages.All, Filters = listImages.Filters.ToMutable() }; IList <ImagesListResponse> images = await dockerClient.Images.ListImagesAsync(parameters); return(new ImageList(listImages.CorrelationId, images)); }); _connection.Tell(executeCommand, Sender); }); Receive <CreateContainer>(createContainer => { var executeCommand = new Connection.ExecuteCommand(createContainer, async(dockerClient, cancellationToken) => { var parameters = new CreateContainerParameters { Image = createContainer.Image, Name = createContainer.Name, AttachStdout = createContainer.AttachStdOut, AttachStderr = createContainer.AttachStdErr, AttachStdin = createContainer.AttachStdIn, Tty = createContainer.TTY, HostConfig = new HostConfig { // Hard-coded for now. LogConfig = new LogConfig { Type = createContainer.LogType } } // TODO: Add other parameters. }; if (createContainer.EnvironmentVariables.Count > 0) { parameters.Env = createContainer.EnvironmentVariables .Select( environmentVariable => $"{environmentVariable.Key}={environmentVariable.Value}" ) .ToList(); } if (createContainer.Binds.Count > 0) { parameters.HostConfig.Binds = createContainer.Binds .Select( bind => $"{bind.Key}:{bind.Value}" ) .ToList(); } if (createContainer.Ports.Count > 0) { parameters.ExposedPorts = createContainer.Ports.ToDictionary( port => port.Key, port => (object)port.Value ); } CreateContainerResponse response = await dockerClient.Containers.CreateContainerAsync(parameters); return(new ContainerCreated(createContainer.CorrelationId, response)); }); _connection.Tell(executeCommand, Sender); }); Receive <StartContainer>(startContainer => { var executeCommand = new Connection.ExecuteCommand(startContainer, async(dockerClient, cancellationToken) => { ContainerStartParameters parameters = new ContainerStartParameters { DetachKeys = startContainer.DetachKeys }; bool containerWasStarted = await dockerClient.Containers.StartContainerAsync(startContainer.ContainerId, parameters); return(new ContainerStarted(startContainer.CorrelationId, startContainer.ContainerId, alreadyStarted: !containerWasStarted )); }); _connection.Tell(executeCommand, Sender); }); Receive <StopContainer>(stopContainer => { var executeCommand = new Connection.ExecuteCommand(stopContainer, async(dockerClient, cancellationToken) => { var parameters = new ContainerStopParameters { WaitBeforeKillSeconds = stopContainer.WaitBeforeKillSeconds }; bool containerWasStopped = await dockerClient.Containers.StopContainerAsync(stopContainer.ContainerId, parameters, cancellationToken); return(new ContainerStopped(stopContainer.CorrelationId, stopContainer.ContainerId, alreadyStopped: !containerWasStopped )); }); _connection.Tell(executeCommand, Sender); }); Receive <RemoveContainer>(removeContainer => { var executeCommand = new Connection.ExecuteCommand(removeContainer, async(dockerClient, cancellationToken) => { await dockerClient.Containers.RemoveContainerAsync(removeContainer.ContainerId, removeContainer.Parameters); return(new ContainerRemoved(removeContainer.CorrelationId, removeContainer.ContainerId )); }); _connection.Tell(executeCommand, Sender); }); Receive <GetContainerLogs>(getContainerLogs => { Log.Debug("Received GetContainerLogs request '{0}' from '{1}'.", getContainerLogs.CorrelationId, Sender); var executeCommand = new Connection.ExecuteCommand(getContainerLogs, async(dockerClient, cancellationToken) => { Stream responseStream = await dockerClient.Containers.GetContainerLogsAsync( getContainerLogs.ContainerId, getContainerLogs.Parameters, cancellationToken ); return(new StreamedResponse(getContainerLogs.CorrelationId, responseStream, format: StreamedResponseFormat.Log)); }); _connection.Tell(executeCommand, Sender); }); Receive <MonitorContainerEvents>(monitorContainerEvents => { Log.Debug("Received MonitorContainerEvents request '{0}' from '{1}'.", monitorContainerEvents.CorrelationId, Sender); var executeCommand = new Connection.ExecuteCommand(monitorContainerEvents, async(dockerClient, cancellationToken) => { Stream responseStream = await dockerClient.Miscellaneous.MonitorEventsAsync(monitorContainerEvents.Parameters, cancellationToken); return(new StreamedResponse(monitorContainerEvents.CorrelationId, responseStream, format: StreamedResponseFormat.Events)); }); _connection.Tell(executeCommand, Sender); }); Receive <CancelRequest>(cancelRequest => { _connection.Forward(cancelRequest); }); Receive <EventBusActor.Subscribe>(subscribeToDockerEvents => { if (_dockerEventBus == null) { _dockerEventBus = Context.ActorOf( DockerEventBus.Create(Self), name: DockerEventBus.ActorName ); } _dockerEventBus.Forward(subscribeToDockerEvents); }); Receive <EventBusActor.Unsubscribe>(unsubscribeFromDockerEvents => { if (_dockerEventBus == null) { return; } _dockerEventBus.Forward(unsubscribeFromDockerEvents); }); }