public async Task CreateLoadBalancerContainer()

in src/ccf/virtual-ccf-provider/docker/DockerNginxLoadBalancerProvider.cs [160:267]


    public async Task<LoadBalancerEndpoint> CreateLoadBalancerContainer(
        string lbName,
        string networkName,
        List<string> servers,
        string? hostPort,
        JsonObject? providerConfig)
    {
        string containerName = lbName;

        string workspaceDir =
            Environment.GetEnvironmentVariable("WORKSPACE_DIR") ?? Directory.GetCurrentDirectory();
        var scratchDir = workspaceDir + $"/{ProviderFolderName}/{networkName}/nginx";

        Directory.CreateDirectory(scratchDir);

        List<string> nginxConfigTemplate =
            (await File.ReadAllLinesAsync("templates/nginx.conf"))!.ToList();
        int serverEntriesIndex =
            nginxConfigTemplate.FindIndex(0, (line) => line.Contains("$serverEntries"));

        List<string> nginxConfig = new();
        nginxConfig.AddRange(nginxConfigTemplate.Take(serverEntriesIndex));
        foreach (var server in servers)
        {
            nginxConfig.Add(nginxConfigTemplate[serverEntriesIndex].
                Replace("$serverEntries", $"server {server};"));
        }

        nginxConfig.AddRange(nginxConfigTemplate.Skip(serverEntriesIndex + 1));

        var nginxConfigPath = scratchDir + "/nginx.conf";

        await File.WriteAllLinesAsync(nginxConfigPath, nginxConfig);

        // Pack the contents of the directory into base64 encoded tar gzip string which then
        // gets uncompressed and expanded in the container.
        string tgzConfigData = await Utils.PackDirectory(scratchDir);

        var imageParams = new ImagesCreateParameters
        {
            FromImage = ImageUtils.CcfNginxImage(),
            Tag = ImageUtils.CcfNginxTag(),
        };

        await this.client.Images.CreateImageAsync(
            imageParams,
            authConfig: null,
            new Progress<JSONMessage>(m => this.logger.LogInformation(m.ToProgressMessage())));

        var createParams = new CreateContainerParameters
        {
            Labels = new Dictionary<string, string>
                {
                    {
                        DockerConstants.CcfNetworkNameTag,
                        networkName
                    },
                    {
                        DockerConstants.CcfNetworkTypeTag,
                        "load-balancer"
                    },
                    {
                        DockerConstants.CcfNetworkResourceNameTag,
                        lbName
                    }
                },
            Name = containerName,
            Image = $"{imageParams.FromImage}:{imageParams.Tag}",
            Env = new List<string>
                {
                $"CONFIG_DATA_TGZ={tgzConfigData}"
                },
            ExposedPorts = new Dictionary<string, EmptyStruct>
                {
                {
                    $"{NginxPort}/tcp", new EmptyStruct()
                },
                {
                    "80/tcp", new EmptyStruct()
                }
                },
            HostConfig = new HostConfig
            {
                NetworkMode = networkName,
                PortBindings = new Dictionary<string, IList<PortBinding>>
                    {
                    {
                        $"{NginxPort}/tcp", new List<PortBinding>
                        {
                            new()
                            {
                                HostPort = hostPort
                            }
                        }
                    }
                    }
            }
        };
        var container = await this.client.CreateOrGetContainer(createParams);

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

        // Fetch again after starting to get the port mapping information.
        container = await this.client.GetContainerById(container.ID);
        return this.ToLbEndpoint(container);
    }