diff --git a/django/db/migrations/writer.py b/django/db/migrations/writer.py
index c8a3a6cf76..f73c4b78a0 100644
--- a/django/db/migrations/writer.py
+++ b/django/db/migrations/writer.py
@@ -6,6 +6,7 @@ import decimal
 import collections
 from importlib import import_module
 import os
+import sys
 import types
 
 from django.apps import apps
@@ -158,7 +159,18 @@ class MigrationWriter(object):
             if '%s.%s' % (app_config.name, migrations_package_basename) == migrations_package_name:
                 basedir = os.path.join(app_config.path, migrations_package_basename)
             else:
-                raise ImportError("Cannot open migrations module %s for app %s" % (migrations_package_name, self.migration.app_label))
+                # In case of using MIGRATION_MODULES setting and the custom
+                # package doesn't exist, create one.
+                package_dirs = migrations_package_name.split(".")
+                create_path = os.path.join(sys.path[0], *package_dirs)
+                if not os.path.isdir(create_path):
+                    os.makedirs(create_path)
+                for i in range(1, len(package_dirs) + 1):
+                    init_dir = os.path.join(sys.path[0], *package_dirs[:i])
+                    init_path = os.path.join(init_dir, "__init__.py")
+                    if not os.path.isfile(init_path):
+                        open(init_path, "w").close()
+                return os.path.join(create_path, self.filename)
         return os.path.join(basedir, self.filename)
 
     @classmethod
diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt
index 6f3c0533b9..683d0f4b0f 100644
--- a/docs/ref/settings.txt
+++ b/docs/ref/settings.txt
@@ -1757,6 +1757,9 @@ Example::
 
 In this case, migrations pertaining to the ``blog`` app will be contained in the ``blog.db_migrations`` package.
 
+:djadmin:`makemigrations` will automatically create the package if it doesn't
+already exist.
+
 .. setting:: MONTH_DAY_FORMAT
 
 MONTH_DAY_FORMAT
diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py
index 4783ffa0c3..4063a8db8e 100644
--- a/tests/migrations/test_commands.py
+++ b/tests/migrations/test_commands.py
@@ -413,3 +413,38 @@ class MakeMigrationsTests(MigrationTestBase):
         self.assertIn("migrations.AddField(", stdout.getvalue())
         self.assertIn("model_name='sillymodel',", stdout.getvalue())
         self.assertIn("name='silly_char',", stdout.getvalue())
+
+    @override_system_checks([])
+    @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_path_doesnt_exist.foo.bar"})
+    def test_makemigrations_migrations_modules_path_not_exist(self):
+        """
+        Ticket #22682 -- Makemigrations fails when specifying custom location
+        for migration files (using MIGRATION_MODULES) if the custom path
+        doesn't already exist.
+        """
+
+        class SillyModel(models.Model):
+            silly_field = models.BooleanField(default=False)
+
+            class Meta:
+                app_label = "migrations"
+
+        stdout = six.StringIO()
+        call_command("makemigrations", "migrations", stdout=stdout)
+
+        # Command output indicates the migration is created.
+        self.assertIn(" - Create model SillyModel", stdout.getvalue())
+
+        # Migrations file is actually created in the expected path.
+        self.assertTrue(os.path.isfile(os.path.join(self.test_dir,
+                       "test_migrations_path_doesnt_exist", "foo", "bar",
+                       "0001_initial.py")))
+
+        os.chdir(self.test_dir)
+        try:
+            self._rmrf(os.path.join(self.test_dir,
+                       "test_migrations_path_doesnt_exist"))
+            pass
+        except OSError:
+            pass
+        os.chdir(self._cwd)