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);
}