예제 #1
0
파일: Docker.cs 프로젝트: lie112/ApsimX
        /// <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);
            }
        }
예제 #2
0
        public async Task WaitOnServerExit(string containerId)
        {
            ContainerWaitResponse containerWaitResponse = await _dockerClient.Containers.WaitContainerAsync(containerId).ConfigureAwait(false);

            _logger.LogInformation($"Container {containerId} exited with exit code {containerWaitResponse.StatusCode}.");
        }