in src/ccf/virtual-ccf-provider/docker/DockerNodeProvider.cs [882:987]
private async Task<RecoveryAgentEndpoint> CreateAndStartRecoveryAgentContainer(
string networkName,
NodeEndpoint nodeEndpoint)
{
var containerName = "recovery-agent-nw-" + nodeEndpoint.NodeName;
var envoyEndpoint = await this.CreateAndStartEnvoyProxyContainer(
networkName,
containerName,
nodeEndpoint);
var imageParams = new ImagesCreateParameters
{
FromImage = ImageUtils.CcfRecoveryAgentImage(),
Tag = ImageUtils.CcfRecoveryAgentTag(),
};
await this.client.Images.CreateImageAsync(
imageParams,
authConfig: null,
new Progress<JSONMessage>(m => this.logger.LogInformation(m.ToProgressMessage())));
string hostServiceCertDir =
DockerClientEx.GetHostServiceCertDirectory("ra", nodeEndpoint.NodeName);
string hostInsecureVirtualDir =
DockerClientEx.GetHostInsecureVirtualDirectory("ra", nodeEndpoint.NodeName);
string insecureVirtualDir =
DockerClientEx.GetInsecureVirtualDirectory("ra", nodeEndpoint.NodeName);
Directory.CreateDirectory(insecureVirtualDir);
// Copy out the test keys/report into the host directory so that it can be mounted into
// the container.
WorkspaceDirectories.CopyDirectory(
Directory.GetCurrentDirectory() + "/insecure-virtual/recovery-agent",
insecureVirtualDir,
recursive: true);
var createContainerParams = new CreateContainerParameters
{
Labels = new Dictionary<string, string>
{
{
DockerConstants.CcfNetworkNameTag,
networkName
},
{
DockerConstants.CcfNetworkTypeTag,
"recovery-agent"
},
{
DockerConstants.CcfNetworkResourceNameTag,
nodeEndpoint.NodeName
}
},
Name = containerName,
Image = $"{imageParams.FromImage}:{imageParams.Tag}",
Env =
[
$"CCF_ENDPOINT={nodeEndpoint.ClientRpcAddress}",
$"CCF_ENDPOINT_SKIP_TLS_VERIFY=true",
$"ASPNETCORE_URLS=http://+:{Ports.RecoveryAgentPort}",
$"SERVICE_CERT_LOCATION={DockerConstants.ServiceCertPemFilePath}",
$"INSECURE_VIRTUAL_ENVIRONMENT=true"
],
ExposedPorts = new Dictionary<string, EmptyStruct>
{
{
$"{Ports.RecoveryAgentPort}/tcp", new EmptyStruct()
}
},
HostConfig = new HostConfig
{
NetworkMode = networkName,
Devices = new List<DeviceMapping>(), // Allocate these as might be modified later.
CapAdd = new List<string>(),
Binds = new List<string>
{
$"{hostServiceCertDir}:{DockerConstants.ServiceFolderMountPath}:ro",
$"{hostInsecureVirtualDir}:/app/insecure-virtual:ro"
},
// Although traffic will be routed via envoy exposing the HTTP port for easier
// debugging.
PortBindings = new Dictionary<string, IList<PortBinding>>
{
{
$"{Ports.RecoveryAgentPort}/tcp", new List<PortBinding>
{
new()
{
// Dynamic assignment.
HostPort = null
}
}
}
}
}
};
this.logger.LogInformation($"Creating container: {createContainerParams.Name}");
var container = await this.client.CreateOrGetContainer(createContainerParams);
await this.client.Containers.StartContainerAsync(
container.ID,
new ContainerStartParameters());
return envoyEndpoint.ToRecoveryAgentEndpoint();
}