private async Task CreateRecoveryServiceContainer()

in src/ccf/virtual-ccf-provider/docker/DockerRecoveryServiceInstanceProvider.cs [166:276]


    private async Task<RecoveryServiceEndpoint> CreateRecoveryServiceContainer(
        string instanceName,
        string serviceName,
        string akvEndpoint,
        string maaEndpoint,
        NetworkJoinPolicy networkJoinPolicy,
        JsonObject? providerConfig,
        string skrEndpoint,
        CredentialsProxyEndpoint credsProxyEndpoint,
        EnvoyEndpoint envoyEndpoint)
    {
        string containerName = "recovery-service-" + instanceName;
        var imageParams = new ImagesCreateParameters
        {
            FromImage = ImageUtils.CcfRecoveryServiceImage(),
            Tag = ImageUtils.CcfRecoveryServiceTag(),
        };
        await this.client.Images.CreateImageAsync(
            imageParams,
            authConfig: null,
            new Progress<JSONMessage>(m => this.logger.LogInformation(m.ToProgressMessage())));

        string hostServiceCertDir = DockerClientEx.GetHostServiceCertDirectory("rs", instanceName);

        string hostInsecureVirtualDir =
            DockerClientEx.GetHostInsecureVirtualDirectory("rs", instanceName);
        string insecureVirtualDir =
            DockerClientEx.GetInsecureVirtualDirectory("rs", instanceName);
        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-service",
            insecureVirtualDir,
            recursive: true);

        string base64EncodedPolicy =
            Convert.ToBase64String(
                Encoding.UTF8.GetBytes(JsonSerializer.Serialize(networkJoinPolicy)));
        var createParams = new CreateContainerParameters
        {
            Labels = new Dictionary<string, string>
            {
                {
                    DockerConstants.CcfRecoveryServiceNameTag,
                    serviceName
                },
                {
                    DockerConstants.CcfRecoveryServiceTypeTag,
                    "recovery-service"
                },
                {
                    DockerConstants.CcfRecoveryServiceResourceNameTag,
                    instanceName
                }
            },
            Name = containerName,
            Image = $"{imageParams.FromImage}:{imageParams.Tag}",
            Env = new List<string>
            {
                $"ASPNETCORE_URLS=http://+:{Ports.RecoveryServicePort}",
                $"IDENTITY_ENDPOINT={credsProxyEndpoint.IdentityEndpoint}",
                $"IMDS_ENDPOINT={credsProxyEndpoint.ImdsEndpoint}",
                $"AKV_ENDPOINT={akvEndpoint}",
                $"MAA_ENDPOINT={maaEndpoint}",
                $"SKR_ENDPOINT={skrEndpoint}",
                $"CCF_NETWORK_INITIAL_JOIN_POLICY={base64EncodedPolicy}",
                $"SERVICE_CERT_LOCATION={DockerConstants.ServiceCertPemFilePath}",
                $"INSECURE_VIRTUAL_ENVIRONMENT=true"
            },
            ExposedPorts = new Dictionary<string, EmptyStruct>
            {
                {
                    $"{Ports.RecoveryServicePort}/tcp", new EmptyStruct()
                }
            },
            HostConfig = new HostConfig
            {
                Binds = new List<string>
                {
                    $"{hostServiceCertDir}:{DockerConstants.ServiceFolderMountPath}:ro",
                    $"{hostInsecureVirtualDir}:/app/insecure-virtual:ro"
                },
                NetworkMode = serviceName,

                // Although traffic will be routed via envoy exposing the HTTP port for easier
                // debugging.
                PortBindings = new Dictionary<string, IList<PortBinding>>
                {
                    {
                        $"{Ports.RecoveryServicePort}/tcp", new List<PortBinding>
                        {
                            new()
                            {
                                // Dynamic assignment.
                                HostPort = null
                            }
                        }
                    }
                }
            }
        };
        var container = await this.client.CreateOrGetContainer(createParams);

        await this.client.Containers.StartContainerAsync(
            container.ID,
            new ContainerStartParameters());

        return this.ToServiceEndpoint(envoyEndpoint);
    }