Browse Source

Pull docker images before running (#275)

* Pull docker images before running
- This step also validates that docker is installed before trying to pull and before running so that logic can be removed from the DockerRunner.
- Let the application exit if it tye run fails to start.

Fixes #222
pull/284/head
David Fowler 6 years ago
committed by GitHub
parent
commit
40ecc07dc2
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 91
      src/Microsoft.Tye.Hosting/DockerImagePuller.cs
  2. 16
      src/Microsoft.Tye.Hosting/DockerRunner.cs
  3. 27
      src/Microsoft.Tye.Hosting/TyeHost.cs

91
src/Microsoft.Tye.Hosting/DockerImagePuller.cs

@ -0,0 +1,91 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Tye.Hosting.Model;
namespace Microsoft.Tye.Hosting
{
public class DockerImagePuller : IApplicationProcessor
{
private readonly ILogger _logger;
public DockerImagePuller(ILogger logger)
{
_logger = logger;
}
public async Task StartAsync(Application application)
{
var images = new HashSet<string>();
foreach (var s in application.Services)
{
if (s.Value.Description.RunInfo is DockerRunInfo docker)
{
images.Add(docker.Image);
}
}
// No images, no docker skip it.
if (images.Count == 0)
{
return;
}
if (!await DockerDetector.Instance.IsDockerInstalled.Value)
{
_logger.LogError("Unable to detect docker installation. Docker is not installed.");
throw new CommandException("Docker is not installed.");
}
if (!await DockerDetector.Instance.IsDockerConnectedToDaemon.Value)
{
_logger.LogError("Unable to connect to docker daemon. Docker is not running.");
throw new CommandException("Docker is not running.");
}
var tasks = new Task[images.Count];
var index = 0;
foreach (var image in images)
{
tasks[index++] = PullContainerAsync(image);
}
await Task.WhenAll(tasks);
}
private async Task PullContainerAsync(string image)
{
await Task.Yield();
var command = $"pull {image}";
_logger.LogInformation("Running docker command {command}", command);
var result = await ProcessUtil.RunAsync(
"docker",
command,
outputDataReceived: data => _logger.LogInformation("{Image}: " + data, image),
errorDataReceived: data => _logger.LogInformation("{Image}: " + data, image),
throwOnError: false);
if (result.ExitCode != 0)
{
throw new CommandException("Docker pull command failed");
}
}
public Task StopAsync(Application application)
{
return Task.CompletedTask;
}
}
}

16
src/Microsoft.Tye.Hosting/DockerRunner.cs

@ -61,22 +61,6 @@ namespace Microsoft.Tye.Hosting
private async Task StartContainerAsync(Application application, Service service, DockerRunInfo docker)
{
if (!await DockerDetector.Instance.IsDockerInstalled.Value)
{
_logger.LogError("Unable to start docker container for service {ServiceName}, Docker is not installed.", service.Description.Name);
service.Logs.OnNext($"Unable to start docker container for service {service.Description.Name}, Docker is not installed.");
return;
}
if (!await DockerDetector.Instance.IsDockerConnectedToDaemon.Value)
{
_logger.LogError("Unable to start docker container for service {ServiceName}, Docker is not running.", service.Description.Name);
service.Logs.OnNext($"Unable to start docker container for service {service.Description.Name}, Docker is not running.");
return;
}
var serviceDescription = service.Description;
var environmentArguments = "";
var volumes = "";

27
src/Microsoft.Tye.Hosting/TyeHost.cs

@ -60,13 +60,18 @@ namespace Microsoft.Tye.Hosting
public async Task RunAsync()
{
await StartAsync();
var waitForStop = new TaskCompletionSource<object?>(TaskCreationOptions.RunContinuationsAsynchronously);
_lifetime?.ApplicationStopping.Register(obj => waitForStop.TrySetResult(null), null);
await waitForStop.Task;
try
{
await StartAsync();
await StopAsync();
var waitForStop = new TaskCompletionSource<object?>(TaskCreationOptions.RunContinuationsAsynchronously);
_lifetime?.ApplicationStopping.Register(obj => waitForStop.TrySetResult(null), null);
await waitForStop.Task;
}
finally
{
await StopAsync();
}
}
public async Task<WebApplication> StartAsync()
@ -91,14 +96,7 @@ namespace Microsoft.Tye.Hosting
_logger.LogInformation("Dashboard running on {Address}", app.Addresses.First());
try
{
await _processor.StartAsync(_application);
}
catch (Exception ex)
{
_logger.LogError(0, ex, "Failed to launch application");
}
await _processor.StartAsync(_application);
return app;
}
@ -280,6 +278,7 @@ namespace Microsoft.Tye.Hosting
new PortAssigner(logger),
new ProxyService(logger),
new HttpProxyService(logger),
new DockerImagePuller(logger),
new DockerRunner(logger, replicaRegistry),
new ProcessRunner(logger, replicaRegistry, ProcessRunnerOptions.FromArgs(args, servicesToDebug))
};

Loading…
Cancel
Save