Repository: Azure/draft
Pull request #399 (2024-10-10 18:17:18)

Migrate Dockerfile to generic handler
# Description

Migrating the dockerfile templates to the generic template handler.

Adding Fixture for all dockerfile languages

## Type of change

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update
- [ ] Refactor

## How Has This Been Tested?

Provide instructions so we can reproduce, and list any relevant details for your test configuration. Please mention if this is a breaking change which will impact consuming tool(s).

- [x] Unit Test:
- [x] E2E Test:

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream modules



isutton: Please. Our use case will include applications with side-cars, so this would be really helpful.

Perhaps adding some sort of label/annotation to the "default" container, and an option to connect to other containers on the same pod.

`draft connect` would then either connect to:

* The only container in the pod, in the case there's only one;
* The first container in the pod (perhaps listed alphabetically?) in the case of many containers;
* The "default" container of the pod if there's a label/annotation in  the container;
* The specified container through `draft connect -c my-container`
michelleN: Would it be helpful if the default scenario was creating a connection for all containers? 

I really like the idea of adding a `-c` flag for which container to connect to. It is explicit and the developer wouldn't necessarily have to go mess with the kubernetes manifests in the chart.

The only issue I have with relying on labels or annotations is that I want to burden the developer with knowing too much about which part of the Kubernetes manifest to change. What do you think?
isutton: Sorry for the delay, completely missed this.

I understand your issue, but I think I haven't explained well enough that point. It was meant to aid the Chart developer to indicate which container to connect to by default and would be only specified if the setup would be rather complex. 

Although I think that this could be a "nice to have" and would depend on actual real life scenarios, thus it wouldn't be the first thing I'd implement.
radu-matei: @michelleN - is the `-c` flag something you want to add?
I might take a look at it during the weekend :)
michelleN: oh yeah that would be great! feel free to ping me if you have any questions. I'm @mnoorali on the kubernetes slack.
michelleN: @isutton yeah I'm with you on idea of adding this notion of a default container to connect to. I think using labels or annotations would be a great way to go about that.

Another option is to connect to all of the containers in the pod and provide a localhost url for each container. Do you think if that were the case, you'd still want to see default logic for connecting to one container? Not saying it has to be one or other; I just want to get your take.
radu-matei: Added in #528 

Patch:
diff --git a/cmd/create.go b/cmd/create.go
index 31dfbe5..c936093 100644
--- a/cmd/create.go
+++ b/cmd/create.go
@@ -19,12 +19,10 @@ import (
 	"github.com/Azure/draft/pkg/config"
 	dryrunpkg "github.com/Azure/draft/pkg/dryrun"
 	"github.com/Azure/draft/pkg/filematches"
-	"github.com/Azure/draft/pkg/languages"
 	"github.com/Azure/draft/pkg/linguist"
 	"github.com/Azure/draft/pkg/prompts"
 	"github.com/Azure/draft/pkg/templatewriter"
 	"github.com/Azure/draft/pkg/templatewriter/writers"
-	"github.com/Azure/draft/template"
 )
 
 // ErrNoLanguageDetected is raised when `draft create` does not detect source
