diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index 81c1e01901e9d52b5f4cf01e17c2572d51b58c27..f60f27d1210937aa5a3c405b839b80dfe9dfc2ef 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -11,6 +11,7 @@
     licensePath: "/api/:version/templates/licenses/:key",
     gitignorePath: "/api/:version/templates/gitignores/:key",
     gitlabCiYmlPath: "/api/:version/templates/gitlab_ci_ymls/:key",
+    dockerfilePath: "/api/:version/dockerfiles/:key",
     issuableTemplatePath: "/:namespace_path/:project_path/templates/:type/:key",
     group: function(group_id, callback) {
       var url = Api.buildUrl(Api.groupPath)
@@ -120,6 +121,10 @@
         return callback(file);
       });
     },
+    dockerfileYml: function(key, callback) {
+      var url = Api.buildUrl(Api.dockerfilePath).replace(':key', key);
+      $.get(url, callback);
+    },
     issueTemplate: function(namespacePath, projectPath, key, type, callback) {
       var url = Api.buildUrl(Api.issuableTemplatePath)
         .replace(':key', key)
diff --git a/app/assets/javascripts/blob/blob_dockerfile_selector.js.es6 b/app/assets/javascripts/blob/blob_dockerfile_selector.js.es6
new file mode 100644
index 0000000000000000000000000000000000000000..bdf9501761366aaf3c297a2b5f68059ca4abcf16
--- /dev/null
+++ b/app/assets/javascripts/blob/blob_dockerfile_selector.js.es6
@@ -0,0 +1,18 @@
+/* global Api */
+/*= require blob/template_selector */
+
+(() => {
+  const global = window.gl || (window.gl = {});
+
+  class BlobDockerfileSelector extends gl.TemplateSelector {
+    requestFile(query) {
+      return Api.dockerfileYml(query.name, this.requestFileSuccess.bind(this));
+    }
+
+    requestFileSuccess(file) {
+      return super.requestFileSuccess(file);
+    }
+  }
+
+  global.BlobDockerfileSelector = BlobDockerfileSelector;
+})();
diff --git a/app/assets/javascripts/blob/blob_dockerfile_selectors.js.es6 b/app/assets/javascripts/blob/blob_dockerfile_selectors.js.es6
new file mode 100644
index 0000000000000000000000000000000000000000..9cee79fa5d56756846ab5c01cbe46f33d1e887f7
--- /dev/null
+++ b/app/assets/javascripts/blob/blob_dockerfile_selectors.js.es6
@@ -0,0 +1,27 @@
+(() => {
+  const global = window.gl || (window.gl = {});
+
+  class BlobDockerfileSelectors {
+    constructor({ editor, $dropdowns } = {}) {
+      this.editor = editor;
+      this.$dropdowns = $dropdowns || $('.js-dockerfile-selector');
+      this.initSelectors();
+    }
+
+    initSelectors() {
+      const editor = this.editor;
+      this.$dropdowns.each((i, dropdown) => {
+        const $dropdown = $(dropdown);
+        return new gl.BlobDockerfileSelector({
+          editor,
+          pattern: /(Dockerfile)/,
+          data: $dropdown.data('data'),
+          wrapper: $dropdown.closest('.js-dockerfile-selector-wrap'),
+          dropdown: $dropdown,
+        });
+      });
+    }
+  }
+
+  global.BlobDockerfileSelectors = BlobDockerfileSelectors;
+})();
diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js
index b528e32340dc15fa14aa4783f364b759d28d5a44..fa43ff611ccbb566abf20d26b16015a7d5502ebf 100644
--- a/app/assets/javascripts/blob_edit/edit_blob.js
+++ b/app/assets/javascripts/blob_edit/edit_blob.js
@@ -36,6 +36,9 @@
       new gl.BlobCiYamlSelectors({
         editor: this.editor
       });
+      new gl.BlobDockerfileSelectors({
+        editor: this.editor
+      });
     }
 
     EditBlob.prototype.initModePanesAndLinks = function() {
diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss
index 3fdb4f510fa2e621a94c28c328dac6bb885a7a53..4af267403d8841c77af6b1a5bc55d778be399d18 100644
--- a/app/assets/stylesheets/pages/editor.scss
+++ b/app/assets/stylesheets/pages/editor.scss
@@ -75,7 +75,8 @@
   .soft-wrap-toggle,
   .license-selector,
   .gitignore-selector,
-  .gitlab-ci-yml-selector {
+  .gitlab-ci-yml-selector,
+  .dockerfile-selector {
     display: inline-block;
     vertical-align: top;
     font-family: $regular_font;
@@ -105,7 +106,8 @@
 
   .gitignore-selector,
   .license-selector,
-  .gitlab-ci-yml-selector {
+  .gitlab-ci-yml-selector,
+  .dockerfile-selector {
     .dropdown {
       line-height: 21px;
     }
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 07ff6fb94889c58503a881861c64f31d3a18f805..f31d4fb897d3a237879a06c34726d3b44e1c6514 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -191,6 +191,10 @@ module BlobHelper
     @gitlab_ci_ymls ||= Gitlab::Template::GitlabCiYmlTemplate.dropdown_names
   end
 
+  def dockerfile_names
+    @dockerfile_names ||= Gitlab::Template::DockerfileTemplate.dropdown_names
+  end
+
   def blob_editor_paths
     {
       'relative-url-root' => Rails.application.config.relative_url_root,
diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml
index 4a6aa92e3f3db04685091e0882c416a59e2a3ac2..1d058daa0943301b6766f53a45f3b90d4a5c994f 100644
--- a/app/views/projects/blob/_editor.html.haml
+++ b/app/views/projects/blob/_editor.html.haml
@@ -21,6 +21,8 @@
         = dropdown_tag("Choose a .gitignore template", options: { toggle_class: 'btn js-gitignore-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: gitignore_names } } )
       .gitlab-ci-yml-selector.js-gitlab-ci-yml-selector-wrap.hidden
         = dropdown_tag("Choose a GitLab CI Yaml template", options: { toggle_class: 'btn js-gitlab-ci-yml-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls } } )
+      .dockerfile-selector.js-dockerfile-selector-wrap.hidden
+        = dropdown_tag("Choose a Dockerfile template", options: { toggle_class: 'btn js-dockerfile-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: dockerfile_names } } )
       = button_tag class: 'soft-wrap-toggle btn', type: 'button' do
         %span.no-wrap
           = custom_icon('icon_no_wrap')
diff --git a/changelogs/unreleased/dockerfile-templates.yml b/changelogs/unreleased/dockerfile-templates.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e4db46cdf9ac8b991ec0780e4aa6620c0f53855b
--- /dev/null
+++ b/changelogs/unreleased/dockerfile-templates.yml
@@ -0,0 +1,4 @@
+---
+title: Add support for Dockerfile templates
+merge_request: 7247
+author:
diff --git a/lib/api/templates.rb b/lib/api/templates.rb
index 8a53d9c0095d5355224bb19e40ce174b734b49f4..e23f99256a59e2fea3a74a1ae4c61438bab9ccce 100644
--- a/lib/api/templates.rb
+++ b/lib/api/templates.rb
@@ -8,6 +8,10 @@ module API
       gitlab_ci_ymls: {
         klass: Gitlab::Template::GitlabCiYmlTemplate,
         gitlab_version: 8.9
+      },
+      dockerfiles: {
+        klass: Gitlab::Template::DockerfileTemplate,
+        gitlab_version: 8.15
       }
     }.freeze
     PROJECT_TEMPLATE_REGEX =
@@ -51,7 +55,7 @@ module API
       end
       params do
         optional :popular, type: Boolean, desc: 'If passed, returns only popular licenses'
-      end 
+      end
       get route do
         options = {
           featured: declared(params).popular.present? ? true : nil
@@ -69,7 +73,7 @@ module API
       end
       params do
         requires :name, type: String, desc: 'The name of the template'
-      end 
+      end
       get route, requirements: { name: /[\w\.-]+/ } do
         not_found!('License') unless Licensee::License.find(declared(params).name)
 
@@ -78,7 +82,7 @@ module API
         present template, with: Entities::RepoLicense
       end
     end
-      
+
     GLOBAL_TEMPLATE_TYPES.each do |template_type, properties|
       klass = properties[:klass]
       gitlab_version = properties[:gitlab_version]
@@ -104,7 +108,7 @@ module API
         end
         params do
           requires :name, type: String, desc: 'The name of the template'
-        end 
+        end
         get route do
           new_template = klass.find(declared(params).name)
 
diff --git a/lib/gitlab/template/dockerfile_template.rb b/lib/gitlab/template/dockerfile_template.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d5d3e045a42d8db432f7436cdbdd30c2a4a581c6
--- /dev/null
+++ b/lib/gitlab/template/dockerfile_template.rb
@@ -0,0 +1,30 @@
+module Gitlab
+  module Template
+    class DockerfileTemplate < BaseTemplate
+      def content
+        explanation = "# This file is a template, and might need editing before it works on your project."
+        [explanation, super].join("\n")
+      end
+
+      class << self
+        def extension
+          'Dockerfile'
+        end
+
+        def categories
+          {
+            "General" => ''
+          }
+        end
+
+        def base_dir
+          Rails.root.join('vendor/dockerfile')
+        end
+
+        def finder(project = nil)
+          Gitlab::Template::Finders::GlobalTemplateFinder.new(self.base_dir, self.extension, self.categories)
+        end
+      end
+    end
+  end
+end
diff --git a/spec/features/projects/files/dockerfile_dropdown_spec.rb b/spec/features/projects/files/dockerfile_dropdown_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..32f33a3ca97e2f0c8376ba90f68fd3a7803bda6c
--- /dev/null
+++ b/spec/features/projects/files/dockerfile_dropdown_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+feature 'User wants to add a Dockerfile file', feature: true do
+  include WaitForAjax
+
+  before do
+    user = create(:user)
+    project = create(:project)
+    project.team << [user, :master]
+    login_as user
+    visit namespace_project_new_blob_path(project.namespace, project, 'master', file_name: 'Dockerfile')
+  end
+
+  scenario 'user can see Dockerfile dropdown' do
+    expect(page).to have_css('.dockerfile-selector')
+  end
+
+  scenario 'user can pick a Dockerfile file from the dropdown', js: true do
+    find('.js-dockerfile-selector').click
+    wait_for_ajax
+    within '.dockerfile-selector' do
+      find('.dropdown-input-field').set('HTTPd')
+      find('.dropdown-content li', text: 'HTTPd').click
+    end
+    wait_for_ajax
+
+    expect(page).to have_css('.dockerfile-selector .dropdown-toggle-text', text: 'HTTPd')
+    expect(page).to have_content('COPY ./ /usr/local/apache2/htdocs/')
+  end
+end
diff --git a/vendor/dockerfile/HTTPdDockerfile b/vendor/dockerfile/HTTPdDockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..2f05427323c29c19355093ef1a8d2772b4a18971
--- /dev/null
+++ b/vendor/dockerfile/HTTPdDockerfile
@@ -0,0 +1,3 @@
+FROM httpd:alpine
+
+COPY ./ /usr/local/apache2/htdocs/