diff --git a/lib/bootstrap-definitions.php b/lib/bootstrap-definitions.php
new file mode 100644
index 0000000000000000000000000000000000000000..3acb0261dd834ad4b590cd64395e79c73785f66b
--- /dev/null
+++ b/lib/bootstrap-definitions.php
@@ -0,0 +1,16 @@
+<?php
+
+use Monolog\Handler\StreamHandler;
+use Monolog\Logger;
+use Psr\Log\LoggerInterface;
+
+return [
+    LoggerInterface::class => DI\factory(function () {
+        return new Logger('studip', [
+            new StreamHandler(
+                $GLOBALS['TMP_PATH'] . '/studip.log',
+                \Studip\ENV === 'development' ? Logger::DEBUG : Logger::ERROR
+            ),
+        ]);
+    }),
+];
diff --git a/lib/bootstrap.php b/lib/bootstrap.php
index 3950eefc8c7bc064aba77a349d59bc13616190bb..94fec26eaffb541f30ba9080230ef1ea46cecdf5 100644
--- a/lib/bootstrap.php
+++ b/lib/bootstrap.php
@@ -99,6 +99,7 @@ if ($GLOBALS['ASSETS_URL'][0] === '/') {
 
 require 'config.inc.php';
 
+require 'lib/helpers.php';
 require 'lib/phplib/page_open.php';
 require_once 'lib/functions.php';
 require_once 'lib/language.inc.php';
diff --git a/lib/classes/DIContainer.php b/lib/classes/DIContainer.php
new file mode 100644
index 0000000000000000000000000000000000000000..22d0d857129fe18e5c350e2159ae32c8d5c9edaa
--- /dev/null
+++ b/lib/classes/DIContainer.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace Studip;
+
+use DI\ContainerBuilder;
+use Psr\Container\ContainerInterface;
+
+class DIContainer
+{
+    /**
+     * The current globally available container.
+     *
+     * @var static
+     */
+    protected static $instance;
+
+    /**
+     * Get the globally available instance of the container.
+     *
+     * @return static
+     */
+    public static function getInstance()
+    {
+        if (is_null(static::$instance)) {
+            $builder = static::createBuilder();
+            static::$instance = $builder->build();
+        }
+
+        return static::$instance;
+    }
+
+    /**
+     * Set the instance of the container.
+     *
+     * @param  \Psr\Container\ContainerInterface|null  $container
+     * @return \Psr\Container\ContainerInterface|static
+     */
+    public static function setInstance(ContainerInterface $container = null)
+    {
+        return static::$instance = $container;
+    }
+
+    /**
+     * Set up the ContainerBuilder.
+     */
+    protected static function createBuilder(): ContainerBuilder
+    {
+        $builder = new ContainerBuilder();
+        if (\Studip\ENV == 'production') {
+            $builder->enableCompilation($GLOBALS['TMP_PATH']);
+        }
+        $builder->ignorePhpDocErrors(true);
+        $builder->addDefinitions('lib/bootstrap-definitions.php');
+
+        return $builder;
+    }
+}
diff --git a/lib/helpers.php b/lib/helpers.php
new file mode 100644
index 0000000000000000000000000000000000000000..d851d73b5bc5d8dde06cef32fe325835c46a976c
--- /dev/null
+++ b/lib/helpers.php
@@ -0,0 +1,30 @@
+<?php
+
+use Psr\Container\ContainerInterface;
+
+/**
+ * This function returns the Dependency Injection container used.
+ *
+ * ```
+ * $container = app();
+ * ```
+ *
+ * You may pass a class or interface name to resolve it from the container:
+ *
+ * ```
+ * $logger = app(LoggerInterface::class);
+ * ```
+ *
+ * @param string|null $entryId
+ *
+ * @return ContainerInterface|mixed either the DI container or the entry associated to the $entryId
+ */
+function app($entryId = null)
+{
+    $container = \Studip\DIContainer::getInstance();
+    if (is_null($entryId)) {
+        return $container;
+    }
+
+    return $container->get($entryId);
+}