diff --git a/src/Types.ts b/src/Types.ts
index 283fa26..9bbaf3a 100644
--- a/src/Types.ts
+++ b/src/Types.ts
@@ -80,3 +80,23 @@ export interface DockerHubResponse {
content_types: string[]; // An array of supported content types for the repository
}
+export interface DockerCompose {
+ version: string;
+ services: {
+ [serviceName: string]: {
+ image: string;
+ ports?: string[];
+ environment?: { [envVar: string]: string };
+ volumes?: string[];
+ restart?: string;
+ command?: string;
+ build?: string | { context: string; dockerfile?: string };
+ networks?: string[] | { [networkName: string]: { aliases?: string[] } };
+ depends_on?: string[];
+ labels?: { [labelName: string]: string };
+ };
+ };
+ networks?: { [networkName: string]: {} };
+ volumes?: { [volumeName: string]: {} };
+}
+
diff --git a/src/lib/Header.svelte b/src/lib/Header.svelte
index 1291f3e..e6b654a 100644
--- a/src/lib/Header.svelte
+++ b/src/lib/Header.svelte
@@ -9,7 +9,7 @@
Portainer Templates
diff --git a/src/utils/template-to-docker-parser.ts b/src/utils/template-to-docker-parser.ts
new file mode 100644
index 0000000..2ed423a
--- /dev/null
+++ b/src/utils/template-to-docker-parser.ts
@@ -0,0 +1,88 @@
+
+import yaml from 'js-yaml';
+import type { Template, Volume, Service, DockerCompose } from '$src/Types';
+
+export const generateDockerRunCommand = (template: Template) => {
+ let command = `docker run -d \\ \n`;
+ if (template.ports) {
+ template.ports.forEach((port) => {
+ command += ` -p ${port} \\\n`;
+ });
+ }
+ if (template.env) {
+ template.env.forEach((env) => {
+ command += ` -e ${env.name}=\${${env.name}} \\\n`;
+ });
+ }
+ if (template.volumes) {
+ template.volumes.forEach((volume: Volume) => {
+ const readOnly = volume.readonly ? ":ro" : "";
+ command += ` -v ${volume.bind}:${volume.container}${readOnly} \\\n`;
+ });
+ }
+ if (template.restart_policy) {
+ command += ` --restart=${template.restart_policy} \\\n`;
+ }
+ command += ` ${template.image}`;
+ return command;
+};
+
+export const generateDockerRunCommands = (stack: Service[]) => {
+ const commands = stack.map((service) => {
+ let cmd = `docker run --name ${service.name} -d \\\n`;
+ if (service.command) {
+ cmd += ` ${service.command} \\\n`;
+ }
+ if (service.env) {
+ service.env.forEach((envVar) => {
+ cmd += ` -e "${envVar.value}" \\\n`;
+ });
+ }
+ if (service.ports) {
+ service.ports.forEach((port) => {
+ cmd += ` -p ${port} \\\n`;
+ });
+ }
+ if (service.volumes) {
+ service.volumes.forEach((volume) => {
+ cmd += ` -v ${volume.bind}:${volume.container} \\\n`;
+ });
+ }
+ if (service.restart_policy) {
+ cmd += ` --restart=${service.restart_policy} \\\n`;
+ }
+ cmd += ` ${service.image}`;
+ return cmd;
+ });
+ return commands;
+}
+
+export const convertToDockerCompose = (template: Template) => {
+ const serviceName = template.title.toLowerCase().replace(/[^a-z0-9]+/g, "-");
+ const dockerCompose: DockerCompose = {
+ version: "3.8",
+ services: { [serviceName]: { image: template.image } },
+ };
+ if (template.ports && template.ports.length > 0) {
+ dockerCompose.services[serviceName].ports = template.ports.map((port) => port.replace('/', ':'));
+ }
+ if (template.env && template.env.length > 0) {
+ dockerCompose.services[serviceName].environment = template.env.reduce((envVars, envVar) => {
+ envVars[envVar.name] = envVar.set || "";
+ return envVars;
+ }, {});
+ }
+ if (template.volumes && template.volumes.length > 0) {
+ dockerCompose.services[serviceName].volumes = template.volumes.map(
+ (volume) => `${volume.bind || ""}:${volume.container}`
+ );
+ }
+
+ return yaml.dump(dockerCompose);
+};
+
+export const convertPortainerStackToDockerCompose = (stack: Service[]) => {
+ const composeStack = stack.map(({ dockerStats, ...s }) => s);
+ return yaml.dump(composeStack);
+};
+