diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 4abbd40..c962e26 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -1,6 +1,7 @@
 <?php
 
 use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\DrupalKernel;
 use Drupal\Core\Database\Database;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Symfony\Component\ClassLoader\UniversalClassLoader;
@@ -128,39 +129,44 @@
 const DRUPAL_BOOTSTRAP_CONFIGURATION = 0;
 
 /**
- * Second bootstrap phase: try to serve a cached page.
+ * Second bootstrap phase, initalize a kernel.
  */
-const DRUPAL_BOOTSTRAP_PAGE_CACHE = 1;
+const DRUPAL_BOOTSTRAP_KERNEL = 1;
 
 /**
- * Third bootstrap phase: initialize database layer.
+ * Third bootstrap phase: try to serve a cached page.
  */
-const DRUPAL_BOOTSTRAP_DATABASE = 2;
+const DRUPAL_BOOTSTRAP_PAGE_CACHE = 2;
 
 /**
- * Fourth bootstrap phase: initialize the variable system.
+ * Fourth bootstrap phase: initialize database layer.
  */
-const DRUPAL_BOOTSTRAP_VARIABLES = 3;
+const DRUPAL_BOOTSTRAP_DATABASE = 3;
 
 /**
- * Fifth bootstrap phase: initialize session handling.
+ * Fifth bootstrap phase: initialize the variable system.
  */
-const DRUPAL_BOOTSTRAP_SESSION = 4;
+const DRUPAL_BOOTSTRAP_VARIABLES = 4;
 
 /**
- * Sixth bootstrap phase: set up the page header.
+ * Sixth bootstrap phase: initialize session handling.
  */
-const DRUPAL_BOOTSTRAP_PAGE_HEADER = 5;
+const DRUPAL_BOOTSTRAP_SESSION = 5;
 
 /**
- * Seventh bootstrap phase: load code for subsystems and modules.
+ * Seventh bootstrap phase: set up the page header.
  */
-const DRUPAL_BOOTSTRAP_CODE = 6;
+const DRUPAL_BOOTSTRAP_PAGE_HEADER = 6;
+
+/**
+ * Eighth bootstrap phase: load code for subsystems and modules.
+ */
+const DRUPAL_BOOTSTRAP_CODE = 7;
 
 /**
  * Final bootstrap phase: initialize language, path, theme, and modules.
  */