@@ -52,8 +50,6 @@ type createCmd struct {
 	createConfigPath string
 	createConfig     *CreateConfig
 
-	supportedLangs *languages.Languages
-
 	templateWriter           templatewriter.TemplateWriter
 	templateVariableRecorder config.TemplateVariableRecorder
 	repoReader               reporeader.RepoReader
@@ -151,7 +147,7 @@ func (cc *createCmd) run() error {
 
 // detectLanguage detects the language used in a project destination directory
 // It returns the DraftConfig for that language and the name of the language
-func (cc *createCmd) detectLanguage() (*config.DraftConfig, string, error) {
+func (cc *createCmd) detectLanguage() (*handlers.Template, string, error) {
 	hasGo := false
 	hasGoMod := false
 	var langs []*linguist.Language
@@ -213,44 +209,48 @@ func (cc *createCmd) detectLanguage() (*config.DraftConfig, string, error) {
 		}
 	}
 
-	cc.supportedLangs = languages.CreateLanguagesFromEmbedFS(template.Dockerfiles, cc.dest)
-
 	if cc.createConfig.LanguageType != "" {
 		log.Debug("using configuration language")
 		lowerLang := strings.ToLower(cc.createConfig.LanguageType)
-		langConfig := cc.supportedLangs.GetConfig(lowerLang)
-		if langConfig == nil {
-			return nil, "", ErrNoLanguageDetected
+		langDockerfileTemplate, err := handlers.GetTemplate(fmt.Sprintf("dockerfile-%s", lowerLang), "", cc.dest, cc.templateWriter)
+		if err != nil {
+			return nil, "", err
+		}
+		if langDockerfileTemplate == nil {
+			return nil, "", fmt.Errorf("could not find a template for %s", cc.createConfig.LanguageType)
 		}
 
-		return langConfig, lowerLang, nil
+		return langDockerfileTemplate, lowerLang, nil
 	}
 
 	for _, lang := range langs {
 		detectedLang := linguist.Alias(lang)
 		log.Infof("--> Draft detected %s (%f%%)\n", detectedLang.Language, detectedLang.Percent)
 		lowerLang := strings.ToLower(detectedLang.Language)
-		if cc.supportedLangs.ContainsLanguage(lowerLang) {
+		if handlers.IsValidTemplate(fmt.Sprintf("dockerfile-%s", lowerLang)) {
 			if lowerLang == "go" && hasGo && hasGoMod {
 				log.Debug("detected go and go module")
 				lowerLang = "gomodule"
 			}
-			langConfig := cc.supportedLangs.GetConfig(lowerLang)
-			return langConfig, lowerLang, nil
+			langDockerfileTemplate, err := handlers.GetTemplate(fmt.Sprintf("dockerfile-%s", lowerLang), "", cc.dest, cc.templateWriter)
+			if err != nil {
+				return nil, "", err
+			}
+			if langDockerfileTemplate == nil {
+				return nil, "", fmt.Errorf("could not find a template for detected language %s", detectedLang.Language)
+			}
+			return langDockerfileTemplate, lowerLang, nil
 		}
 		log.Infof("--> Could not find a pack for %s. Trying to find the next likely language match...", detectedLang.Language)
 	}
 	return nil, "", ErrNoLanguageDetected
 }
 
-func (cc *createCmd) generateDockerfile(langConfig *config.DraftConfig, lowerLang string) error {
+func (cc *createCmd) generateDockerfile(dockerfileTemplate *handlers.Template, lowerLang string) error {
 	log.Info("--- Dockerfile Creation ---")
-	if cc.supportedLangs == nil {
-		return errors.New("supported languages were loaded incorrectly")
-	}
 
 	// Extract language-specific defaults from repo
-	extractedValues, err := cc.supportedLangs.ExtractDefaults(lowerLang, cc.repoReader)
+	extractedValues, err := dockerfileTemplate.ExtractDefaults(lowerLang, cc.repoReader)
 	if err != nil {
 		return err
 	}
@@ -258,15 +258,15 @@ func (cc *createCmd) generateDockerfile(langConfig *config.DraftConfig, lowerLan
 	// Check for existing duplicate defaults
 	for k, v := range extractedValues {
 		variableExists := false
-		for i, variable := range langConfig.Variables {
+		for i, variable := range dockerfileTemplate.Config.Variables {
 			if k == variable.Name {
 				variableExists = true
-				langConfig.Variables[i].Default.Value = v
+				dockerfileTemplate.Config.Variables[i].Default.Value = v
 				break
 			}
 		}
 		if !variableExists {
-			langConfig.Variables = append(langConfig.Variables, &config.BuilderVar{
+			dockerfileTemplate.Config.Variables = append(dockerfileTemplate.Config.Variables, &config.BuilderVar{
 				Name: k,
 				Default: config.BuilderVarDefault{
 					Value: v,
@@ -276,25 +276,25 @@ func (cc *createCmd) generateDockerfile(langConfig *config.DraftConfig, lowerLan
 	}
 
 	if cc.createConfig.LanguageVariables == nil {
-		langConfig.VariableMapToDraftConfig(flagVariablesMap)
+		dockerfileTemplate.Config.VariableMapToDraftConfig(flagVariablesMap)
 
-		if err = prompts.RunPromptsFromConfigWithSkips(langConfig); err != nil {
+		if err = prompts.RunPromptsFromConfigWithSkips(dockerfileTemplate.Config); err != nil {
 			return err
 		}
 	} else {
-		err = validateConfigInputsToPrompts(langConfig, cc.createConfig.LanguageVariables)
+		err = validateConfigInputsToPrompts(dockerfileTemplate.Config, cc.createConfig.LanguageVariables)
 		if err != nil {
 			return err
 		}
 	}
 
 	if cc.templateVariableRecorder != nil {
-		for _, variable := range langConfig.Variables {
+		for _, variable := range dockerfileTemplate.Config.Variables {
 			cc.templateVariableRecorder.Record(variable.Name, variable.Value)
 		}
 	}
 
-	if err = cc.supportedLangs.CreateDockerfileForLanguage(lowerLang, langConfig, cc.templateWriter); err != nil {
+	if err = dockerfileTemplate.Generate(); err != nil {
 		return fmt.Errorf("there was an error when creating the Dockerfile for language %s: %w", cc.createConfig.LanguageType, err)
 	}
 
@@ -363,7 +363,7 @@ func (cc *createCmd) createDeployment() error {
 	return deployTemplate.Generate()
 }
 
-func (cc *createCmd) createFiles(detectedLang *config.DraftConfig, lowerLang string) error {
+func (cc *createCmd) createFiles(detectedLangTempalte *handlers.Template, lowerLang string) error {
 	// does no further checks without file detection
 
 	if cc.dockerfileOnly && cc.deploymentOnly {
@@ -372,7 +372,7 @@ func (cc *createCmd) createFiles(detectedLang *config.DraftConfig, lowerLang str
 
 	if cc.skipFileDetection {
 		if !cc.deploymentOnly {
-			err := cc.generateDockerfile(detectedLang, lowerLang)
+			err := cc.generateDockerfile(detectedLangTempalte, lowerLang)
 			if err != nil {
 				return err
 			}
@@ -412,7 +412,7 @@ func (cc *createCmd) createFiles(detectedLang *config.DraftConfig, lowerLang str
 	} else if hasDockerFile {
 		log.Info("--> Found Dockerfile in local directory, skipping Dockerfile creation...")
 	} else if !cc.deploymentOnly {
-		err := cc.generateDockerfile(detectedLang, lowerLang)
+		err := cc.generateDockerfile(detectedLangTempalte, lowerLang)
 		if err != nil {
 			return err
 		}
diff --git a/cmd/info.go b/cmd/info.go
index 449dd65..ee1a2f0 100644
--- a/cmd/info.go
+++ b/cmd/info.go
@@ -7,8 +7,7 @@ import (
 	log "github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
 
-	"github.com/Azure/draft/pkg/languages"
-	"github.com/Azure/draft/template"
+	"github.com/Azure/draft/pkg/handlers"
 )
 
 type Format string
@@ -61,15 +60,14 @@ func newInfoCmd() *cobra.Command {
 
 func (ic *infoCmd) run() error {
 	log.Debugf("getting supported languages")
-	l := languages.CreateLanguagesFromEmbedFS(template.Dockerfiles, "")
+	supportedDockerfileTemplates := handlers.GetTemplatesByType(handlers.TemplateTypeDockerfile)
 
 	languagesInfo := make([]draftConfigInfo, 0)
-	for _, lang := range l.Names() {
-		langConfig := l.GetConfig(lang)
+	for _, template := range supportedDockerfileTemplates {
 		newConfig := draftConfigInfo{
-			Name:                  lang,
-			DisplayName:           langConfig.DisplayName,
-			VariableExampleValues: langConfig.GetVariableExampleValues(),
+			Name:                  template.Config.TemplateName,
+			DisplayName:           template.Config.DisplayName,
+			VariableExampleValues: template.Config.GetVariableExampleValues(),
 		}
 		languagesInfo = append(languagesInfo, newConfig)
 	}
diff --git a/example/deployment.go b/example/deployment.go
index dc6adf3..095c8d2 100644
--- a/example/deployment.go
+++ b/example/deployment.go
@@ -20,7 +20,7 @@ func WriteDeploymentFilesExample() error {
 	// Select the deployment type to generate the files for (must correspond to a directory in the template/deployments directory)
 	deploymentTemplateType := "deployment-manifests"
 
-	// Create a DraftConfig of inputs to the template (must correspond to the inputs in the template/deployments/<deploymentType>/draft.yaml files)
+	// Create a map of of inputs to the template (must correspond to the inputs in the template/deployments/<deploymentType>/draft.yaml files)
 	templateVars := map[string]string{
 		"PORT":           "8080",
 		"APPNAME":        "example-app",
diff --git a/example/dockerfile.go b/example/dockerfile.go
index 0667028..d3eb5e0 100644
--- a/example/dockerfile.go
+++ b/example/dockerfile.go
@@ -3,24 +3,10 @@ package example
 import (
 	"fmt"
 
-	"github.com/Azure/draft/pkg/config"
-	"github.com/Azure/draft/pkg/languages"
-	"github.com/Azure/draft/pkg/templatewriter"
+	"github.com/Azure/draft/pkg/handlers"
 	"github.com/Azure/draft/pkg/templatewriter/writers"
-	"github.com/Azure/draft/template"
 )
 
-// WriteDockerfile generates a Dockerfile and dockerignore using Draft, writing to a Draft TemplateWriter. See the corresponding draft.yaml file in templates/dockerfiles/[language] for the template inputs.
-func WriteDockerfile(w templatewriter.TemplateWriter, dockerfileOutputPath string, langConfig *config.DraftConfig, generationLanguage string) error {
-	l := languages.CreateLanguagesFromEmbedFS(template.Dockerfiles, dockerfileOutputPath)
-
-	err := l.CreateDockerfileForLanguage(generationLanguage, langConfig, w)
-	if err != nil {
-		return fmt.Errorf("failed to generate dockerfile: %e", err)
-	}
-	return nil
-}
-
 // WriteDockerfileExample shows how to set up a fileWriter and generate a fileMap using WriteDockerfile
 func WriteDockerfileExample() error {
 	// Create a file map
@@ -34,27 +20,38 @@ func WriteDockerfileExample() error {
 	// Select the language to generate the Dockerfile for (must correspond to a directory in the template/dockerfiles directory)
 	generationLanguage := "go"
 
-	// Create a DraftConfig of inputs to the template (must correspond to the inputs in the template/dockerfiles/<language>/draft.yaml files)
-	langConfig := &config.DraftConfig{
-		Variables: []*config.BuilderVar{
-			{
-				Name:  "PORT",
-				Value: "8080",
-			},
-			{
-				Name:  "VERSION",
-				Value: "1.20",
-			},
-		},
+	// Create a map of inputs to the template (must correspond to the inputs in the template/dockerfiles/<language>/draft.yaml files)
+	templateVars := map[string]string{
+		"PORT":           "8080",
+		"APPNAME":        "example-app",
+		"SERVICEPORT":    "8080",
+		"NAMESPACE":      "example-namespace",
+		"IMAGENAME":      "example-image",
+		"IMAGETAG":       "latest",
+		"GENERATORLABEL": "draft",
 	}
 
 	// Set the output path for the Dockerfile
 	outputPath := "./"
 
-	// Write the Dockerfile
-	err := WriteDockerfile(&w, outputPath, langConfig, generationLanguage)
+	// Get the dockerfile template
+	d, err := handlers.GetTemplate(fmt.Sprintf("dockerfile-%s", generationLanguage), "", outputPath, &w)
 	if err != nil {
-		return err
+		return fmt.Errorf("failed to get template: %e", err)
+	}
+	if d == nil {
+		return fmt.Errorf("template is nil")
+	}
+
+	// Set the variable values within the template
+	for k, v := range templateVars {
+		d.Config.SetVariable(k, v)
+	}
+
+	// Generate the dockerfile files
+	err = d.Generate()
+	if err != nil {
+		return fmt.Errorf("failed to generate dockerfile: %e", err)
 	}
 
 	// Read written files from the file map
diff --git a/pkg/fixtures/dockerfiles/clojure/.dockerignore b/pkg/fixtures/dockerfiles/clojure/.dockerignore
new file mode 100644
index 0000000..5b48e5e
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/clojure/.dockerignore
@@ -0,0 +1,5 @@
+Dockerfile
+charts/
+resources/
+target/
+test/
diff --git a/pkg/fixtures/dockerfiles/clojure/Dockerfile b/pkg/fixtures/dockerfiles/clojure/Dockerfile
new file mode 100644
index 0000000..283c5a4
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/clojure/Dockerfile
@@ -0,0 +1,13 @@
+FROM clojure as BUILD
+COPY . /usr/src/app
+WORKDIR /usr/src/app
+RUN lein ring uberjar
+
+FROM eclipse-temurin:19-jdk-alpine
+
+RUN apk update && apk upgrade && apk add bash
+ENV PORT 80
+EXPOSE 80
+COPY --from=BUILD /usr/src/app/target/*.jar /opt/
+WORKDIR /opt
+CMD ["/bin/bash", "-c", "find -type f -name '*standalone.jar' | xargs java -jar"]
diff --git a/pkg/fixtures/dockerfiles/csharp/.dockerignore b/pkg/fixtures/dockerfiles/csharp/.dockerignore
new file mode 100644
index 0000000..ac69008
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/csharp/.dockerignore
@@ -0,0 +1,4 @@
+Dockerfile
+charts/
+bin/
+obj/
diff --git a/pkg/fixtures/dockerfiles/csharp/Dockerfile b/pkg/fixtures/dockerfiles/csharp/Dockerfile
new file mode 100644
index 0000000..de6c156
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/csharp/Dockerfile
@@ -0,0 +1,21 @@
+FROM mcr.microsoft.com/dotnet/sdk:6.0 AS builder
+WORKDIR /app
+
+# caches restore result by copying csproj file separately
+COPY *.csproj .
+RUN dotnet restore
+
+COPY . .
+RUN dotnet publish --output /app/ --configuration Release --no-restore
+RUN sed -n 's:.*<AssemblyName>\(.*\)</AssemblyName>.*:\1:p' *.csproj > __assemblyname
+RUN if [ ! -s __assemblyname ]; then filename=$(ls *.csproj); echo ${filename%.*} > __assemblyname; fi
+
+# Stage 2
+FROM mcr.microsoft.com/dotnet/aspnet:6.0
+WORKDIR /app
+COPY --from=builder /app .
+
+ENV PORT 80
+EXPOSE 80
+
+ENTRYPOINT dotnet $(cat /app/__assemblyname).dll --urls "http://*:80"
diff --git a/pkg/fixtures/dockerfiles/erlang/.dockerignore b/pkg/fixtures/dockerfiles/erlang/.dockerignore
new file mode 100644
index 0000000..e851355
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/erlang/.dockerignore
@@ -0,0 +1,3 @@
+# files and directories to exclude from context
+Dockerfile
+_build
\ No newline at end of file
diff --git a/pkg/fixtures/dockerfiles/erlang/Dockerfile b/pkg/fixtures/dockerfiles/erlang/Dockerfile
new file mode 100644
index 0000000..8f6c8c3
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/erlang/Dockerfile
@@ -0,0 +1,40 @@
+FROM erlang:27.0-alpine as builder
+
+RUN apk add --update tar curl git bash make libc-dev gcc g++ && \
+    rm -rf /var/cache/apk/*
+
+RUN set -xe \
+    && curl -fSL -o rebar3 "https://s3.amazonaws.com/rebar3/rebar3" \
+    && chmod +x ./rebar3 \
+    && ./rebar3 local install \
+    && rm ./rebar3
+
+WORKDIR /usr/src/app
+COPY . /usr/src/app
+
+ENV PATH "$PATH:/root/.cache/rebar3/bin"
+RUN rebar3 as prod tar
+
+RUN mkdir -p /opt/rel
+RUN tar -zxvf /usr/src/app/_build/prod/rel/*/*.tar.gz -C /opt/rel
+
+RUN relname=$(ls _build/prod/rel) ; echo $relname > /opt/rel/__relname
+
+FROM alpine:3.17
+
+RUN apk add --no-cache openssl-dev ncurses libstdc++ libgcc
+
+WORKDIR /opt/rel
+
+ENV RELX_REPLACE_OS_VARS true
+ENV HTTP_PORT 80
+
+COPY --from=builder /opt/rel /opt/rel
+
+EXPOSE 80 80
+
+RUN ln -s /opt/rel/bin/$(cat /opt/rel/__relname) /opt/rel/bin/start_script
+ENTRYPOINT ["/opt/rel/bin/start_script"]
+
+CMD ["foreground"]
+
diff --git a/pkg/fixtures/dockerfiles/go/.dockerignore b/pkg/fixtures/dockerfiles/go/.dockerignore
new file mode 100644
index 0000000..843dec4
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/go/.dockerignore
@@ -0,0 +1,2 @@
+Dockerfile
+charts/
diff --git a/pkg/fixtures/dockerfiles/go/Dockerfile b/pkg/fixtures/dockerfiles/go/Dockerfile
new file mode 100644
index 0000000..83b7699
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/go/Dockerfile
@@ -0,0 +1,12 @@
+FROM golang:1.23
+ENV PORT=80
+EXPOSE 80
+
+WORKDIR /go/src/app
+COPY . .
+
+ARG GO111MODULE=off
+RUN go build -v -o app ./main.go
+RUN mv ./app /go/bin/
+
+CMD ["app"]
\ No newline at end of file
diff --git a/pkg/fixtures/dockerfiles/gomodule/.dockerignore b/pkg/fixtures/dockerfiles/gomodule/.dockerignore
new file mode 100644
index 0000000..843dec4
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/gomodule/.dockerignore
@@ -0,0 +1,2 @@
+Dockerfile
+charts/
diff --git a/pkg/fixtures/dockerfiles/gomodule/Dockerfile b/pkg/fixtures/dockerfiles/gomodule/Dockerfile
new file mode 100644
index 0000000..1b334c2
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/gomodule/Dockerfile
@@ -0,0 +1,16 @@
+FROM golang:1.23 AS builder
+
+WORKDIR /build
+COPY go.mod go.sum ./
+RUN go mod download && go mod verify
+COPY . .
+RUN CGO_ENABLED=0 GOOS=linux go build -v -o app-binary
+
+FROM gcr.io/distroless/static-debian12
+
+ENV PORT=80
+EXPOSE 80
+
+WORKDIR /app
+COPY --from=builder /build/app-binary . 
+CMD ["/app/app-binary"]
diff --git a/pkg/fixtures/dockerfiles/gradle/.dockerignore b/pkg/fixtures/dockerfiles/gradle/.dockerignore
new file mode 100644
index 0000000..843dec4
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/gradle/.dockerignore
@@ -0,0 +1,2 @@
+Dockerfile
+charts/
diff --git a/pkg/fixtures/dockerfiles/gradle/Dockerfile b/pkg/fixtures/dockerfiles/gradle/Dockerfile
new file mode 100644
index 0000000..61b7926
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/gradle/Dockerfile
@@ -0,0 +1,13 @@
+FROM gradle:jdk21 as BUILD
+
+COPY --chown=gradle:gradle . /project
+RUN gradle -i -s -b /project/build.gradle clean build
+
+FROM eclipse-temurin:21-jre
+ENV PORT 80
+EXPOSE 80
+
+COPY --from=BUILD /project/build/libs/* /opt/
+WORKDIR /opt/
+RUN ls -l
+CMD ["/bin/bash", "-c", "find -type f -name '*SNAPSHOT.jar' | xargs java -jar"]
diff --git a/pkg/fixtures/dockerfiles/gradlew/.dockerignore b/pkg/fixtures/dockerfiles/gradlew/.dockerignore
new file mode 100644
index 0000000..843dec4
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/gradlew/.dockerignore
@@ -0,0 +1,2 @@
+Dockerfile
+charts/
diff --git a/pkg/fixtures/dockerfiles/gradlew/Dockerfile b/pkg/fixtures/dockerfiles/gradlew/Dockerfile
new file mode 100644
index 0000000..4c5aede
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/gradlew/Dockerfile
@@ -0,0 +1,17 @@
+FROM gradle:jdk21 as BUILD
+
+COPY --chown=gradle:gradle . /project
+COPY gradlew gradlew
+COPY gradle/wrapper gradle/wrapper
+RUN chmod +x gradle/wrapper
+RUN chmod +x gradlew
+RUN ./gradlew -i -s -b /project/build.gradle clean build
+
+FROM eclipse-temurin:21-jre
+ENV PORT 80
+EXPOSE 80
+
+COPY --from=BUILD /project/build/libs/* /opt/
+WORKDIR /opt/
+RUN ls -l
+CMD ["/bin/bash", "-c", "find -type f -name '*SNAPSHOT.jar' | xargs java -jar"]
\ No newline at end of file
diff --git a/pkg/fixtures/dockerfiles/java/.dockerignore b/pkg/fixtures/dockerfiles/java/.dockerignore
new file mode 100644
index 0000000..c81336f
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/java/.dockerignore
@@ -0,0 +1,5 @@
+Dockerfile
+charts/
+target/
+work/
+.git/
diff --git a/pkg/fixtures/dockerfiles/java/Dockerfile b/pkg/fixtures/dockerfiles/java/Dockerfile
new file mode 100644
index 0000000..5fd9613
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/java/Dockerfile
@@ -0,0 +1,12 @@
+FROM maven:3 as BUILD
+
+COPY . /usr/src/app
+RUN mvn --batch-mode -f /usr/src/app/pom.xml clean package
+
+FROM eclipse-temurin:21-jre
+ENV PORT 80
+EXPOSE 80
+COPY --from=BUILD /usr/src/app/target /opt/target
+WORKDIR /opt/target
+
+CMD ["/bin/bash", "-c", "find -type f -name '*-SNAPSHOT.jar' | xargs java -jar"]
diff --git a/pkg/fixtures/dockerfiles/javascript/.dockerignore b/pkg/fixtures/dockerfiles/javascript/.dockerignore
new file mode 100644
index 0000000..843dec4
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/javascript/.dockerignore
@@ -0,0 +1,2 @@
+Dockerfile
+charts/
diff --git a/pkg/fixtures/dockerfiles/javascript/Dockerfile b/pkg/fixtures/dockerfiles/javascript/Dockerfile
new file mode 100644
index 0000000..12be52f
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/javascript/Dockerfile
@@ -0,0 +1,11 @@
+FROM node:14.15.4
+ENV PORT 80
+EXPOSE 80
+
+RUN mkdir -p /usr/src/app
+WORKDIR /usr/src/app
+COPY package.json .
+RUN npm install
+COPY . .
+
+CMD ["npm", "start"]
diff --git a/pkg/fixtures/dockerfiles/php/.dockerignore b/pkg/fixtures/dockerfiles/php/.dockerignore
new file mode 100644
index 0000000..843dec4
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/php/.dockerignore
@@ -0,0 +1,2 @@
+Dockerfile
+charts/
diff --git a/pkg/fixtures/dockerfiles/php/Dockerfile b/pkg/fixtures/dockerfiles/php/Dockerfile
new file mode 100644
index 0000000..ed65028
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/php/Dockerfile
@@ -0,0 +1,11 @@
+FROM composer:1 AS build-env
+COPY . /app
+RUN cd /app && composer install
+
+FROM php:7.1-apache
+ENV PORT 80
+EXPOSE 80
+COPY --from=build-env /app /var/www/html
+RUN usermod -u 1000 www-data; \
+    a2enmod rewrite; \
+    chown -R www-data:www-data /var/www/html
diff --git a/pkg/fixtures/dockerfiles/python/.dockerignore b/pkg/fixtures/dockerfiles/python/.dockerignore
new file mode 100644
index 0000000..843dec4
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/python/.dockerignore
@@ -0,0 +1,2 @@
+Dockerfile
+charts/
diff --git a/pkg/fixtures/dockerfiles/python/Dockerfile b/pkg/fixtures/dockerfiles/python/Dockerfile
new file mode 100644
index 0000000..27d5e8b
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/python/Dockerfile
@@ -0,0 +1,12 @@
+FROM python:3.9
+ENV PORT 80
+EXPOSE 80
+WORKDIR /usr/src/app
+
+COPY requirements.txt ./
+RUN pip install --no-cache-dir -r requirements.txt
+
+COPY . .
+
+ENTRYPOINT ["python"]
+CMD ["app.py"]
\ No newline at end of file
diff --git a/pkg/fixtures/dockerfiles/ruby/.dockerignore b/pkg/fixtures/dockerfiles/ruby/.dockerignore
new file mode 100644
index 0000000..3e5a44e
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/ruby/.dockerignore
@@ -0,0 +1,3 @@
+Dockerfile
+charts/
+tmp/
diff --git a/pkg/fixtures/dockerfiles/ruby/Dockerfile b/pkg/fixtures/dockerfiles/ruby/Dockerfile
new file mode 100644
index 0000000..28fccec
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/ruby/Dockerfile
@@ -0,0 +1,12 @@
+FROM ruby:3.1.2
+ENV PORT 80
+EXPOSE 80
+RUN bundle config --global frozen 1
+
+WORKDIR /usr/src/app
+
+COPY Gemfile Gemfile.lock ./
+RUN bundle install
+
+COPY . .
+CMD ["ruby", "app.rb"]
diff --git a/pkg/fixtures/dockerfiles/rust/.dockerignore b/pkg/fixtures/dockerfiles/rust/.dockerignore
new file mode 100644
index 0000000..160b0d8
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/rust/.dockerignore
@@ -0,0 +1,3 @@
+Dockerfile
+charts/
+target
diff --git a/pkg/fixtures/dockerfiles/rust/Dockerfile b/pkg/fixtures/dockerfiles/rust/Dockerfile
new file mode 100644
index 0000000..5ea25b5
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/rust/Dockerfile
@@ -0,0 +1,10 @@
+FROM rust:1.70.0
+
+WORKDIR /usr/src/app
+COPY . /usr/src/app
+RUN cargo build
+
+ENV PORT 80
+EXPOSE 80
+
+CMD ["cargo", "run", "-q"]
diff --git a/pkg/fixtures/dockerfiles/swift/.dockerignore b/pkg/fixtures/dockerfiles/swift/.dockerignore
new file mode 100644
index 0000000..843dec4
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/swift/.dockerignore
@@ -0,0 +1,2 @@
+Dockerfile
+charts/
diff --git a/pkg/fixtures/dockerfiles/swift/Dockerfile b/pkg/fixtures/dockerfiles/swift/Dockerfile
new file mode 100644
index 0000000..13a0a02
--- /dev/null
+++ b/pkg/fixtures/dockerfiles/swift/Dockerfile
@@ -0,0 +1,11 @@
+FROM swift:5.5
+
+WORKDIR /src
+COPY . /src
+RUN apt-get update && apt-get install -y sudo openssl libssl-dev libcurl4-openssl-dev
+RUN swift build -c release
+
+ENV PORT 80
+EXPOSE 80
+
+CMD ["swift", "run"]
diff --git a/pkg/handlers/template.go b/pkg/handlers/template.go
index c64d6e8..0c6769c 100644
--- a/pkg/handlers/template.go
+++ b/pkg/handlers/template.go
@@ -9,6 +9,8 @@ import (
 	tmpl "text/template"
 
 	"github.com/Azure/draft/pkg/config"
+	"github.com/Azure/draft/pkg/handlers/variableextractors/defaults"
+	"github.com/Azure/draft/pkg/reporeader"
 	"github.com/Azure/draft/pkg/templatewriter"
 	log "github.com/sirupsen/logrus"
 )
@@ -109,6 +111,35 @@ func (t *Template) DeepCopy() *Template {
 	}
 }
 
+func (l *Template) ExtractDefaults(lowerLang string, r reporeader.RepoReader) (map[string]string, error) {
+	extractors := []reporeader.VariableExtractor{
+		&defaults.PythonExtractor{},
+		&defaults.GradleExtractor{},
+	}
+	extractedValues := make(map[string]string)
+	if r == nil {
+		log.Debugf("no repo reader provided, returning empty list of defaults")
+		return extractedValues, nil
+	}
+	for _, extractor := range extractors {
+		if extractor.MatchesLanguage(lowerLang) {
+			newDefaults, err := extractor.ReadDefaults(r)
+			if err != nil {
+				return nil, fmt.Errorf("error reading defaults for language %s: %v", lowerLang, err)
+			}
+			for k, v := range newDefaults {
+				if _, ok := extractedValues[k]; ok {
+					log.Debugf("duplicate default %s for language %s with extractor %s", k, lowerLang, extractor.GetName())
+				}
+				extractedValues[k] = v
+				log.Debugf("extracted default %s=%s with extractor:%s", k, v, extractor.GetName())
+			}
+		}
+	}
+
+	return extractedValues, nil
+}
+
 func generateTemplate(template *Template) error {
 	err := fs.WalkDir(template.templateFiles, template.src, func(path string, d fs.DirEntry, err error) error {
 		if d.IsDir() {
diff --git a/pkg/handlers/template_utils.go b/pkg/handlers/template_utils.go
index 22ba85c..ff757f9 100644
--- a/pkg/handlers/template_utils.go
+++ b/pkg/handlers/template_utils.go
@@ -15,6 +15,19 @@ import (
 
 var templateConfigs map[string]*Template
 
+type TemplateType string
+
+func (t TemplateType) String() string {
+	return string(t)
+}
+
+const (
+	TemplateTypeDeployment TemplateType = "deployment"
+	TemplateTypeDockerfile TemplateType = "dockerfile"
+	TemplateTypeManifests  TemplateType = "manifest"
+	TemplateTypeWorkflow   TemplateType = "workflow"
+)
+
 func init() {
 	if err := loadTemplates(); err != nil {
 		log.Fatalf("failed to init templates: %s", err.Error())
@@ -26,6 +39,21 @@ func GetTemplates() map[string]*Template {
 	return templateConfigs
 }
 
+func GetTemplatesByType(templateType TemplateType) map[string]*Template {
+	templates := make(map[string]*Template)
+	for name, template := range templateConfigs {
+		if template.Config.Type == templateType.String() {
+			templates[name] = template
+		}
+	}
+	return templates
+}
+
+func IsValidTemplate(templateName string) bool {
+	_, ok := templateConfigs[strings.ToLower(templateName)]
+	return ok
+}
+
 func loadTemplates() error {
 	templateConfigs = make(map[string]*Template)
 	return fs.WalkDir(template.Templates, ".", func(path string, d fs.DirEntry, err error) error {
diff --git a/pkg/languages/defaults/gradle.go b/pkg/handlers/variableextractors/defaults/gradle.go
similarity index 100%
rename from pkg/languages/defaults/gradle.go
rename to pkg/handlers/variableextractors/defaults/gradle.go
diff --git a/pkg/languages/defaults/gradle_test.go b/pkg/handlers/variableextractors/defaults/gradle_test.go
similarity index 100%
rename from pkg/languages/defaults/gradle_test.go
rename to pkg/handlers/variableextractors/defaults/gradle_test.go
diff --git a/pkg/languages/defaults/python.go b/pkg/handlers/variableextractors/defaults/python.go
similarity index 100%
rename from pkg/languages/defaults/python.go
rename to pkg/handlers/variableextractors/defaults/python.go
diff --git a/pkg/languages/defaults/python_test.go b/pkg/handlers/variableextractors/defaults/python_test.go
similarity index 100%
rename from pkg/languages/defaults/python_test.go
rename to pkg/handlers/variableextractors/defaults/python_test.go
diff --git a/pkg/languages/defaults/testdata/sample.gradle b/pkg/handlers/variableextractors/defaults/testdata/sample.gradle
similarity index 100%
rename from pkg/languages/defaults/testdata/sample.gradle
rename to pkg/handlers/variableextractors/defaults/testdata/sample.gradle
diff --git a/pkg/languages/languages.go b/pkg/languages/languages.go
deleted file mode 100644
index f563012..0000000
--- a/pkg/languages/languages.go
+++ /dev/null
@@ -1,146 +0,0 @@
-package languages
-
-import (
-	"embed"
-	"fmt"
-	"io/fs"
-	"path"
-
-	"golang.org/x/exp/maps"
-	"gopkg.in/yaml.v3"
-
-	"github.com/Azure/draft/pkg/languages/defaults"
-	"github.com/Azure/draft/pkg/reporeader"
-	log "github.com/sirupsen/logrus"
-
-	"github.com/Azure/draft/pkg/config"
-	"github.com/Azure/draft/pkg/embedutils"
-	"github.com/Azure/draft/pkg/osutil"
-	"github.com/Azure/draft/pkg/templatewriter"
-)
-
-var (
-	parentDirName = "dockerfiles"
-)
-
-type Languages struct {
-	langs               map[string]fs.DirEntry
-	configs             map[string]*config.DraftConfig
-	dest                string
-	dockerfileTemplates fs.FS
-}
-
-// Names returns a slice of the names of the supported languages
-func (l *Languages) Names() []string {
-	names := maps.Keys(l.langs)
-	return names
-}
-
-func (l *Languages) ContainsLanguage(lang string) bool {
-	_, ok := l.langs[lang]
-	return ok
-}
-
-func (l *Languages) CreateDockerfileForLanguage(lang string, langConfig *config.DraftConfig, templateWriter templatewriter.TemplateWriter) error {
-	val, ok := l.langs[lang]
-	if !ok {
-		return fmt.Errorf("language %s is not supported", lang)
-	}
-
-	srcDir := path.Join(parentDirName, val.Name())
-
-	if err := langConfig.ApplyDefaultVariables(); err != nil {
-		return fmt.Errorf("create dockerfile for language: %w", err)
-	}
-
-	if err := osutil.CopyDirWithTemplates(l.dockerfileTemplates, srcDir, l.dest, langConfig, templateWriter); err != nil {
-		return err
-	}
-
-	return nil
-}
-
-func (l *Languages) loadConfig(lang string) (*config.DraftConfig, error) {
-	val, ok := l.langs[lang]
-	if !ok {
-		return nil, fmt.Errorf("language %s unsupported", lang)
-	}
-
-	configPath := path.Join(parentDirName, val.Name(), "/draft.yaml")
-	configBytes, err := fs.ReadFile(l.dockerfileTemplates, configPath)
-	if err != nil {
-		return nil, err
-	}
-
-	var draftConfig config.DraftConfig
-	if err = yaml.Unmarshal(configBytes, &draftConfig); err != nil {
-		return nil, err
-	}
-
-	return &draftConfig, nil
-}
-
-func (l *Languages) GetConfig(lang string) *config.DraftConfig {
-	val, ok := l.configs[lang]
-	if !ok {
-		return nil
-	}
-	return val
-}
-
-func (l *Languages) PopulateConfigs() {
-	for lang := range l.langs {
-		draftConfig, err := l.loadConfig(lang)
-		if err != nil {
-			log.Debugf("no draftConfig found for language %s", lang)
-			draftConfig = &config.DraftConfig{}
-		}
-		l.configs[lang] = draftConfig
-	}
-}
-
-func CreateLanguagesFromEmbedFS(dockerfileTemplates embed.FS, dest string) *Languages {
-	langMap, err := embedutils.EmbedFStoMap(dockerfileTemplates, parentDirName)
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	l := &Languages{
-		langs:               langMap,
-		dest:                dest,
-		configs:             make(map[string]*config.DraftConfig),
-		dockerfileTemplates: dockerfileTemplates,
-	}
-	l.PopulateConfigs()
-
-	return l
-}
-
-func (l *Languages) ExtractDefaults(lowerLang string, r reporeader.RepoReader) (map[string]string, error) {
-	extractors := []reporeader.VariableExtractor{
-		&defaults.PythonExtractor{},
-		&defaults.GradleExtractor{},
-	}
-	extractedValues := make(map[string]string)
-	if r == nil {
-		log.Debugf("no repo reader provided, returning empty list of defaults")
-		return extractedValues, nil
-	}
-	for _, extractor := range extractors {
-		if extractor.MatchesLanguage(lowerLang) {
-			newDefaults, err := extractor.ReadDefaults(r)
-			if err != nil {
-				return nil, fmt.Errorf("error reading defaults for language %s: %v", lowerLang, err)
-			}
-			for k, v := range newDefaults {
-				if _, ok := extractedValues[k]; ok {
-					log.Debugf("duplicate default %s for language %s with extractor %s", k, lowerLang, extractor.GetName())
-				}
-				extractedValues[k] = v
-				log.Debugf("extracted default %s=%s with extractor:%s", k, v, extractor.GetName())
-			}
-		}
-	}
-
-	return extractedValues, nil
-}
diff --git a/template/dockerfiles.go b/template/dockerfiles.go
deleted file mode 100644
index 9fefca7..0000000
--- a/template/dockerfiles.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package template
-
-import "embed"
-
-var (
-	//go:embed all:dockerfiles
-	Dockerfiles embed.FS
-)
diff --git a/template/dockerfiles/clojure/.dockerignore b/template/dockerfiles/clojure/.dockerignore
index 5b48e5e..310cd0c 100644
--- a/template/dockerfiles/clojure/.dockerignore
+++ b/template/dockerfiles/clojure/.dockerignore
@@ -1,4 +1,4 @@
-Dockerfile
+{{ .Config.GetVariableValue "DOCKERFILENAME" }}
 charts/
 resources/
 target/
diff --git a/template/dockerfiles/clojure/Dockerfile b/template/dockerfiles/clojure/Dockerfile
index 76957dd..386a133 100644
--- a/template/dockerfiles/clojure/Dockerfile
+++ b/template/dockerfiles/clojure/Dockerfile
@@ -3,11 +3,11 @@ COPY . /usr/src/app
 WORKDIR /usr/src/app
 RUN lein ring uberjar
 
-FROM eclipse-temurin:{{.VERSION}}
+FROM eclipse-temurin:{{ .Config.GetVariableValue "VERSION" }}
 
 RUN apk update && apk upgrade && apk add bash
-ENV PORT {{.PORT}}
-EXPOSE {{.PORT}}
+ENV PORT {{ .Config.GetVariableValue "PORT" }}
+EXPOSE {{ .Config.GetVariableValue "PORT"}}
 COPY --from=BUILD /usr/src/app/target/*.jar /opt/
 WORKDIR /opt
 CMD ["/bin/bash", "-c", "find -type f -name '*standalone.jar' | xargs java -jar"]
diff --git a/template/dockerfiles/clojure/draft.yaml b/template/dockerfiles/clojure/draft.yaml
index bbe7a1e..1ccbff7 100644
--- a/template/dockerfiles/clojure/draft.yaml
+++ b/template/dockerfiles/clojure/draft.yaml
@@ -2,6 +2,8 @@ language: clojure
 displayName: Clojure
 templateName: "dockerfile-clojure"
 description: "This template is used to create a Dockerfile for a Clojure application"
+versions: "0.0.1"
+defaultVersion: "0.0.1"
 type: "dockerfile"
 variables:
   - name: "PORT"
@@ -10,6 +12,7 @@ variables:
     default:
       value: "80"
     description: "the port exposed in the application"
+    versions: ">=0.0.1"
   - name: "VERSION"
     type: "string"
     kind: "containerImageVersion"
@@ -18,3 +21,12 @@ variables:
     description: "the version of openjdk that the application uses"
     exampleValues:
       ["8-jdk-alpine", "11-jdk-alpine", "17-jdk-alpine", "19-jdk-alpine"]
+    versions: ">=0.0.1"
+  - name: "DOCKERFILENAME"
+    type: "string"
+    kind: "dockerFileName"
+    default:
+      value: "Dockerfile"
+      disablePrompt: true
+    description: "the name of the Dockerfile"
+    versions: ">=0.0.1"
diff --git a/template/dockerfiles/csharp/.dockerignore b/template/dockerfiles/csharp/.dockerignore
index ac69008..7a0a9df 100644
--- a/template/dockerfiles/csharp/.dockerignore
+++ b/template/dockerfiles/csharp/.dockerignore
@@ -1,4 +1,4 @@
-Dockerfile
+{{ .Config.GetVariableValue "DOCKERFILENAME" }}
 charts/
 bin/
 obj/
diff --git a/template/dockerfiles/csharp/Dockerfile b/template/dockerfiles/csharp/Dockerfile
index 992ad42..e8e411c 100644
--- a/template/dockerfiles/csharp/Dockerfile
+++ b/template/dockerfiles/csharp/Dockerfile
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:{{.VERSION}} AS builder
+FROM mcr.microsoft.com/dotnet/sdk:{{ .Config.GetVariableValue "VERSION" }} AS builder
 WORKDIR /app
 
 # caches restore result by copying csproj file separately
@@ -11,11 +11,11 @@ RUN sed -n 's:.*<AssemblyName>\(.*\)</AssemblyName>.*:\1:p' *.csproj > __assembl
 RUN if [ ! -s __assemblyname ]; then filename=$(ls *.csproj); echo ${filename%.*} > __assemblyname; fi
 
 # Stage 2
-FROM mcr.microsoft.com/dotnet/aspnet:{{.VERSION}}
+FROM mcr.microsoft.com/dotnet/aspnet:{{ .Config.GetVariableValue "VERSION" }}
 WORKDIR /app
 COPY --from=builder /app .
 
-ENV PORT {{.PORT}}
-EXPOSE {{.PORT}}
+ENV PORT {{ .Config.GetVariableValue "PORT" }}
+EXPOSE {{ .Config.GetVariableValue "PORT" }}
 
-ENTRYPOINT dotnet $(cat /app/__assemblyname).dll --urls "http://*:{{.PORT}}"
+ENTRYPOINT dotnet $(cat /app/__assemblyname).dll --urls "http://*:{{ .Config.GetVariableValue "PORT" }}"
diff --git a/template/dockerfiles/csharp/draft.yaml b/template/dockerfiles/csharp/draft.yaml
index 4c15c0f..7fcbe52 100644
--- a/template/dockerfiles/csharp/draft.yaml
+++ b/template/dockerfiles/csharp/draft.yaml
@@ -2,6 +2,8 @@ language: csharp
 displayName: C#
 templateName: "dockerfile-csharp"
 description: "This template is used to create a Dockerfile for a C# application"
+versions: "0.0.1"
+defaultVersion: "0.0.1"
 type: "dockerfile"
 variables:
   - name: "PORT"
@@ -10,6 +12,7 @@ variables:
     default:
       value: "80"
     description: "the port exposed in the application"
+    versions: ">=0.0.1"
   - name: "VERSION"
     type: "float"
     kind: "containerImageVersion"
@@ -17,3 +20,12 @@ variables:
       value: "5.0"
     description: "the dotnet SDK version"
     exampleValues: ["3.1", "4.0", "5.0", "6.0"]
+    versions: ">=0.0.1"
+  - name: "DOCKERFILENAME"
+    type: "string"
+    kind: "dockerFileName"
+    default:
+      value: "Dockerfile"
+      disablePrompt: true
+    description: "the name of the Dockerfile"
+    versions: ">=0.0.1"
diff --git a/template/dockerfiles/erlang/.dockerignore b/template/dockerfiles/erlang/.dockerignore
index 1822f8c..b585166 100644
--- a/template/dockerfiles/erlang/.dockerignore
+++ b/template/dockerfiles/erlang/.dockerignore
@@ -1,2 +1,3 @@
 # files and directories to exclude from context
+{{ .Config.GetVariableValue "DOCKERFILENAME" }}
 _build
\ No newline at end of file
diff --git a/template/dockerfiles/erlang/Dockerfile b/template/dockerfiles/erlang/Dockerfile
index 2245dfe..5d176e9 100644
--- a/template/dockerfiles/erlang/Dockerfile
+++ b/template/dockerfiles/erlang/Dockerfile
@@ -1,4 +1,4 @@
-FROM erlang:{{.BUILDERVERSION}} as builder
+FROM erlang:{{ .Config.GetVariableValue "BUILDERVERSION" }} as builder
 
 RUN apk add --update tar curl git bash make libc-dev gcc g++ && \
     rm -rf /var/cache/apk/*
@@ -20,18 +20,18 @@ RUN tar -zxvf /usr/src/app/_build/prod/rel/*/*.tar.gz -C /opt/rel
 
 RUN relname=$(ls _build/prod/rel) ; echo $relname > /opt/rel/__relname
 
-FROM alpine:{{.VERSION}}
+FROM alpine:{{ .Config.GetVariableValue "VERSION" }}
 
 RUN apk add --no-cache openssl-dev ncurses libstdc++ libgcc
 
 WORKDIR /opt/rel
 
 ENV RELX_REPLACE_OS_VARS true
-ENV HTTP_PORT {{.PORT}}
+ENV HTTP_PORT {{ .Config.GetVariableValue "PORT" }}
 
 COPY --from=builder /opt/rel /opt/rel
 
-EXPOSE {{.PORT}} {{.PORT}}
+EXPOSE {{ .Config.GetVariableValue "PORT" }} {{ .Config.GetVariableValue "PORT" }}
 
 RUN ln -s /opt/rel/bin/$(cat /opt/rel/__relname) /opt/rel/bin/start_script
 ENTRYPOINT ["/opt/rel/bin/start_script"]
diff --git a/template/dockerfiles/erlang/draft.yaml b/template/dockerfiles/erlang/draft.yaml
index 9d7caf6..e456c52 100644
--- a/template/dockerfiles/erlang/draft.yaml
+++ b/template/dockerfiles/erlang/draft.yaml
@@ -2,6 +2,8 @@ language: erlang
 displayName: Erlang
 templateName: "dockerfile-erlang"
 description: "This template is used to create a Dockerfile for an Erlang application"
+versions: "0.0.1"
+defaultVersion: "0.0.1"
 type: "dockerfile"
 variables:
   - name: "PORT"
@@ -10,6 +12,7 @@ variables:
     default:
       value: "80"
     description: "the port exposed in the application"
+    versions: ">=0.0.1"
   - name: "BUILDERVERSION"
     type: "string"
     kind: "containerImageVersion"
@@ -17,6 +20,7 @@ variables:
       value: "27.0-alpine"
     description: "the version of erlang used during the builder stage to generate the executable"
     exampleValues: ["27.0-alpine"]
+    versions: ">=0.0.1"
   - name: "VERSION"
     type: "string"
     kind: "containerImageVersion"
@@ -24,3 +28,12 @@ variables:
       value: "3.17"
     description: "the version of alpine used by the application"
     exampleValues: ["3.17"]
+    versions: ">=0.0.1"
+  - name: "DOCKERFILENAME"
+    type: "string"
+    kind: "dockerFileName"
+    default:
+      value: "Dockerfile"
+      disablePrompt: true
+    description: "the name of the Dockerfile"
+    versions: ">=0.0.1"
\ No newline at end of file
diff --git a/template/dockerfiles/go/.dockerignore b/template/dockerfiles/go/.dockerignore
index 843dec4..868566d 100644
--- a/template/dockerfiles/go/.dockerignore
+++ b/template/dockerfiles/go/.dockerignore
@@ -1,2 +1,2 @@
-Dockerfile
+{{ .Config.GetVariableValue "DOCKERFILENAME" }}
 charts/
diff --git a/template/dockerfiles/go/Dockerfile b/template/dockerfiles/go/Dockerfile
index 368c908..564b27e 100644
--- a/template/dockerfiles/go/Dockerfile
+++ b/template/dockerfiles/go/Dockerfile
@@ -1,6 +1,6 @@
-FROM golang:{{.VERSION}}
-ENV PORT={{.PORT}}
-EXPOSE {{.PORT}}
+FROM golang:{{ .Config.GetVariableValue "VERSION" }}
+ENV PORT={{ .Config.GetVariableValue "PORT" }}
+EXPOSE {{ .Config.GetVariableValue "PORT" }}
 
 WORKDIR /go/src/app
 COPY . .
diff --git a/template/dockerfiles/go/draft.yaml b/template/dockerfiles/go/draft.yaml
index f7ef7c5..999f8c5 100644
--- a/template/dockerfiles/go/draft.yaml
+++ b/template/dockerfiles/go/draft.yaml
@@ -2,6 +2,8 @@ language: go
 displayName: Go
 templateName: "dockerfile-go"
 description: "This template is used to create a Dockerfile for a Go application"
+versions: "0.0.1"
+defaultVersion: "0.0.1"
 type: "dockerfile"
 variables:
   - name: "PORT"
@@ -10,6 +12,7 @@ variables:
     default:
       value: "80"
     description: "the port exposed in the application"
+    versions: ">=0.0.1"
   - name: "VERSION"
     type: "string"
     kind: "containerImageVersion"
@@ -17,3 +20,12 @@ variables:
       value: "1.23"
     description: "the version of go used by the application"
     exampleValues: ["1.20", "1.21", "1.22", "1.23"]
+    versions: ">=0.0.1"
+  - name: "DOCKERFILENAME"
+    type: "string"
+    kind: "dockerFileName"
+    default:
+      value: "Dockerfile"
+      disablePrompt: true
+    description: "the name of the Dockerfile"
+    versions: ">=0.0.1"
\ No newline at end of file
diff --git a/template/dockerfiles/gomodule/.dockerignore b/template/dockerfiles/gomodule/.dockerignore
index 843dec4..868566d 100644
--- a/template/dockerfiles/gomodule/.dockerignore
+++ b/template/dockerfiles/gomodule/.dockerignore
@@ -1,2 +1,2 @@
-Dockerfile
+{{ .Config.GetVariableValue "DOCKERFILENAME" }}
 charts/
diff --git a/template/dockerfiles/gomodule/Dockerfile b/template/dockerfiles/gomodule/Dockerfile
index 15ba241..2e11be4 100644
--- a/template/dockerfiles/gomodule/Dockerfile
+++ b/template/dockerfiles/gomodule/Dockerfile
@@ -1,4 +1,4 @@
-FROM golang:{{.VERSION}} AS builder
+FROM golang:{{ .Config.GetVariableValue "VERSION" }} AS builder
 
 WORKDIR /build
 COPY go.mod go.sum ./
@@ -8,8 +8,8 @@ RUN CGO_ENABLED=0 GOOS=linux go build -v -o app-binary
 
 FROM gcr.io/distroless/static-debian12
 
-ENV PORT={{.PORT}}
-EXPOSE {{.PORT}}
+ENV PORT={{ .Config.GetVariableValue "PORT" }}
+EXPOSE {{ .Config.GetVariableValue "PORT" }}
 
 WORKDIR /app
 COPY --from=builder /build/app-binary . 
diff --git a/template/dockerfiles/gomodule/draft.yaml b/template/dockerfiles/gomodule/draft.yaml
index 55991a1..c4d6d31 100644
--- a/template/dockerfiles/gomodule/draft.yaml
+++ b/template/dockerfiles/gomodule/draft.yaml
@@ -2,6 +2,8 @@ language: gomodule
 displayName: Go Module
 templateName: "dockerfile-gomodule"
 description: "This template is used to create a Dockerfile for a Go Module application"
+versions: "0.0.1"
+defaultVersion: "0.0.1"
 type: "dockerfile"
 variables:
   - name: "PORT"
@@ -10,6 +12,7 @@ variables:
     default:
       value: "80"
     description: "the port exposed in the application"
+    versions: ">=0.0.1"
   - name: "VERSION"
     type: "string"
     kind: "containerImageVersion"
@@ -17,3 +20,12 @@ variables:
       value: "1.23"
     description: "the version of go used by the application"
     exampleValues: ["1.20", "1.21", "1.22", "1.23"]
+    versions: ">=0.0.1"
+  - name: "DOCKERFILENAME"
+    type: "string"
+    kind: "dockerFileName"
+    default:
+      value: "Dockerfile"
+      disablePrompt: true
+    description: "the name of the Dockerfile"
+    versions: ">=0.0.1"
\ No newline at end of file
diff --git a/template/dockerfiles/gradle/.dockerignore b/template/dockerfiles/gradle/.dockerignore
index 843dec4..868566d 100644
--- a/template/dockerfiles/gradle/.dockerignore
+++ b/template/dockerfiles/gradle/.dockerignore
@@ -1,2 +1,2 @@
-Dockerfile
+{{ .Config.GetVariableValue "DOCKERFILENAME" }}
 charts/
diff --git a/template/dockerfiles/gradle/Dockerfile b/template/dockerfiles/gradle/Dockerfile
index 79d9acc..b7bc961 100644
--- a/template/dockerfiles/gradle/Dockerfile
+++ b/template/dockerfiles/gradle/Dockerfile
@@ -1,11 +1,11 @@
-FROM gradle:{{.BUILDERVERSION}} as BUILD
+FROM gradle:{{ .Config.GetVariableValue "BUILDERVERSION" }} as BUILD
 
 COPY --chown=gradle:gradle . /project
 RUN gradle -i -s -b /project/build.gradle clean build
 
-FROM eclipse-temurin:{{.VERSION}}
-ENV PORT {{.PORT}}
-EXPOSE {{.PORT}}
+FROM eclipse-temurin:{{ .Config.GetVariableValue "VERSION" }}
+ENV PORT {{ .Config.GetVariableValue "PORT" }}
+EXPOSE {{ .Config.GetVariableValue "PORT" }}
 
 COPY --from=BUILD /project/build/libs/* /opt/
 WORKDIR /opt/
diff --git a/template/dockerfiles/gradle/draft.yaml b/template/dockerfiles/gradle/draft.yaml
index 182c511..cff58e9 100644
--- a/template/dockerfiles/gradle/draft.yaml
+++ b/template/dockerfiles/gradle/draft.yaml
@@ -2,6 +2,8 @@ language: gradle
 displayName: Gradle
 templateName: "dockerfile-gradle"
 description: "This template is used to create a Dockerfile for a Gradle application"
+versions: "0.0.1"
+defaultVersion: "0.0.1"
 type: "dockerfile"
 variables:
   - name: "PORT"
@@ -10,6 +12,7 @@ variables:
     default:
       value: "80"
     description: "the port exposed in the application"
+    versions: ">=0.0.1"
   - name: "BUILDERVERSION"
     type: "string"
     kind: "containerImageVersion"
@@ -17,6 +20,7 @@ variables:
       value: "jdk21"
     description: "the version of gradle used during the builder stage to generate the executable"
     exampleValues: ["jdk8", "jdk11", "jdk17", "jdk19", "jdk21"]
+    versions: ">=0.0.1"
   - name: "VERSION"
     type: "string"
     kind: "containerImageVersion"
@@ -24,3 +28,12 @@ variables:
       value: "21-jre"
     description: "the java version used by the application"
     exampleValues: ["11-jre", "17-jre", "19-jre", "21-jre"]
+    versions: ">=0.0.1"
+  - name: "DOCKERFILENAME"
+    type: "string"
+    kind: "dockerFileName"
+    default:
+      value: "Dockerfile"
+      disablePrompt: true
+    description: "the name of the Dockerfile"
+    versions: ">=0.0.1"
\ No newline at end of file
diff --git a/template/dockerfiles/gradlew/.dockerignore b/template/dockerfiles/gradlew/.dockerignore
index 843dec4..868566d 100644
--- a/template/dockerfiles/gradlew/.dockerignore
+++ b/template/dockerfiles/gradlew/.dockerignore
@@ -1,2 +1,2 @@
-Dockerfile
+{{ .Config.GetVariableValue "DOCKERFILENAME" }}
 charts/
diff --git a/template/dockerfiles/gradlew/Dockerfile b/template/dockerfiles/gradlew/Dockerfile
index 0a09d12..f9ca902 100644
--- a/template/dockerfiles/gradlew/Dockerfile
+++ b/template/dockerfiles/gradlew/Dockerfile
@@ -1,4 +1,4 @@
-FROM gradle:{{.BUILDERVERSION}} as BUILD
+FROM gradle:{{ .Config.GetVariableValue "BUILDERVERSION" }} as BUILD
 
 COPY --chown=gradle:gradle . /project
 COPY gradlew gradlew
@@ -7,9 +7,9 @@ RUN chmod +x gradle/wrapper
 RUN chmod +x gradlew
 RUN ./gradlew -i -s -b /project/build.gradle clean build
 
-FROM eclipse-temurin:{{.VERSION}}
-ENV PORT {{.PORT}}
-EXPOSE {{.PORT}}
+FROM eclipse-temurin:{{ .Config.GetVariableValue "VERSION" }}
+ENV PORT {{ .Config.GetVariableValue "PORT" }}
+EXPOSE {{ .Config.GetVariableValue "PORT" }}
 
 COPY --from=BUILD /project/build/libs/* /opt/
 WORKDIR /opt/
diff --git a/template/dockerfiles/gradlew/draft.yaml b/template/dockerfiles/gradlew/draft.yaml
index 22e0788..0b9ca9c 100644
--- a/template/dockerfiles/gradlew/draft.yaml
+++ b/template/dockerfiles/gradlew/draft.yaml
@@ -2,6 +2,8 @@ language: gradle
 displayName: Gradle
 templateName: "dockerfile-gradlew"
 description: "This template is used to create a Dockerfile for a Gradle application"
+versions: "0.0.1"
+defaultVersion: "0.0.1"
 type: "dockerfile"
 variables:
   - name: "PORT"
@@ -10,6 +12,7 @@ variables:
     default:
       value: "80"
     description: "the port exposed in the application"
+    versions: ">=0.0.1"
   - name: "BUILDERVERSION"
     type: "string"
     kind: "containerImageVersion"
@@ -17,6 +20,7 @@ variables:
       value: "jdk21"
     description: "the version of gradle used during the builder stage to generate the executable"
     exampleValues: ["jdk8", "jdk11", "jdk17", "jdk19", "jdk21"]
+    versions: ">=0.0.1"
   - name: "VERSION"
     type: "string"
     kind: "containerImageVersion"
@@ -24,3 +28,12 @@ variables:
       value: "21-jre"
     description: "the java version used by the application"
     exampleValues: ["11-jre", "17-jre", "19-jre", "21-jre"]
+    versions: ">=0.0.1"
+  - name: "DOCKERFILENAME"
+    type: "string"
+    kind: "dockerFileName"
+    default:
+      value: "Dockerfile"
+      disablePrompt: true
+    description: "the name of the Dockerfile"
+    versions: ">=0.0.1"
\ No newline at end of file
diff --git a/template/dockerfiles/java/.dockerignore b/template/dockerfiles/java/.dockerignore
index c81336f..2f7bbf2 100644
--- a/template/dockerfiles/java/.dockerignore
+++ b/template/dockerfiles/java/.dockerignore
@@ -1,4 +1,4 @@
-Dockerfile
+{{ .Config.GetVariableValue "DOCKERFILENAME" }}
 charts/
 target/
 work/
diff --git a/template/dockerfiles/java/Dockerfile b/template/dockerfiles/java/Dockerfile
index 5ab34fd..baa33d5 100644
--- a/template/dockerfiles/java/Dockerfile
+++ b/template/dockerfiles/java/Dockerfile
@@ -1,11 +1,11 @@
-FROM maven:{{.BUILDERVERSION}} as BUILD
+FROM maven:{{ .Config.GetVariableValue "BUILDERVERSION" }} as BUILD
 
 COPY . /usr/src/app
 RUN mvn --batch-mode -f /usr/src/app/pom.xml clean package
 
-FROM eclipse-temurin:{{.VERSION}}
-ENV PORT {{.PORT}}
-EXPOSE {{.PORT}}
+FROM eclipse-temurin:{{ .Config.GetVariableValue "VERSION" }}
+ENV PORT {{ .Config.GetVariableValue "PORT" }}
+EXPOSE {{ .Config.GetVariableValue "PORT" }}
 COPY --from=BUILD /usr/src/app/target /opt/target
 WORKDIR /opt/target
 
diff --git a/template/dockerfiles/java/draft.yaml b/template/dockerfiles/java/draft.yaml
index 7cbf81e..59a825e 100644
--- a/template/dockerfiles/java/draft.yaml
+++ b/template/dockerfiles/java/draft.yaml
@@ -2,6 +2,8 @@ language: java
 displayName: Java
 templateName: "dockerfile-java"
 description: "This template is used to create a Dockerfile for a Java application"
+versions: "0.0.1"
+defaultVersion: "0.0.1"
 type: "dockerfile"
 variables:
   - name: "PORT"
@@ -10,6 +12,7 @@ variables:
     default:
       value: "80"
     description: "the port exposed in the application"
+    versions: ">=0.0.1"
   - name: "BUILDERVERSION"
     type: "string"
     kind: "containerImageVersion"
@@ -18,6 +21,7 @@ variables:
     description: "the version of maven used during the builder stage to generate the executable"
     exampleValues:
       ["3-eclipse-temurin-17", "3-eclipse-temurin-21", "3 (jdk-21)"]
+    versions: ">=0.0.1"
   - name: "VERSION"
     type: "string"
     kind: "containerImageVersion"
@@ -25,3 +29,12 @@ variables:
       value: "21-jre"
     description: "the java version used by the application"
     exampleValues: ["11-jre", "17-jre", "19-jre", "21-jre"]
+    versions: ">=0.0.1"
+  - name: "DOCKERFILENAME"
+    type: "string"
+    kind: "dockerFileName"
+    default:
+      value: "Dockerfile"
+      disablePrompt: true
+    description: "the name of the Dockerfile"
+    versions: ">=0.0.1"
\ No newline at end of file
diff --git a/template/dockerfiles/javascript/.dockerignore b/template/dockerfiles/javascript/.dockerignore
index 843dec4..868566d 100644
--- a/template/dockerfiles/javascript/.dockerignore
+++ b/template/dockerfiles/javascript/.dockerignore
@@ -1,2 +1,2 @@
-Dockerfile
+{{ .Config.GetVariableValue "DOCKERFILENAME" }}
 charts/
diff --git a/template/dockerfiles/javascript/Dockerfile b/template/dockerfiles/javascript/Dockerfile
index 96c7c16..56abb05 100644
--- a/template/dockerfiles/javascript/Dockerfile
+++ b/template/dockerfiles/javascript/Dockerfile
@@ -1,6 +1,6 @@
-FROM node:{{.VERSION}}
-ENV PORT {{.PORT}}
-EXPOSE {{.PORT}}
+FROM node:{{ .Config.GetVariableValue "VERSION" }}
+ENV PORT {{ .Config.GetVariableValue "PORT" }}
+EXPOSE {{ .Config.GetVariableValue "PORT" }}
 
 RUN mkdir -p /usr/src/app
 WORKDIR /usr/src/app
diff --git a/template/dockerfiles/javascript/draft.yaml b/template/dockerfiles/javascript/draft.yaml
index 701bdbc..f3d8bbd 100644
--- a/template/dockerfiles/javascript/draft.yaml
+++ b/template/dockerfiles/javascript/draft.yaml
@@ -2,6 +2,8 @@ language: javascript
 displayName: JavaScript
 templateName: "dockerfile-javascript"
 description: "This template is used to create a Dockerfile for a JavaScript application"
+versions: "0.0.1"
+defaultVersion: "0.0.1"
 type: "dockerfile"
 variables:
   - name: "PORT"
@@ -10,6 +12,7 @@ variables:
     default:
       value: "80"
     description: "the port exposed in the application"
+    versions: ">=0.0.1"
   - name: "VERSION"
     type: "string"
     kind: "containerImageVersion"
@@ -17,3 +20,12 @@ variables:
       value: "14"
     description: "the version of node used in the application"
     exampleValues: ["10.16.3", "12.16.3", "14.15.4"]
+    versions: ">=0.0.1"
+  - name: "DOCKERFILENAME"
+    type: "string"
+    kind: "dockerFileName"
+    default:
+      value: "Dockerfile"
+      disablePrompt: true
+    description: "the name of the Dockerfile"
+    versions: ">=0.0.1"
\ No newline at end of file
diff --git a/template/dockerfiles/php/.dockerignore b/template/dockerfiles/php/.dockerignore
index 843dec4..868566d 100644
--- a/template/dockerfiles/php/.dockerignore
+++ b/template/dockerfiles/php/.dockerignore
@@ -1,2 +1,2 @@
-Dockerfile
+{{ .Config.GetVariableValue "DOCKERFILENAME" }}
 charts/
diff --git a/template/dockerfiles/php/Dockerfile b/template/dockerfiles/php/Dockerfile
index 00b7c9f..8e3c2af 100644
--- a/template/dockerfiles/php/Dockerfile
+++ b/template/dockerfiles/php/Dockerfile
@@ -1,10 +1,10 @@
-FROM composer:{{.BUILDERVERSION}} AS build-env
+FROM composer:{{ .Config.GetVariableValue "BUILDERVERSION" }} AS build-env
 COPY . /app
 RUN cd /app && composer install
 
-FROM php:{{.VERSION}}
-ENV PORT 80
-EXPOSE 80
+FROM php:{{ .Config.GetVariableValue "VERSION" }}
+ENV PORT {{ .Config.GetVariableValue "PORT" }}
+EXPOSE {{ .Config.GetVariableValue "PORT" }}
 COPY --from=build-env /app /var/www/html
 RUN usermod -u 1000 www-data; \
     a2enmod rewrite; \
diff --git a/template/dockerfiles/php/draft.yaml b/template/dockerfiles/php/draft.yaml
index 1ca077c..6f71621 100644
--- a/template/dockerfiles/php/draft.yaml
+++ b/template/dockerfiles/php/draft.yaml
@@ -2,6 +2,8 @@ language: php
 displayName: PHP
 templateName: "dockerfile-php"
 description: "This template is used to create a Dockerfile for a PHP application"
+versions: "0.0.1"
+defaultVersion: "0.0.1"
 type: "dockerfile"
 variables:
   - name: "PORT"
@@ -10,6 +12,7 @@ variables:
     default:
       value: "80"
     description: "the port exposed in the application"
+    versions: ">=0.0.1"
   - name: "BUILDERVERSION"
     type: "string"
     kind: "containerImageVersion"
@@ -17,6 +20,7 @@ variables:
       value: "1"
     description: "the version of composer installed during the build stage to be used by the application"
     exampleValues: ["1"]
+    versions: ">=0.0.1"
   - name: "VERSION"
     type: "string"
     kind: "containerImageVersion"
@@ -24,3 +28,12 @@ variables:
       value: "7.1-apache"
     description: "the version of php used by the application"
     exampleValues: ["7.1-apache"]
+    versions: ">=0.0.1"
+  - name: "DOCKERFILENAME"
+    type: "string"
+    kind: "dockerFileName"
+    default:
+      value: "Dockerfile"
+      disablePrompt: true
+    description: "the name of the Dockerfile"
+    versions: ">=0.0.1"
\ No newline at end of file
diff --git a/template/dockerfiles/python/.dockerignore b/template/dockerfiles/python/.dockerignore
index 843dec4..868566d 100644
--- a/template/dockerfiles/python/.dockerignore
+++ b/template/dockerfiles/python/.dockerignore
@@ -1,2 +1,2 @@
-Dockerfile
+{{ .Config.GetVariableValue "DOCKERFILENAME" }}
 charts/
diff --git a/template/dockerfiles/python/Dockerfile b/template/dockerfiles/python/Dockerfile
index 87e0aa6..f21016e 100644
--- a/template/dockerfiles/python/Dockerfile
+++ b/template/dockerfiles/python/Dockerfile
@@ -1,6 +1,6 @@
-FROM python:{{.VERSION}}
-ENV PORT {{.PORT}}
-EXPOSE {{.PORT}}
+FROM python:{{ .Config.GetVariableValue "VERSION" }}
+ENV PORT {{ .Config.GetVariableValue "PORT" }}
+EXPOSE {{ .Config.GetVariableValue "PORT" }}
 WORKDIR /usr/src/app
 
 COPY requirements.txt ./
@@ -9,4 +9,4 @@ RUN pip install --no-cache-dir -r requirements.txt
 COPY . .
 
 ENTRYPOINT ["python"]
-CMD ["{{.ENTRYPOINT}}"]
\ No newline at end of file
+CMD ["{{ .Config.GetVariableValue "ENTRYPOINT" }}"]
\ No newline at end of file
diff --git a/template/dockerfiles/python/draft.yaml b/template/dockerfiles/python/draft.yaml
index 7250eb0..809c832 100644
--- a/template/dockerfiles/python/draft.yaml
+++ b/template/dockerfiles/python/draft.yaml
@@ -2,6 +2,8 @@ language: python
 displayName: Python
 templateName: "dockerfile-python"
 description: "This template is used to create a Dockerfile for a Python application"
+versions: "0.0.1"
+defaultVersion: "0.0.1"
 type: "dockerfile"
 variables:
   - name: "PORT"
@@ -10,6 +12,7 @@ variables:
     default:
       value: "80"
     description: "the port exposed in the application"
+    versions: ">=0.0.1"
   - name: "VERSION"
     type: "string"
     kind: "containerImageVersion"
@@ -17,6 +20,7 @@ variables:
       value: "3"
     description: "the version of python used by the application"
     exampleValues: ["3.9", "3.8", "3.7", "3.6"]
+    versions: ">=0.0.1"
   - name: "ENTRYPOINT"
     type: "string"
     kind: "filePath"
@@ -24,3 +28,12 @@ variables:
       value: "app.py"
     description: "the entrypoint file of the repository"
     exampleValues: ["app.py", "main.py"]
+    versions: ">=0.0.1"
+  - name: "DOCKERFILENAME"
+    type: "string"
+    kind: "dockerFileName"
+    default:
+      value: "Dockerfile"
+      disablePrompt: true
+    description: "the name of the Dockerfile"
+    versions: ">=0.0.1"
\ No newline at end of file
diff --git a/template/dockerfiles/ruby/.dockerignore b/template/dockerfiles/ruby/.dockerignore
index 3e5a44e..e5badce 100644
--- a/template/dockerfiles/ruby/.dockerignore
+++ b/template/dockerfiles/ruby/.dockerignore
@@ -1,3 +1,3 @@
-Dockerfile
+{{ .Config.GetVariableValue "DOCKERFILENAME" }}
 charts/
 tmp/
diff --git a/template/dockerfiles/ruby/Dockerfile b/template/dockerfiles/ruby/Dockerfile
index 5ffdc26..52487c7 100644
--- a/template/dockerfiles/ruby/Dockerfile
+++ b/template/dockerfiles/ruby/Dockerfile
@@ -1,6 +1,6 @@
-FROM ruby:{{.VERSION}}
-ENV PORT {{.PORT}}
-EXPOSE {{.PORT}}
+FROM ruby:{{ .Config.GetVariableValue "VERSION" }}
+ENV PORT {{ .Config.GetVariableValue "PORT" }}
+EXPOSE {{ .Config.GetVariableValue "PORT" }}
 RUN bundle config --global frozen 1
 
 WORKDIR /usr/src/app
diff --git a/template/dockerfiles/ruby/draft.yaml b/template/dockerfiles/ruby/draft.yaml
index 99d64b9..1a64243 100644
--- a/template/dockerfiles/ruby/draft.yaml
+++ b/template/dockerfiles/ruby/draft.yaml
@@ -2,6 +2,8 @@ language: ruby
 displayName: Ruby
 templateName: "dockerfile-ruby"
 description: "This template is used to create a Dockerfile for a Ruby application"
+versions: "0.0.1"
+defaultVersion: "0.0.1"
 type: "dockerfile"
 variables:
   - name: "PORT"
@@ -10,6 +12,7 @@ variables:
     default:
       value: "80"
     description: "the port exposed in the application"
+    versions: ">=0.0.1"
   - name: "VERSION"
     type: "string"
     kind: "containerImageVersion"
@@ -17,3 +20,12 @@ variables:
       value: "3.1.2"
     description: "the version of ruby used by the application"
     exampleValues: ["3.1.2", "2.6", "2.5", "2.4"]
+    versions: ">=0.0.1"
+  - name: "DOCKERFILENAME"
+    type: "string"
+    kind: "dockerFileName"
+    default:
+      value: "Dockerfile"
+      disablePrompt: true
+    description: "the name of the Dockerfile"
+    versions: ">=0.0.1"
\ No newline at end of file
diff --git a/template/dockerfiles/rust/.dockerignore b/template/dockerfiles/rust/.dockerignore
index 160b0d8..bcace91 100644
--- a/template/dockerfiles/rust/.dockerignore
+++ b/template/dockerfiles/rust/.dockerignore
@@ -1,3 +1,3 @@
-Dockerfile
+{{ .Config.GetVariableValue "DOCKERFILENAME" }}
 charts/
 target
diff --git a/template/dockerfiles/rust/Dockerfile b/template/dockerfiles/rust/Dockerfile
index 86827ea..d02d96c 100644
--- a/template/dockerfiles/rust/Dockerfile
+++ b/template/dockerfiles/rust/Dockerfile
@@ -1,10 +1,10 @@
-FROM rust:{{.VERSION}}
+FROM rust:{{ .Config.GetVariableValue "VERSION" }}
 
 WORKDIR /usr/src/app
 COPY . /usr/src/app
 RUN cargo build
 
-ENV PORT {{.PORT}}
-EXPOSE {{.PORT}}
+ENV PORT {{ .Config.GetVariableValue "PORT" }}
+EXPOSE {{ .Config.GetVariableValue "PORT" }}
 
 CMD ["cargo", "run", "-q"]
diff --git a/template/dockerfiles/rust/draft.yaml b/template/dockerfiles/rust/draft.yaml
index 284cba7..22a7d21 100644
--- a/template/dockerfiles/rust/draft.yaml
+++ b/template/dockerfiles/rust/draft.yaml
@@ -2,6 +2,8 @@ language: rust
 displayName: Rust
 templateName: "dockerfile-rust"
 description: "This template is used to create a Dockerfile for a Rust application"
+versions: "0.0.1"
+defaultVersion: "0.0.1"
 type: "dockerfile"
 variables:
   - name: "PORT"
@@ -10,6 +12,7 @@ variables:
     default:
       value: "80"
     description: "the port exposed in the application"
+    versions: ">=0.0.1"
   - name: "VERSION"
     type: "string"
     kind: "containerImageVersion"
@@ -17,3 +20,12 @@ variables:
       value: "1.70.0"
     description: "the version of rust used by the application"
     exampleValues: ["1.70.0", "1.65.0", "1.60", "1.54", "1.53"]
+    versions: ">=0.0.1"
+  - name: "DOCKERFILENAME"
+    type: "string"
+    kind: "dockerFileName"
+    default:
+      value: "Dockerfile"
+      disablePrompt: true
+    description: "the name of the Dockerfile"
+    versions: ">=0.0.1"
\ No newline at end of file
diff --git a/template/dockerfiles/swift/.dockerignore b/template/dockerfiles/swift/.dockerignore
index 843dec4..868566d 100644
--- a/template/dockerfiles/swift/.dockerignore
+++ b/template/dockerfiles/swift/.dockerignore
@@ -1,2 +1,2 @@
-Dockerfile
+{{ .Config.GetVariableValue "DOCKERFILENAME" }}
 charts/
diff --git a/template/dockerfiles/swift/Dockerfile b/template/dockerfiles/swift/Dockerfile
index 68594e7..d83bf7b 100644
--- a/template/dockerfiles/swift/Dockerfile
+++ b/template/dockerfiles/swift/Dockerfile
@@ -1,11 +1,11 @@
-FROM swift:{{.VERSION}}
+FROM swift:{{ .Config.GetVariableValue "VERSION" }}
 
 WORKDIR /src
 COPY . /src
 RUN apt-get update && apt-get install -y sudo openssl libssl-dev libcurl4-openssl-dev
 RUN swift build -c release
 
-ENV PORT {{.PORT}}
-EXPOSE {{.PORT}}
+ENV PORT {{ .Config.GetVariableValue "PORT" }}
+EXPOSE {{ .Config.GetVariableValue "PORT" }}
 
 CMD ["swift", "run"]
diff --git a/template/dockerfiles/swift/draft.yaml b/template/dockerfiles/swift/draft.yaml
index 186d8ff..caf72f3 100644
--- a/template/dockerfiles/swift/draft.yaml
+++ b/template/dockerfiles/swift/draft.yaml
@@ -2,6 +2,8 @@ language: swift
 displayName: Swift
 templateName: "dockerfile-swift"
 description: "This template is used to create a Dockerfile for a Swift application"
+versions: "0.0.1"
+defaultVersion: "0.0.1"
 type: "dockerfile"
 variables:
   - name: "PORT"
@@ -10,6 +12,7 @@ variables:
     default:
       value: "80"
     description: "the port exposed in the application"
+    versions: ">=0.0.1"
   - name: "VERSION"
     type: "string"
     kind: "containerImageVersion"
@@ -17,3 +20,12 @@ variables:
       value: "5.5"
     description: "the version of swift used by the application"
     exampleValues: ["5.2", "5.5"]
+    versions: ">=0.0.1"
+  - name: "DOCKERFILENAME"
+    type: "string"
+    kind: "dockerFileName"
+    default:
+      value: "Dockerfile"
+      disablePrompt: true
+    description: "the name of the Dockerfile"
+    versions: ">=0.0.1"
\ No newline at end of file


Test patch:
diff --git a/cmd/create_test.go b/cmd/create_test.go
index a4550cc..10714ed 100644
--- a/cmd/create_test.go
+++ b/cmd/create_test.go
@@ -13,16 +13,15 @@ import (
 	"github.com/stretchr/testify/assert"
 
 	"github.com/Azure/draft/pkg/config"
-	"github.com/Azure/draft/pkg/languages"
+	"github.com/Azure/draft/pkg/handlers"
 	"github.com/Azure/draft/pkg/linguist"
 	"github.com/Azure/draft/pkg/reporeader"
 	"github.com/Azure/draft/pkg/templatewriter/writers"
-	"github.com/Azure/draft/template"
 )
 
 func TestRun(t *testing.T) {
-	testCreateConfig := CreateConfig{LanguageVariables: []UserInputs{{Name: "PORT", Value: "8080"}}, DeployVariables: []UserInputs{{Name: "PORT", Value: "8080"}, {Name: "APPNAME", Value: "testingCreateCommand"}}}
-	flagVariablesMap = map[string]string{"PORT": "8080", "APPNAME": "testingCreateCommand", "VERSION": "1.18", "SERVICEPORT": "8080", "NAMESPACE": "testNamespace", "IMAGENAME": "testImage", "IMAGETAG": "latest"}
+	testCreateConfig := CreateConfig{LanguageVariables: []UserInputs{{Name: "PORT", Value: "8080"}}, DeployVariables: []UserInputs{{Name: "PORT", Value: "8080"}, {Name: "APPNAME", Value: "testingCreateCommand"}, {Name: "DOCKERFILENAME", Value: "Dockerfile"}}}
+	flagVariablesMap = map[string]string{"PORT": "8080", "APPNAME": "testingCreateCommand", "VERSION": "1.18", "SERVICEPORT": "8080", "NAMESPACE": "testNamespace", "IMAGENAME": "testImage", "IMAGETAG": "latest", "DOCKERFILENAME": "test.Dockerfile"}
 	mockCC := createCmd{
 		dest:           "./..",
 		createConfig:   &testCreateConfig,
@@ -199,7 +198,7 @@ func TestValidateConfigInputsToPromptsMissing(t *testing.T) {
 	assert.NotNil(t, err)
 }
 
-func (mcc *createCmd) mockDetectLanguage() (*config.DraftConfig, string, error) {
+func (mcc *createCmd) mockDetectLanguage() (*handlers.Template, string, error) {
 	hasGo := false
 	hasGoMod := false
 	var langs []*linguist.Language
@@ -227,12 +226,13 @@ func (mcc *createCmd) mockDetectLanguage() (*config.DraftConfig, string, error)
 		}
 	}
 
-	mcc.supportedLangs = languages.CreateLanguagesFromEmbedFS(template.Dockerfiles, mcc.dest)
-
 	if mcc.createConfig.LanguageType != "" {
 		log.Debug("using configuration language")
 		lowerLang := strings.ToLower(mcc.createConfig.LanguageType)
-		langConfig := mcc.supportedLangs.GetConfig(lowerLang)
+		langConfig, err := handlers.GetTemplate(fmt.Sprintf("dockerfile-%s", lowerLang), "", mcc.dest, mcc.templateWriter)
+		if err != nil {
+			return nil, "", err
+		}
 		if langConfig == nil {
 			return nil, "", ErrNoLanguageDetected
 		}
@@ -245,13 +245,19 @@ func (mcc *createCmd) mockDetectLanguage() (*config.DraftConfig, string, error)
 		log.Infof("--> Draft detected %s (%f%%)\n", detectedLang.Language, detectedLang.Percent)
 		lowerLang := strings.ToLower(detectedLang.Language)
 
-		if mcc.supportedLangs.ContainsLanguage(lowerLang) {
+		if handlers.IsValidTemplate(fmt.Sprintf("dockerfile-%s", lowerLang)) {
 			if lowerLang == "go" && hasGo && hasGoMod {
 				log.Debug("detected go and go module")
 				lowerLang = "gomodule"
 			}
 
-			langConfig := mcc.supportedLangs.GetConfig(lowerLang)
+			langConfig, err := handlers.GetTemplate(fmt.Sprintf("dockerfile-%s", lowerLang), "", mcc.dest, mcc.templateWriter)
+			if err != nil {
+				return nil, "", err
+			}
+			if langConfig == nil {
+				return nil, "", ErrNoLanguageDetected
+			}
 			return langConfig, lowerLang, nil
 		}
 		log.Infof("--> Could not find a pack for %s. Trying to find the next likely language match...\n", detectedLang.Language)
diff --git a/example/dockerfile_test.go b/example/dockerfile_test.go
index 8fd2b6c..668c2b0 100644
--- a/example/dockerfile_test.go
+++ b/example/dockerfile_test.go
@@ -1,121 +1,9 @@
 package example
 
 import (
-	"fmt"
 	"testing"
-
-	"github.com/Azure/draft/pkg/config"
-	"github.com/Azure/draft/pkg/templatewriter/writers"
 )
 
-func TestWriteDockerfile(t *testing.T) {
-	templateWriter := writers.FileMapWriter{}
-	outputPath := "test/path"
-
-	testCases := []struct {
-		name               string
-		langConfig         *config.DraftConfig
-		generationLanguage string
-		expectError        bool
-	}{
-
-		{
-			name: "Test Valid Go Dockerfile Generation",
-			langConfig: &config.DraftConfig{
-				Variables: []*config.BuilderVar{
-					{
-						Name: "PORT",
-						Default: config.BuilderVarDefault{
-							Value: "80",
-						},
-						Description: "the port exposed in the application",
-						Type:        "int",
-						Value:       "8080",
-					},
-					{
-						Name: "VERSION",
-						Default: config.BuilderVarDefault{
-							Value: "1.18",
-						},
-						Description:   "the version of go used by the application",
-						ExampleValues: []string{"1.16", "1.17", "1.18", "1.19"},
-						Value:         "1.20",
-					},
-				},
-			},
-			generationLanguage: "go",
-			expectError:        false,
-		},
-		{
-			name: "Test Valid Go Dockerfile Generation with default",
-			langConfig: &config.DraftConfig{
-				Variables: []*config.BuilderVar{
-					{
-						Name: "PORT",
-						Default: config.BuilderVarDefault{
-							Value: "80",
-						},
-						Description: "the port exposed in the application",
-						Type:        "int",
-						Value:       "8080",
-					},
-					{
-						Name: "VERSION",
-						Default: config.BuilderVarDefault{
-							Value: "1.18",
-						},
-						Description:   "the version of go used by the application",
-						ExampleValues: []string{"1.16", "1.17", "1.18", "1.19"},
-					},
-				},
-			},
-			generationLanguage: "go",
-			expectError:        false,
-		},
-		{
-			name: "Test Invalid GenerationLanguage",
-			langConfig: &config.DraftConfig{
-				Variables: []*config.BuilderVar{
-					{
-						Name: "PORT",
-						Default: config.BuilderVarDefault{
-							Value: "80",
-						},
-						Description: "the port exposed in the application",
-						Type:        "int",
-						Value:       "8080",
-					},
-					{
-						Name: "VERSION",
-						Default: config.BuilderVarDefault{
-							Value: "1.18",
-						},
-						Description:   "the version of go used by the application",
-						ExampleValues: []string{"1.16", "1.17", "1.18", "1.19"},
-						Value:         "1.20",
-					},
-				},
-			},
-			generationLanguage: "invalid",
-			expectError:        true,
-		},
-	}
-
-	for _, tc := range testCases {
-		t.Run(tc.name, func(t *testing.T) {
-			err := WriteDockerfile(&templateWriter, outputPath, tc.langConfig, tc.generationLanguage)
-			errored := err != nil
-			if err != nil {
-				fmt.Printf("WriteDockerfile failed: %e\n", err)
-			}
-			if errored != tc.expectError {
-				t.Errorf("WriteDockerfile failed: expected error %t, got %t", tc.expectError, errored)
-				t.Fail()
-			}
-		})
-	}
-}
-
 func TestWriteDockerfileExample(t *testing.T) {
 	err := WriteDockerfileExample()
 	if err != nil {
diff --git a/pkg/config/draftconfig_template_test.go b/pkg/config/draftconfig_template_test.go
index 5a48d03..5c3bfde 100644
--- a/pkg/config/draftconfig_template_test.go
+++ b/pkg/config/draftconfig_template_test.go
@@ -35,6 +35,7 @@ var validVariableKinds = map[string]bool{
 	"containerImageName":     true,
 	"containerImageVersion":  true,
 	"dirPath":                true,
+	"dockerFileName":         true,
 	"filePath":               true,
 	"flag":                   true,
 	"helmChartOverrides":     true,
diff --git a/pkg/handlers/template_test.go b/pkg/handlers/template_test.go
index 30b8ecf..41a6ea6 100644
--- a/pkg/handlers/template_test.go
+++ b/pkg/handlers/template_test.go
@@ -115,6 +115,180 @@ func TestTemplateHandlerValidation(t *testing.T) {
 			varMap:          map[string]string{},
 			expectedErr:     fmt.Errorf("create workflow files: variable APPNAME has no default value"),
 		},
+		{
+			name:            "valid clojure dockerfile",
+			templateName:    "dockerfile-clojure",
+			fixturesBaseDir: "../fixtures/dockerfiles/clojure",
+			version:         "0.0.1",
+			dest:            ".",
+			templateWriter:  &writers.FileMapWriter{},
+			varMap: map[string]string{
+				"PORT":    "80",
+				"VERSION": "19-jdk-alpine",
+			},
+		},
+		{
+			name:            "valid csharp dockerfile",
+			templateName:    "dockerfile-csharp",
+			fixturesBaseDir: "../fixtures/dockerfiles/csharp",
+			version:         "0.0.1",
+			dest:            ".",
+			templateWriter:  &writers.FileMapWriter{},
+			varMap: map[string]string{
+				"PORT":    "80",
+				"VERSION": "6.0",
+			},
+		},
+		{
+			name:            "valid erlang dockerfile",
+			templateName:    "dockerfile-erlang",
+			fixturesBaseDir: "../fixtures/dockerfiles/erlang",
+			version:         "0.0.1",
+			dest:            ".",
+			templateWriter:  &writers.FileMapWriter{},
+			varMap: map[string]string{
+				"PORT":         "80",
+				"BUILDVERSION": "27.0-alpine",
+				"VERSION":      "3.17",
+			},
+		},
+		{
+			name:            "valid go dockerfile",
+			templateName:    "dockerfile-go",
+			fixturesBaseDir: "../fixtures/dockerfiles/go",
+			version:         "0.0.1",
+			dest:            ".",
+			templateWriter:  &writers.FileMapWriter{},
+			varMap: map[string]string{
+				"PORT":    "80",
+				"VERSION": "1.23",
+			},
+		},
+		{
+			name:            "valid gomodule dockerfile",
+			templateName:    "dockerfile-gomodule",
+			fixturesBaseDir: "../fixtures/dockerfiles/gomodule",
+			version:         "0.0.1",
+			dest:            ".",
+			templateWriter:  &writers.FileMapWriter{},
+			varMap: map[string]string{
+				"PORT":    "80",
+				"VERSION": "1.23",
+			},
+		},
+		{
+			name:            "valid gradle dockerfile",
+			templateName:    "dockerfile-gradle",
+			fixturesBaseDir: "../fixtures/dockerfiles/gradle",
+			version:         "0.0.1",
+			dest:            ".",
+			templateWriter:  &writers.FileMapWriter{},
+			varMap: map[string]string{
+				"PORT":         "80",
+				"BUILDVERSION": "jdk21",
+				"VERSION":      "21-jre",
+			},
+		},
+		{
+			name:            "valid gradlew dockerfile",
+			templateName:    "dockerfile-gradlew",
+			fixturesBaseDir: "../fixtures/dockerfiles/gradlew",
+			version:         "0.0.1",
+			dest:            ".",
+			templateWriter:  &writers.FileMapWriter{},
+			varMap: map[string]string{
+				"PORT":         "80",
+				"BUILDVERSION": "jdk21",
+				"VERSION":      "21-jre",
+			},
+		},
+		{
+			name:            "valid java dockerfile",
+			templateName:    "dockerfile-java",
+			fixturesBaseDir: "../fixtures/dockerfiles/java",
+			version:         "0.0.1",
+			dest:            ".",
+			templateWriter:  &writers.FileMapWriter{},
+			varMap: map[string]string{
+				"PORT":         "80",
+				"BUILDVERSION": "3 (jdk-21)",
+				"VERSION":      "21-jre",
+			},
+		},
+		{
+			name:            "valid javascript dockerfile",
+			templateName:    "dockerfile-javascript",
+			fixturesBaseDir: "../fixtures/dockerfiles/javascript",
+			version:         "0.0.1",
+			dest:            ".",
+			templateWriter:  &writers.FileMapWriter{},
+			varMap: map[string]string{
+				"PORT":    "80",
+				"VERSION": "14.15.4",
+			},
+		},
+		{
+			name:            "valid php dockerfile",
+			templateName:    "dockerfile-php",
+			fixturesBaseDir: "../fixtures/dockerfiles/php",
+			version:         "0.0.1",
+			dest:            ".",
+			templateWriter:  &writers.FileMapWriter{},
+			varMap: map[string]string{
+				"PORT":         "80",
+				"BUILDVERSION": "1",
+				"VERSION":      "7.1-apache",
+			},
+		},
+		{
+			name:            "valid python dockerfile",
+			templateName:    "dockerfile-python",
+			fixturesBaseDir: "../fixtures/dockerfiles/python",
+			version:         "0.0.1",
+			dest:            ".",
+			templateWriter:  &writers.FileMapWriter{},
+			varMap: map[string]string{
+				"PORT":       "80",
+				"ENTRYPOINT": "app.py",
+				"VERSION":    "3.9",
+			},
+		},
+		{
+			name:            "valid ruby dockerfile",
+			templateName:    "dockerfile-ruby",
+			fixturesBaseDir: "../fixtures/dockerfiles/ruby",
+			version:         "0.0.1",
+			dest:            ".",
+			templateWriter:  &writers.FileMapWriter{},
+			varMap: map[string]string{
+				"PORT":    "80",
+				"VERSION": "3.1.2",
+			},
+		},
+		{
+			name:            "valid rust dockerfile",
+			templateName:    "dockerfile-rust",
+			fixturesBaseDir: "../fixtures/dockerfiles/rust",
+			version:         "0.0.1",
+			dest:            ".",
+			templateWriter:  &writers.FileMapWriter{},
+			varMap: map[string]string{
+				"PORT":    "80",
+				"VERSION": "1.70.0",
+			},
+		},
+		{
+			name:            "valid swift dockerfile",
+			templateName:    "dockerfile-swift",
+			fixturesBaseDir: "../fixtures/dockerfiles/swift",
+			version:         "0.0.1",
+			dest:            ".",
+			templateWriter:  &writers.FileMapWriter{},
+			varMap: map[string]string{
+				"PORT":    "80",
+				"VERSION": "5.5",
+			},
+		},
 	}
 
 	for _, tt := range tests {
diff --git a/pkg/languages/languages_test.go b/pkg/languages/languages_test.go
deleted file mode 100644
index d041691..0000000
--- a/pkg/languages/languages_test.go
+++ /dev/null
@@ -1,32 +0,0 @@
-package languages
-
-import (
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-
-	"github.com/Azure/draft/pkg/config"
-	"github.com/Azure/draft/pkg/templatewriter/writers"
-	"github.com/Azure/draft/template"
-)
-
-func TestLanguagesCreateDockerfileFileMap(t *testing.T) {
-	templateWriter := &writers.FileMapWriter{}
-	l := CreateLanguagesFromEmbedFS(template.Dockerfiles, "/test/dest/dir")
-	err := l.CreateDockerfileForLanguage("go", &config.DraftConfig{
-		Variables: []*config.BuilderVar{
-			{
-				Name:  "PORT",
-				Value: "8080",
-			},
-			{
-				Name:  "VERSION",
-				Value: "14",
-			},
-		},
-	}, templateWriter)
-
-	assert.Nil(t, err)
-	assert.NotNil(t, templateWriter.FileMap)
-	assert.NotNil(t, templateWriter.FileMap["/test/dest/dir/Dockerfile"])
-}
diff --git a/pkg/templatewriter/writers/filemapwriter_test.go b/pkg/templatewriter/writers/filemapwriter_test.go
index d184f6d..855960b 100644
--- a/pkg/templatewriter/writers/filemapwriter_test.go
+++ b/pkg/templatewriter/writers/filemapwriter_test.go
@@ -13,19 +13,23 @@ import (
 func TestCopyDirToFileMap(t *testing.T) {
 
 	templatewriter := &FileMapWriter{}
-	err := osutil.CopyDir(template.Dockerfiles, "dockerfiles/javascript", "/test/dir", &config.DraftConfig{
+	err := osutil.CopyDir(template.Addons, "addons/azure/webapp_routing", "/test/dir", &config.DraftConfig{
 		Variables: []*config.BuilderVar{
 			{
-				Name:  "PORT",
-				Value: "8080",
+				Name:  "ingress-tls-cert-keyvault-uri",
+				Value: "https://test.vault.azure.net/secrets/test-secret",
 			},
 			{
-				Name:  "VERSION",
-				Value: "14",
+				Name:  "ingress-use-osm-mtls",
+				Value: "true",
+			},
+			{
+				Name:  "ingress-host",
+				Value: "testhost.com",
 			},
 		},
 	}, templatewriter)
 	assert.Nil(t, err)
 	assert.NotNil(t, templatewriter.FileMap)
-	assert.NotNil(t, templatewriter.FileMap["/test/dir/Dockerfile"])
+	assert.NotNil(t, templatewriter.FileMap["/test/dir/ingress.yaml"])
 }