diff --git a/docker/macros.j2 b/docker/macros.j2
index c10973ef6443e44fdb07296f78b9101ac84b11a4..5cdb12b4ccc9f72ba372044ef5a7c4ccc28b8d63 100644
--- a/docker/macros.j2
+++ b/docker/macros.j2
@@ -1,7 +1,12 @@
 {% macro install_packages(packages) -%}
 {% if base_distro in ['centos', 'fedora', 'oraclelinux', 'rhel'] -%}
-    yum -y install {{ packages | join(' ') }}  && yum clean all
+    yum -y install {{ packages | join(' ') }} && yum clean all
 {%- elif base_distro in ['ubuntu', 'debian'] -%}
-    apt-get -y install --no-install-recommends {{ packages | join(' ') }} && apt-get clean
+    {#-
+      debian_package_install is a utility method to build up an appropriate
+      set of commands to install packages in a debian-based environment that
+      may include URL links to a .deb package (e.g, heka)
+    -#}
+    {{ debian_package_install(packages) }}
 {%- endif %}
 {%- endmacro %}
diff --git a/kolla/image/build.py b/kolla/image/build.py
index 090b28f4b5a07e47a0b568bd7ea1c44c0a96ea24..20d26e01b207b1803b7bb792f938e794caf813a8 100644
--- a/kolla/image/build.py
+++ b/kolla/image/build.py
@@ -51,6 +51,7 @@ if PROJECT_ROOT not in sys.path:
 from kolla.common import config as common_config
 from kolla.common import task
 from kolla.template import filters as jinja_filters
+from kolla.template import methods as jinja_methods
 from kolla import version
 
 
@@ -625,6 +626,17 @@ class KollaWorker(object):
         }
         return filters
 
+    def _get_methods(self):
+        """Mapping of available Jinja methods
+
+        return a dictionary that maps available function names and their
+        corresponding python methods to make them available in jinja templates
+        """
+
+        return {
+            'debian_package_install': jinja_methods.debian_package_install,
+        }
+
     def create_dockerfiles(self):
         kolla_version = version.version_info.cached_version_string()
         supported_distro_release = common_config.DISTRO_RELEASE.get(
@@ -648,6 +660,7 @@ class KollaWorker(object):
             env = jinja2.Environment(  # nosec: not used to render HTML
                 loader=jinja2.FileSystemLoader(self.working_dir))
             env.filters.update(self._get_filters())
+            env.globals.update(self._get_methods())
             tpl_path = os.path.join(
                 os.path.relpath(path, self.working_dir),
                 template_name)
diff --git a/kolla/template/methods.py b/kolla/template/methods.py
new file mode 100644
index 0000000000000000000000000000000000000000..8e655f4c8a987897603b996c033dcee517a5863e
--- /dev/null
+++ b/kolla/template/methods.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+def debian_package_install(packages):
+    """Jinja utility method for building debian-based package install command
+
+    apt-get is not capable of installing .deb files from a URL and the
+    template logic to construct a series of steps to install regular packages
+    from apt repos as well as .deb files that need to be downloaded, manually
+    installed, and cleaned up is complicated. This method will contruct the
+    proper string required to install all packages in a way that's a bit
+    easier to follow
+
+    :param packages: a list of strings that are either packages to install
+    from an apt repo, or URLs to .deb files
+    :type packages: list
+
+    :returns: string suitable to provide to RUN command in a Dockerfile that
+    will install the given packages
+    :rtype: string
+    """
+    cmds = []
+
+    # divide the list into two groups, one for regular packages and one for
+    # URL packages
+    reg_packages, url_packages = [], []
+    for package in packages:
+        if package.startswith('http'):
+            url_packages.append(package)
+        else:
+            reg_packages.append(package)
+
+    # handle the apt-get install
+    if reg_packages:
+        cmds.append('apt-get -y install --no-install-recommends {}'.format(
+            ' '.join(reg_packages)
+        ))
+        cmds.append('apt-get clean')
+
+    # handle URL packages
+    for url in url_packages:
+        # the path portion should be the file name
+        name = url[url.rfind('/') + 1:]
+        cmds.extend([
+            'curl --location {} -o {}'.format(url, name),
+            'dpkg -i {}'.format(name),
+            'rm -rf {}'.format(name),
+        ])
+
+    # return the list of commands
+    return ' && '.join(cmds)