-const DRUPAL_BOOTSTRAP_FULL = 7;
+const DRUPAL_BOOTSTRAP_FULL = 8;
 
 /**
  * Role ID for anonymous users; should match what's in the "role" table.
@@ -2107,6 +2113,7 @@ function drupal_bootstrap($phase = NULL, $new_phase = TRUE) {
   // Not drupal_static(), because does not depend on any run-time information.
   static $phases = array(
     DRUPAL_BOOTSTRAP_CONFIGURATION,
+    DRUPAL_BOOTSTRAP_KERNEL,
     DRUPAL_BOOTSTRAP_PAGE_CACHE,
     DRUPAL_BOOTSTRAP_DATABASE,
     DRUPAL_BOOTSTRAP_VARIABLES,
@@ -2117,14 +2124,15 @@ function drupal_bootstrap($phase = NULL, $new_phase = TRUE) {
   );
   // Not drupal_static(), because the only legitimate API to control this is to
   // call drupal_bootstrap() with a new phase parameter.
-  static $final_phase;
+  static $final_phase = -1;
   // Not drupal_static(), because it's impossible to roll back to an earlier
   // bootstrap state.
   static $stored_phase = -1;
 
-  // When not recursing, store the phase name so it's not forgotten while
-  // recursing.
-  if ($new_phase) {
+  // When not recursing, store the phase name so it's not forgotten during
+  // recursion. Additionally, ensure that $final_phase is never rolled back to an
+  // earlier bootstrap state.
+  if ($new_phase && $phase > $final_phase) {
     $final_phase = $phase;
   }
   if (isset($phase)) {
@@ -2144,6 +2152,10 @@ function drupal_bootstrap($phase = NULL, $new_phase = TRUE) {
           _drupal_bootstrap_configuration();
           break;
 
+        case DRUPAL_BOOTSTRAP_KERNEL:
+          _drupal_bootstrap_kernel();
+          break;
+
         case DRUPAL_BOOTSTRAP_PAGE_CACHE:
           _drupal_bootstrap_page_cache();
           break;
@@ -2274,6 +2286,18 @@ function _drupal_bootstrap_configuration() {
 }
 
 /**
+ * Initialize the kernel / service container.
+ */
+function _drupal_bootstrap_kernel() {
+  // Normally, index.php puts a kernel in the global namespace. Other scripts
+  // might not.
+  if (empty($GLOBALS['kernel'])) {
+    $kernel = new DrupalKernel('prod', FALSE, drupal_classloader());
+    $kernel->boot();
+  }
+}
+
+/**
  * Attempts to serve a page from the cache.
  */
 function _drupal_bootstrap_page_cache() {
@@ -2440,59 +2464,7 @@ function drupal_container(Container $new_container = NULL, $rebuild = FALSE) {
     $container = $new_container;
   }
   if (!isset($container)) {
-    // This is only ever used by the installer and by run-tests.sh.
-    // @todo Remove this entire section once these have been converted to use a
-    //   kernel.
     $container = new ContainerBuilder();
-
-    // Register active configuration storage.
-    $container
-      ->register('config.cachedstorage.storage', 'Drupal\Core\Config\FileStorage')
-      ->addArgument(config_get_config_directory(CONFIG_ACTIVE_DIRECTORY));
-    // @todo Replace this with a cache.factory service plus 'config' argument.
-    $container
-      ->register('cache.config', 'Drupal\Core\Cache\CacheBackendInterface')
-      ->setFactoryClass('Drupal\Core\Cache\CacheFactory')
-      ->setFactoryMethod('get')
-      ->addArgument('config');
-
-    $container
-      ->register('config.storage', 'Drupal\Core\Config\CachedStorage')
-      ->addArgument(new Reference('config.cachedstorage.storage'))
-      ->addArgument(new Reference('cache.config'));
-
-    // Register configuration object factory.
-    $container->register('config.subscriber.globalconf', 'Drupal\Core\EventSubscriber\ConfigGlobalOverrideSubscriber');
-    $container->register('dispatcher', 'Symfony\Component\EventDispatcher\EventDispatcher')
-      ->addMethodCall('addSubscriber', array(new Reference('config.subscriber.globalconf')));
-    $container->register('config.factory', 'Drupal\Core\Config\ConfigFactory')
-      ->addArgument(new Reference('config.storage'))
-      ->addArgument(new Reference('dispatcher'));
-
-    // Register staging configuration storage.
-    $container
-      ->register('config.storage.staging', 'Drupal\Core\Config\FileStorage')
-      ->addArgument(config_get_config_directory(CONFIG_STAGING_DIRECTORY));
-
-    // Register the service for the default database connection.
-    $container->register('database', 'Drupal\Core\Database\Connection')
-      ->setFactoryClass('Drupal\Core\Database\Database')
-      ->setFactoryMethod('getConnection')
-      ->addArgument('default');
-    // Register the KeyValueStore factory.
-    $container
-      ->register('keyvalue', 'Drupal\Core\KeyValueStore\KeyValueFactory')
-      ->addArgument(new Reference('service_container'));
-    $container
-      ->register('keyvalue.database', 'Drupal\Core\KeyValueStore\KeyValueDatabaseFactory')
-      ->addArgument(new Reference('database'));
-
-    $container->register('path.alias_manager', 'Drupal\Core\Path\AliasManager')
-      ->addArgument(new Reference('database'))
-      ->addArgument(new Reference('keyvalue.database'));
-
-    // Register the EntityManager.
-    $container->register('plugin.manager.entity', 'Drupal\Core\Entity\EntityManager');
   }
   return $container;
 }
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 24ceaf2..e8c8cd7 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -288,6 +288,9 @@ function install_begin_request(&$install_state) {
 
   // Determine whether the configuration system is ready to operate.
   $install_state['config_verified'] = install_verify_config_directory(CONFIG_ACTIVE_DIRECTORY) && install_verify_config_directory(CONFIG_STAGING_DIRECTORY);
+  // Check existing settings.php.
+  $install_state['database_verified'] = install_verify_database_settings();
+  $install_state['settings_verified'] = $install_state['config_verified'] && $install_state['database_verified'];
 
   // If it is not, replace the configuration storage with the InstallStorage
   // implementation, for the following reasons:
@@ -312,7 +315,11 @@ function install_begin_request(&$install_state) {
   // This override is reverted as soon as the config directory has been set up
   // successfully.
   // @see drupal_install_config_directories()
-  if (!$install_state['config_verified']) {
+  if ($install_state['settings_verified']) {
+    $kernel = new DrupalKernel('prod', FALSE, drupal_classloader(), FALSE);
+    $kernel->boot();
+  }
+  else {
     // @todo Move into a proper Drupal\Core\DependencyInjection\InstallContainerBuilder.
     $container = new ContainerBuilder();
 
@@ -362,10 +369,6 @@ function install_begin_request(&$install_state) {
   // accessing the database before it is set up yet.)
   drupal_maintenance_theme();
 
-  // Check existing settings.php.
-  $install_state['database_verified'] = install_verify_database_settings();
-  $install_state['settings_verified'] = $install_state['config_verified'] && $install_state['database_verified'];
-
   if ($install_state['database_verified']) {
     // Initialize the database system. Note that the connection
     // won't be initialized until it is actually requested.
@@ -433,7 +436,7 @@ function install_run_tasks(&$install_state) {
       $install_state['tasks_performed'][] = $task_name;
       $install_state['installation_finished'] = empty($tasks_to_perform);
       if ($install_state['database_tables_exist'] && ($task['run'] == INSTALL_TASK_RUN_IF_NOT_COMPLETED || $install_state['installation_finished'])) {
-        variable_set('install_task', $install_state['installation_finished'] ? 'done' : $task_name);
+        state()->set('install_task', $install_state['installation_finished'] ? 'done' : $task_name);
       }
     }
     // Stop when there are no tasks left. In the case of an interactive
@@ -916,9 +919,7 @@ function install_base_system(&$install_state) {
  */
 function install_verify_completed_task() {
   try {
-    if ($result = db_query("SELECT value FROM {variable} WHERE name = :name", array('name' => 'install_task'))) {
-      $task = unserialize($result->fetchField());
-    }
+    $task = state()->get('install_task');
   }
   // Do not trigger an error if the database query fails, since the database
   // might not be set up yet.
@@ -1104,11 +1105,6 @@ function install_settings_form_submit($form, &$form_state) {
   // Add the config directories to settings.php.
   drupal_install_config_directories();
 
-  // We have valid configuration directories in settings.php.
-  // Reset the service container, so the config.storage service will use the
-  // actual active storage for installing configuration.
-  drupal_container(NULL, TRUE);
-
   // Indicate that the settings file has been verified, and check the database
   // for the last completed task, now that we have a valid connection. This
   // last step is important since we want to trigger an error if the new
@@ -1500,10 +1496,6 @@ function install_bootstrap_full(&$install_state) {
   // Clear the module list that was overriden earlier in the process.
   // This will allow all freshly installed modules to be loaded.
   module_list_reset();
-
-  // Instantiate the kernel.
-  $kernel = new DrupalKernel('prod', FALSE, drupal_classloader(), FALSE);
-  $kernel->boot();
   drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 }
 
diff --git a/core/includes/install.inc b/core/includes/install.inc
index a2666ae..56af13f 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -6,6 +6,7 @@
  */
 
 use Drupal\Core\Database\Database;
+use Drupal\Core\DrupalKernel;
 use Drupal\locale\Gettext;
 
 /**
@@ -421,6 +422,9 @@ function drupal_verify_profile($install_state) {
 function drupal_install_system() {
   // Create tables.
   drupal_install_schema('system');
+  // Immediately boot a kernel to have real services ready.
+  $kernel = new DrupalKernel('prod', FALSE, drupal_classloader(), FALSE);
+  $kernel->boot();
 
   $system_path = drupal_get_path('module', 'system');
   require_once DRUPAL_ROOT . '/' . $system_path . '/system.install';
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index a5624d7..e4d30e3 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -158,13 +158,15 @@ public function boot() {
     }
     $this->initializeContainer();
     $this->booted = TRUE;
-    // @todo Remove this once everything in the bootstrap has been converted to
-    //   services in the DIC.
-    drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE);
-    // Now that full bootstrap is complete, we can dump the container if it
-    // was just rebuilt.
-    if ($this->containerNeedsDumping && !$this->dumpDrupalContainer($this->container, $this->getContainerBaseClass())) {
-      watchdog('DrupalKernel', 'Container cannot be written to disk');
+    if ($this->allowDumping) {
+      // @todo Remove this once everything in the bootstrap has been converted to
+      //   services in the DIC.
+      drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE);
+      // Now that full bootstrap is complete, we can dump the container if it
+      // was just rebuilt.
+      if ($this->containerNeedsDumping && !$this->dumpDrupalContainer($this->container, $this->getContainerBaseClass())) {
+        watchdog('DrupalKernel', 'Container cannot be written to disk');
+      }
     }
   }
 
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php
index ac11b8f..bd11d53 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php
@@ -8,6 +8,7 @@
 namespace Drupal\simpletest;
 
 use Drupal\Core\DrupalKernel;
+use Symfony\Component\DependencyInjection\Reference;
 use Drupal\Core\Database\Database;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -128,6 +129,11 @@ public function containerBuild($container) {
     $conf['keyvalue_default'] = 'keyvalue.memory';
     $container
       ->register('keyvalue.memory', 'Drupal\Core\KeyValueStore\KeyValueMemoryFactory');
+    if (!$container->has('keyvalue')) {
+      $container
+        ->register('keyvalue', 'Drupal\Core\KeyValueStore\KeyValueFactory')
+        ->addArgument(new Reference('service_container'));
+    }
   }
 
   /**
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
index 60a9a77..ceb871e 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -819,7 +819,7 @@ protected function prepareEnvironment() {
     $this->originalContainer = clone drupal_container();
     $this->originalLanguage = $language_interface;
     $this->originalConfigDirectories = $GLOBALS['config_directories'];
-    $this->originalThemeKey = $GLOBALS['theme_key'];
+    $this->originalThemeKey = isset($GLOBALS['theme_key']) ? $GLOBALS['theme_key'] : NULL;
     $this->originalTheme = $GLOBALS['theme'];
 
     // Save further contextual information.
@@ -985,7 +985,9 @@ protected function tearDown() {
     $databases['default']['default'] = $connection_info['default'];
 
     // Restore original globals.
-    $GLOBALS['theme_key'] = $this->originalThemeKey;
+    if (isset($this->originalThemeKey)) {
+      $GLOBALS['theme_key'] = $this->originalThemeKey;
+    }
     $GLOBALS['theme'] = $this->originalTheme;
 
     // Reset all static variables.
