Question: Has anyone been able to work with the js-yaml library to write a docker compose like this?
Context:
I am working on dotnet templates and have some pre-defined application architecture patterns for our teams. I would like to take it a step further and create the docker compose
for the entirety of the ecosystem.
The main issue is on this line that I need to change the tokens and write to the YAML.
I have tried both of the following in the template and cannot have valid YAML output.
command: "./daprd -app-id ecosystemtemplate-${application} -app-port ${EXPOSED_PORT:-4443} --resources-path /app/config"
command: [ "./daprd", "-app-id", "ecosystemtemplate-${application}", "-app-port", "${EXPOSED_PORT:-4443}", "--resources-path", "/app/config"
How do I have the js-yaml
lib respect the items that are quoted and it should preserve the quotes?
Taking the above command
YAML and running it through json2yaml.com, the YAML->json looks correct, as does the json->YAML. To recreate this, I first copy the template YAML into the UI, then I copy the json and paste it again, thus updating the YAML output, which looks correct.
If I run this using the nodejs, I have incorrect output in the YAML. the image
, command
, and network_mode
all need quotes. I have hacked at this too many ways to list.
The PoC will become much more involved when this moves to product-ready enterprise-scale applications.
Example:
From the template, I create a solution.json
file that contains information that the ecosystem template uses.
The following code is used to read the solution.json
async function createDockerComposeYaml () {
console.log("Creating Docker Compose");
const fileName = 'docker-compose.yml';
const applicationDescriptor = '${application}';
await (async () => {
try {
await fs.unlink(fileName);
} catch (e) {
// Swallow the error.
// Normally happens when the file does not exist the first time.
}
})();
try {
const dockerComposeYaml = await fs.readFile('./docker-templates/compose/docker-compose-template.yml', 'utf-8');
const serviceYamlTokenized = await fs.readFile('./docker-templates/compose/docker-compose-service-template.yml', 'utf-8');
const daprSidecarYamlTokenized = await fs.readFile('./docker-templates/compose/docker-compose-service-dapr-sidecar-template.yml', 'utf-8');
let dockerCompose = YAML.load(dockerComposeYaml);
solutions.forEach(solution => {
// Build the service for the application.
let serviceYaml = serviceYamlTokenized.replaceAll('${application}', solution.name.toLowerCase());
serviceYaml = serviceYaml.replace('${dockerfile}', solution.dockerfile);
const service = YAML.load(serviceYaml);
// Build the service for the application dapr sidecar.
const serviceSidecarYaml = daprSidecarYamlTokenized.replaceAll('${application}', solution.name.toLowerCase());
const serviceSidecar = YAML.load(serviceSidecarYaml);
if (dockerCompose.services === null) {
dockerCompose.services = [];
}
dockerCompose.services.push(service);
dockerCompose.services.push(serviceSidecar);
});
writeFile(fileName, YAML.dump(dockerCompose, { 'forceQuotes': true }));
} catch(e) {
console.log(e);
}
}
Content:
solution.json
{
"name": "DddTemplate",
"template": "ddd",
"dockerfile": "DddTemplate/src/DddTemplate.Api/Dockerfile",
"launchSettings": "DddTemplate/src/DddTemplate.Api/Properties/launchSettings.json"
}
docker-compose-template.yml
version: '3.7'
name: EcosystemTemplate
volumes:
services:
docker-compose-service-template.yml
${application}:
image: ${DOCKER_REGISTRY-}${application}:${IMAGE_TAG}
build:
context: .
dockerfile: "${dockerfile}"
args:
- IMG_REGISTRY=${REGISTRY:-mcr.microsoft.com}
environment:
- ASPNETCORE_URLS=${ASPNETCORE_URLS:-https://*:4443}
ports:
- "43301:${EXPOSED_PORT:-4443}"
volumes:
- ~/.aspnet/https:/https:ro
docker-compose-service-dapr-sidecar-template.yml
${application}-dapr:
image: "daprio/daprd:latest"
command: "./daprd -app-id ${application} -app-port ${EXPOSED_PORT:-4443} --resources-path /app/config"
depends_on:
- ${application}
network_mode: "service:${application}"
volumes_from:
- ${application}