diff --git a/packages/addons/addon-depends/go/package.mk b/packages/addons/addon-depends/go/package.mk
new file mode 100644
index 0000000000..742a38cc05
--- /dev/null
+++ b/packages/addons/addon-depends/go/package.mk
@@ -0,0 +1,60 @@
+################################################################################
+# This file is part of LibreELEC - http://www.libreelec.tv
+# Copyright (C) 2009-2016 Lukas Rusak (lrusak@libreelec.tv)
+#
+# LibreELEC is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# LibreELEC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with LibreELEC. If not, see .
+################################################################################
+
+PKG_NAME="go"
+PKG_VERSION="1.6"
+PKG_REV="1"
+PKG_ARCH="any"
+PKG_LICENSE="BSD"
+PKG_SITE="https://golang.org"
+PKG_URL="https://github.com/golang/go/archive/${PKG_NAME}${PKG_VERSION}.tar.gz"
+PKG_SOURCE_DIR="${PKG_NAME}-${PKG_NAME}${PKG_VERSION}"
+PKG_DEPENDS_HOST="toolchain"
+PKG_PRIORITY="optional"
+PKG_SECTION="system"
+PKG_SHORTDESC="Go is an open source programming language that makes it easy to build simple, reliable, and efficient software."
+PKG_LONGDESC="Go is an open source programming language that makes it easy to build simple, reliable, and efficient software."
+
+PKG_IS_ADDON="no"
+PKG_AUTORECONF="no"
+
+####################################################################
+# On Fedora `dnf install golang` will install go to /usr/lib/golang
+#
+# On Ubuntu you need to install golang manually, similar to:
+# $ wget https://storage.googleapis.com/golang/go1.6.linux-amd64.tar.gz
+# $ tar xf go1.6.linux-amd64.tar.gz -C /opt/
+# $ ln -s /opt/go /usr/lib/golang
+####################################################################
+
+configure_host() {
+ export GOOS=linux
+ export GOROOT_FINAL=$ROOT/$TOOLCHAIN/lib/golang
+ export GOROOT_BOOTSTRAP=/usr/lib/golang
+ export GOARCH=amd64
+}
+
+make_host() {
+ cd $ROOT/$PKG_BUILD/src
+ bash make.bash --no-banner
+}
+
+makeinstall_host() {
+ mkdir -p $ROOT/$TOOLCHAIN/lib/golang
+ cp -av $ROOT/$PKG_BUILD/* $ROOT/$TOOLCHAIN/lib/golang/
+}
diff --git a/packages/addons/service/docker/changelog.txt b/packages/addons/service/docker/changelog.txt
new file mode 100644
index 0000000000..f9dfb73a63
--- /dev/null
+++ b/packages/addons/service/docker/changelog.txt
@@ -0,0 +1,2 @@
+7.0.100
+- Initial release
diff --git a/packages/addons/service/docker/icon/icon.png b/packages/addons/service/docker/icon/icon.png
new file mode 100644
index 0000000000..c9f07eb63b
Binary files /dev/null and b/packages/addons/service/docker/icon/icon.png differ
diff --git a/packages/addons/service/docker/package.mk b/packages/addons/service/docker/package.mk
new file mode 100644
index 0000000000..6ed609d86a
--- /dev/null
+++ b/packages/addons/service/docker/package.mk
@@ -0,0 +1,96 @@
+################################################################################
+# This file is part of LibreELEC - http://www.libreelec.tv
+# Copyright (C) 2009-2016 Lukas Rusak (lrusak@libreelec.tv)
+#
+# LibreELEC is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# LibreELEC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with LibreELEC. If not, see .
+################################################################################
+
+PKG_NAME="docker"
+PKG_VERSION="1.10.3"
+PKG_REV="100"
+PKG_ARCH="any"
+PKG_ADDON_PROJECTS="Generic RPi RPi2"
+PKG_LICENSE="ASL"
+PKG_SITE="http://www.docker.com/"
+PKG_URL="https://github.com/docker/docker/archive/v${PKG_VERSION}.tar.gz"
+PKG_DEPENDS_TARGET="toolchain sqlite go:host"
+PKG_PRIORITY="optional"
+PKG_SECTION="service/system"
+PKG_SHORTDESC="Docker is an open-source engine that automates the deployment of any application as a lightweight, portable, self-sufficient container that will run virtually anywhere."
+PKG_LONGDESC="Docker containers can encapsulate any payload, and will run consistently on and between virtually any server. The same container that a developer builds and tests on a laptop will run at scale, in production*, on VMs, bare-metal servers, OpenStack clusters, public instances, or combinations of the above."
+PKG_AUTORECONF="no"
+
+PKG_IS_ADDON="yes"
+PKG_ADDON_NAME="Docker"
+PKG_ADDON_TYPE="xbmc.service"
+PKG_ADDON_REPOVERSION="7.0"
+
+configure_target() {
+ export DOCKER_BUILDTAGS="daemon \
+ exclude_graphdriver_devicemapper \
+ exclude_graphdriver_aufs \
+ exclude_graphdriver_btrfs"
+
+ case $TARGET_ARCH in
+ x86_64)
+ export GOARCH=amd64
+ ;;
+ arm)
+ export GOARCH=arm
+
+ case $TARGET_CPU in
+ arm1176jzf-s)
+ export GOARM=6
+ ;;
+ cortex-a7)
+ export GOARM=7
+ ;;
+ esac
+ ;;
+ esac
+
+ export GOOS=linux
+ export CGO_ENABLED=1
+ export CGO_NO_EMULATION=1
+ export CGO_CFLAGS=$CFLAGS
+ export LDFLAGS="-w -linkmode external -extldflags -Wl,--unresolved-symbols=ignore-in-shared-libs -extld $TARGET_CC"
+ export GOLANG=$ROOT/$TOOLCHAIN/lib/golang/bin/go
+ export GOPATH=$ROOT/$PKG_BUILD/.gopath:$ROOT/$PKG_BUILD/vendor
+ export GOROOT=$ROOT/$TOOLCHAIN/lib/golang
+ export PATH=$PATH:$GOROOT/bin
+
+ ./hack/vendor.sh
+
+ ln -fs $ROOT/$PKG_BUILD $ROOT/$PKG_BUILD/vendor/src/github.com/docker/docker
+
+ # used for docker version
+ export GITCOMMIT=$PKG_VERSION
+ export VERSION=$PKG_VERSION
+ export BUILDTIME="$(date --utc)"
+ bash ./hack/make/.go-autogen
+}
+
+make_target() {
+ mkdir -p bin
+ $GOLANG build -v -o bin/docker -a -tags "$DOCKER_BUILDTAGS" -ldflags "$LDFLAGS" ./docker
+}
+
+makeinstall_target() {
+ :
+}
+
+addon() {
+ mkdir -p $ADDON_BUILD/$PKG_ADDON_ID/bin/
+ cp -a $ROOT/$PKG_BUILD/bin/docker $ADDON_BUILD/$PKG_ADDON_ID/bin/
+}
diff --git a/packages/addons/service/docker/patches/docker-001-use-addon-storage-location.patch b/packages/addons/service/docker/patches/docker-001-use-addon-storage-location.patch
new file mode 100644
index 0000000000..cd97127c2d
--- /dev/null
+++ b/packages/addons/service/docker/patches/docker-001-use-addon-storage-location.patch
@@ -0,0 +1,290 @@
+# Created with
+# find . -name "*.go" -print | xargs sed -i 's/\/etc\/docker/\/storage\/.kodi\/userdata\/addon_data\/service.system.docker\/config/g'
+
+diff -Naur a/docker/daemon_unix.go b/docker/daemon_unix.go
+--- a/docker/daemon_unix.go 2016-02-11 19:45:56.000000000 +0100
++++ b/docker/daemon_unix.go 2016-02-19 00:28:50.662085695 +0100
+@@ -16,7 +16,7 @@
+ _ "github.com/docker/docker/daemon/execdriver/native"
+ )
+
+-const defaultDaemonConfigFile = "/etc/docker/daemon.json"
++const defaultDaemonConfigFile = "/storage/.kodi/userdata/addon_data/service.system.docker/config/daemon.json"
+
+ func setPlatformServerConfig(serverConfig *apiserver.Config, daemonCfg *daemon.Config) *apiserver.Config {
+ serverConfig.SocketGroup = daemonCfg.SocketGroup
+@@ -50,7 +50,7 @@
+ }
+
+ func getDaemonConfDir() string {
+- return "/etc/docker"
++ return "/storage/.kodi/userdata/addon_data/service.system.docker/config"
+ }
+
+ // setupConfigReloadTrap configures the USR2 signal to reload the configuration.
+diff -Naur a/integration-cli/docker_cli_authz_unix_test.go b/integration-cli/docker_cli_authz_unix_test.go
+--- a/integration-cli/docker_cli_authz_unix_test.go 2016-02-11 19:45:56.000000000 +0100
++++ b/integration-cli/docker_cli_authz_unix_test.go 2016-02-19 00:28:50.642085661 +0100
+@@ -121,10 +121,10 @@
+ }
+ })
+
+- err := os.MkdirAll("/etc/docker/plugins", 0755)
++ err := os.MkdirAll("/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins", 0755)
+ c.Assert(err, checker.IsNil)
+
+- fileName := fmt.Sprintf("/etc/docker/plugins/%s.spec", testAuthZPlugin)
++ fileName := fmt.Sprintf("/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins/%s.spec", testAuthZPlugin)
+ err = ioutil.WriteFile(fileName, []byte(s.server.URL), 0644)
+ c.Assert(err, checker.IsNil)
+ }
+@@ -163,7 +163,7 @@
+
+ s.server.Close()
+
+- err := os.RemoveAll("/etc/docker/plugins")
++ err := os.RemoveAll("/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins")
+ c.Assert(err, checker.IsNil)
+ }
+
+diff -Naur a/integration-cli/docker_cli_daemon_test.go b/integration-cli/docker_cli_daemon_test.go
+--- a/integration-cli/docker_cli_daemon_test.go 2016-02-11 19:45:56.000000000 +0100
++++ b/integration-cli/docker_cli_daemon_test.go 2016-02-19 00:28:50.636085651 +0100
+@@ -537,13 +537,13 @@
+
+ func (s *DockerDaemonSuite) TestDaemonKeyGeneration(c *check.C) {
+ // TODO: skip or update for Windows daemon
+- os.Remove("/etc/docker/key.json")
++ os.Remove("/storage/.kodi/userdata/addon_data/service.system.docker/config/key.json")
+ if err := s.d.Start(); err != nil {
+ c.Fatalf("Could not start daemon: %v", err)
+ }
+ s.d.Stop()
+
+- k, err := libtrust.LoadKeyFile("/etc/docker/key.json")
++ k, err := libtrust.LoadKeyFile("/storage/.kodi/userdata/addon_data/service.system.docker/config/key.json")
+ if err != nil {
+ c.Fatalf("Error opening key file")
+ }
+@@ -556,7 +556,7 @@
+
+ func (s *DockerDaemonSuite) TestDaemonKeyMigration(c *check.C) {
+ // TODO: skip or update for Windows daemon
+- os.Remove("/etc/docker/key.json")
++ os.Remove("/storage/.kodi/userdata/addon_data/service.system.docker/config/key.json")
+ k1, err := libtrust.GenerateECP256PrivateKey()
+ if err != nil {
+ c.Fatalf("Error generating private key: %s", err)
+@@ -573,7 +573,7 @@
+ }
+ s.d.Stop()
+
+- k2, err := libtrust.LoadKeyFile("/etc/docker/key.json")
++ k2, err := libtrust.LoadKeyFile("/storage/.kodi/userdata/addon_data/service.system.docker/config/key.json")
+ if err != nil {
+ c.Fatalf("Error opening key file")
+ }
+@@ -1337,7 +1337,7 @@
+ Y string `json:"y"`
+ }
+
+- os.Remove("/etc/docker/key.json")
++ os.Remove("/storage/.kodi/userdata/addon_data/service.system.docker/config/key.json")
+ if err := s.d.Start(); err != nil {
+ c.Fatalf("Failed to start daemon: %v", err)
+ }
+@@ -1347,7 +1347,7 @@
+ }
+
+ config := &Config{}
+- bytes, err := ioutil.ReadFile("/etc/docker/key.json")
++ bytes, err := ioutil.ReadFile("/storage/.kodi/userdata/addon_data/service.system.docker/config/key.json")
+ if err != nil {
+ c.Fatalf("Error reading key.json file: %s", err)
+ }
+@@ -1367,11 +1367,11 @@
+ }
+
+ // write back
+- if err := ioutil.WriteFile("/etc/docker/key.json", newBytes, 0400); err != nil {
++ if err := ioutil.WriteFile("/storage/.kodi/userdata/addon_data/service.system.docker/config/key.json", newBytes, 0400); err != nil {
+ c.Fatalf("Error ioutil.WriteFile: %s", err)
+ }
+
+- defer os.Remove("/etc/docker/key.json")
++ defer os.Remove("/storage/.kodi/userdata/addon_data/service.system.docker/config/key.json")
+
+ if err := s.d.Start(); err == nil {
+ c.Fatalf("It should not be successful to start daemon with wrong key: %v", err)
+diff -Naur a/integration-cli/docker_cli_external_graphdriver_unix_test.go b/integration-cli/docker_cli_external_graphdriver_unix_test.go
+--- a/integration-cli/docker_cli_external_graphdriver_unix_test.go 2016-02-11 19:45:56.000000000 +0100
++++ b/integration-cli/docker_cli_external_graphdriver_unix_test.go 2016-02-19 00:28:50.632085644 +0100
+@@ -283,18 +283,18 @@
+ respond(w, &graphDriverResponse{Size: size})
+ })
+
+- err = os.MkdirAll("/etc/docker/plugins", 0755)
+- c.Assert(err, check.IsNil, check.Commentf("error creating /etc/docker/plugins"))
++ err = os.MkdirAll("/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins", 0755)
++ c.Assert(err, check.IsNil, check.Commentf("error creating /storage/.kodi/userdata/addon_data/service.system.docker/config/plugins"))
+
+- err = ioutil.WriteFile("/etc/docker/plugins/test-external-graph-driver.spec", []byte(s.server.URL), 0644)
+- c.Assert(err, check.IsNil, check.Commentf("error writing to /etc/docker/plugins/test-external-graph-driver.spec"))
++ err = ioutil.WriteFile("/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins/test-external-graph-driver.spec", []byte(s.server.URL), 0644)
++ c.Assert(err, check.IsNil, check.Commentf("error writing to /storage/.kodi/userdata/addon_data/service.system.docker/config/plugins/test-external-graph-driver.spec"))
+ }
+
+ func (s *DockerExternalGraphdriverSuite) TearDownSuite(c *check.C) {
+ s.server.Close()
+
+- err := os.RemoveAll("/etc/docker/plugins")
+- c.Assert(err, check.IsNil, check.Commentf("error removing /etc/docker/plugins"))
++ err := os.RemoveAll("/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins")
++ c.Assert(err, check.IsNil, check.Commentf("error removing /storage/.kodi/userdata/addon_data/service.system.docker/config/plugins"))
+ }
+
+ func (s *DockerExternalGraphdriverSuite) TestExternalGraphDriver(c *check.C) {
+diff -Naur a/integration-cli/docker_cli_network_unix_test.go b/integration-cli/docker_cli_network_unix_test.go
+--- a/integration-cli/docker_cli_network_unix_test.go 2016-02-11 19:45:56.000000000 +0100
++++ b/integration-cli/docker_cli_network_unix_test.go 2016-02-19 00:28:50.629085639 +0100
+@@ -201,14 +201,14 @@
+ }
+ })
+
+- err := os.MkdirAll("/etc/docker/plugins", 0755)
++ err := os.MkdirAll("/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins", 0755)
+ c.Assert(err, checker.IsNil)
+
+- fileName := fmt.Sprintf("/etc/docker/plugins/%s.spec", netDrv)
++ fileName := fmt.Sprintf("/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins/%s.spec", netDrv)
+ err = ioutil.WriteFile(fileName, []byte(url), 0644)
+ c.Assert(err, checker.IsNil)
+
+- ipamFileName := fmt.Sprintf("/etc/docker/plugins/%s.spec", ipamDrv)
++ ipamFileName := fmt.Sprintf("/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins/%s.spec", ipamDrv)
+ err = ioutil.WriteFile(ipamFileName, []byte(url), 0644)
+ c.Assert(err, checker.IsNil)
+ }
+@@ -220,7 +220,7 @@
+
+ s.server.Close()
+
+- err := os.RemoveAll("/etc/docker/plugins")
++ err := os.RemoveAll("/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins")
+ c.Assert(err, checker.IsNil)
+ }
+
+diff -Naur a/integration-cli/docker_cli_start_volume_driver_unix_test.go b/integration-cli/docker_cli_start_volume_driver_unix_test.go
+--- a/integration-cli/docker_cli_start_volume_driver_unix_test.go 2016-02-11 19:45:56.000000000 +0100
++++ b/integration-cli/docker_cli_start_volume_driver_unix_test.go 2016-02-19 00:28:50.651085676 +0100
+@@ -206,17 +206,17 @@
+ send(w, nil)
+ })
+
+- err := os.MkdirAll("/etc/docker/plugins", 0755)
++ err := os.MkdirAll("/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins", 0755)
+ c.Assert(err, checker.IsNil)
+
+- err = ioutil.WriteFile("/etc/docker/plugins/test-external-volume-driver.spec", []byte(s.server.URL), 0644)
++ err = ioutil.WriteFile("/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins/test-external-volume-driver.spec", []byte(s.server.URL), 0644)
+ c.Assert(err, checker.IsNil)
+ }
+
+ func (s *DockerExternalVolumeSuite) TearDownSuite(c *check.C) {
+ s.server.Close()
+
+- err := os.RemoveAll("/etc/docker/plugins")
++ err := os.RemoveAll("/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins")
+ c.Assert(err, checker.IsNil)
+ }
+
+@@ -301,7 +301,7 @@
+
+ // Make sure a request to use a down driver doesn't block other requests
+ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverLookupNotBlocked(c *check.C) {
+- specPath := "/etc/docker/plugins/down-driver.spec"
++ specPath := "/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins/down-driver.spec"
+ err := ioutil.WriteFile(specPath, []byte("tcp://127.0.0.7:9999"), 0644)
+ c.Assert(err, check.IsNil)
+ defer os.RemoveAll(specPath)
+@@ -340,7 +340,7 @@
+ err := s.d.StartWithBusybox()
+ c.Assert(err, checker.IsNil)
+
+- specPath := "/etc/docker/plugins/test-external-volume-driver-retry.spec"
++ specPath := "/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins/test-external-volume-driver-retry.spec"
+ os.RemoveAll(specPath)
+ defer os.RemoveAll(specPath)
+
+diff -Naur a/integration-cli/docker_cli_volume_driver_compat_unix_test.go b/integration-cli/docker_cli_volume_driver_compat_unix_test.go
+--- a/integration-cli/docker_cli_volume_driver_compat_unix_test.go 2016-02-11 19:45:56.000000000 +0100
++++ b/integration-cli/docker_cli_volume_driver_compat_unix_test.go 2016-02-19 00:28:50.646085667 +0100
+@@ -173,17 +173,17 @@
+ send(w, nil)
+ })
+
+- err := os.MkdirAll("/etc/docker/plugins", 0755)
++ err := os.MkdirAll("/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins", 0755)
+ c.Assert(err, checker.IsNil)
+
+- err = ioutil.WriteFile("/etc/docker/plugins/test-external-volume-driver.spec", []byte(s.server.URL), 0644)
++ err = ioutil.WriteFile("/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins/test-external-volume-driver.spec", []byte(s.server.URL), 0644)
+ c.Assert(err, checker.IsNil)
+ }
+
+ func (s *DockerExternalVolumeSuiteCompatV1_1) TearDownSuite(c *check.C) {
+ s.server.Close()
+
+- err := os.RemoveAll("/etc/docker/plugins")
++ err := os.RemoveAll("/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins")
+ c.Assert(err, checker.IsNil)
+ }
+
+diff -Naur a/pkg/plugins/discovery.go b/pkg/plugins/discovery.go
+--- a/pkg/plugins/discovery.go 2016-02-11 19:45:56.000000000 +0100
++++ b/pkg/plugins/discovery.go 2016-02-19 00:28:50.247084996 +0100
+@@ -15,7 +15,7 @@
+ // ErrNotFound plugin not found
+ ErrNotFound = errors.New("plugin not found")
+ socketsPath = "/run/docker/plugins"
+- specsPaths = []string{"/etc/docker/plugins", "/usr/lib/docker/plugins"}
++ specsPaths = []string{"/storage/.kodi/userdata/addon_data/service.system.docker/config/plugins", "/usr/lib/docker/plugins"}
+ )
+
+ // localRegistry defines a registry that is local (using unix socket).
+diff -Naur a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go
+--- a/pkg/plugins/plugins.go 2016-02-11 19:45:56.000000000 +0100
++++ b/pkg/plugins/plugins.go 2016-02-19 00:28:50.263085023 +0100
+@@ -4,7 +4,7 @@
+ // Docker discovers plugins by looking for them in the plugin directory whenever
+ // a user or container tries to use one by name. UNIX domain socket files must
+ // be located under /run/docker/plugins, whereas spec files can be located
+-// either under /etc/docker/plugins or /usr/lib/docker/plugins. This is handled
++// either under /storage/.kodi/userdata/addon_data/service.system.docker/config/plugins or /usr/lib/docker/plugins. This is handled
+ // by the Registry interface, which lets you list all plugins or get a plugin by
+ // its name if it exists.
+ //
+diff -Naur a/registry/config_unix.go b/registry/config_unix.go
+--- a/registry/config_unix.go 2016-02-11 19:45:56.000000000 +0100
++++ b/registry/config_unix.go 2016-02-19 00:28:50.742085829 +0100
+@@ -12,7 +12,7 @@
+
+ var (
+ // CertsDir is the directory where certificates are stored
+- CertsDir = "/etc/docker/certs.d"
++ CertsDir = "/storage/.kodi/userdata/addon_data/service.system.docker/config/certs.d"
+ )
+
+ // cleanPath is used to ensure that a directory name is valid on the target
+diff -Naur a/registry/endpoint.go b/registry/endpoint.go
+--- a/registry/endpoint.go 2016-02-11 19:45:56.000000000 +0100
++++ b/registry/endpoint.go 2016-02-19 00:28:50.740085826 +0100
+@@ -73,7 +73,7 @@
+ if endpoint.IsSecure {
+ // If registry is secure and HTTPS failed, show user the error and tell them about `--insecure-registry`
+ // in case that's what they need. DO NOT accept unknown CA certificates, and DO NOT fallback to HTTP.
+- return fmt.Errorf("invalid registry endpoint %s: %v. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add `--insecure-registry %s` to the daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/%s/ca.crt", endpoint, err, endpoint.URL.Host, endpoint.URL.Host)
++ return fmt.Errorf("invalid registry endpoint %s: %v. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add `--insecure-registry %s` to the daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /storage/.kodi/userdata/addon_data/service.system.docker/config/certs.d/%s/ca.crt", endpoint, err, endpoint.URL.Host, endpoint.URL.Host)
+ }
+
+ // If registry is insecure and HTTPS failed, fallback to HTTP.
diff --git a/packages/addons/service/docker/source/bin/docker-config b/packages/addons/service/docker/source/bin/docker-config
new file mode 100755
index 0000000000..da5002b070
--- /dev/null
+++ b/packages/addons/service/docker/source/bin/docker-config
@@ -0,0 +1,37 @@
+#!/bin/sh
+################################################################################
+# This file is part of LibreELEC - http://www.libreelec.tv
+# Copyright (C) 2009-2016 Lukas Rusak (lrusak@libreelec.tv)
+#
+# LibreELEC is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# LibreELEC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with LibreELEC. If not, see .
+################################################################################
+
+ADDON_DIR="/storage/.kodi/addons/service.system.docker"
+ADDON_HOME_DIR="/storage/.kodi/userdata/addon_data/service.system.docker"
+
+if [ ! -d "$ADDON_HOME_DIR/config" ]; then
+ mkdir -p $ADDON_HOME_DIR/config
+fi
+
+if [ ! -f "$ADDON_HOME_DIR/config/docker.conf" ]; then
+ cp $ADDON_DIR/config/docker.conf $ADDON_HOME_DIR/config/docker.conf
+fi
+
+if [ ! -d "$ADDON_HOME_DIR/docker" ]; then
+ mkdir -p $ADDON_HOME_DIR/docker
+fi
+
+if [ ! -d /var/lib/docker ]; then
+ ln -sf $ADDON_HOME_DIR/docker /var/lib/docker
+fi
diff --git a/packages/addons/service/docker/source/config/docker.conf b/packages/addons/service/docker/source/config/docker.conf
new file mode 100644
index 0000000000..36908b53d7
--- /dev/null
+++ b/packages/addons/service/docker/source/config/docker.conf
@@ -0,0 +1,2 @@
+DOCKER_DAEMON_OPTS="--graph=/storage/.kodi/userdata/addon_data/service.system.docker/docker"
+DOCKER_STORAGE_OPTS="--storage-driver=overlay"
diff --git a/packages/addons/service/docker/source/default.py b/packages/addons/service/docker/source/default.py
new file mode 100644
index 0000000000..807ce9432b
--- /dev/null
+++ b/packages/addons/service/docker/source/default.py
@@ -0,0 +1,103 @@
+################################################################################
+# This file is part of LibreELEC - http://www.libreelec.tv
+# Copyright (C) 2009-2016 Lukas Rusak (lrusak@libreelec.tv)
+#
+# LibreELEC is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# LibreELEC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with LibreELEC. If not, see .
+################################################################################
+
+import os
+import subprocess
+import sys
+import time
+import xbmc
+import xbmcaddon
+import xbmcgui
+
+sys.path.append('/usr/share/kodi/addons/service.libreelec.settings')
+
+import oe
+
+__author__ = 'lrusak'
+__addon__ = xbmcaddon.Addon()
+__path__ = __addon__.getAddonInfo('path')
+__service__ = __path__ + '/systemd/' + __addon__.getAddonInfo('id') + '.service'
+__servicename__ = __addon__.getAddonInfo('id') + '.service'
+__socket__ = __path__ + '/systemd/' + __addon__.getAddonInfo('id') + '.socket'
+__socketname__ = __addon__.getAddonInfo('id') + '.socket'
+
+class Main(object):
+
+ def __init__(self, *args, **kwargs):
+
+ monitor = DockerMonitor(self)
+
+ if not Docker().is_enabled():
+ Docker().enable()
+ Docker().start()
+
+ while not monitor.abortRequested():
+ if monitor.waitForAbort():
+ Docker().stop()
+ Docker().disable()
+
+class Docker(object):
+
+ def enable(self):
+ self.execute('systemctl enable ' + __service__)
+ self.execute('systemctl enable ' + __socket__)
+
+ def disable(self):
+ self.execute('systemctl disable ' + __servicename__)
+ self.execute('systemctl disable ' + __socketname__)
+
+ def is_enabled(self):
+ if self.execute('systemctl is-enabled ' + __servicename__, get_result=1).strip('\n') == 'enabled':
+ return True
+ else:
+ return False
+
+ def start(self):
+ self.execute('systemctl start ' + __servicename__)
+
+ def stop(self):
+ self.execute('systemctl stop ' + __servicename__)
+
+ def is_active(self):
+ if self.execute('systemctl is-active ' + __servicename__, get_result=1).strip('\n') == 'active':
+ return True
+ else:
+ return False
+
+ def execute(self, command_line, get_result=0):
+ result = oe.execute(command_line, get_result=get_result)
+ if get_result:
+ return result
+
+ def restart(self):
+ if self.is_active():
+ self.stop()
+ self.start()
+
+class DockerMonitor(xbmc.Monitor):
+
+ def __init__(self, *args, **kwargs):
+ xbmc.Monitor.__init__(self)
+
+ def onSettingsChanged(self):
+ Docker().restart()
+
+if ( __name__ == "__main__" ):
+ Main()
+
+ del DockerMonitor
diff --git a/packages/addons/service/docker/source/examples/couchpotato.service b/packages/addons/service/docker/source/examples/couchpotato.service
new file mode 100644
index 0000000000..3fd8b371f5
--- /dev/null
+++ b/packages/addons/service/docker/source/examples/couchpotato.service
@@ -0,0 +1,22 @@
+[Unit]
+Description=%p container
+Requires=service.system.docker.service
+After=service.system.docker.service
+
+[Service]
+Restart=always
+RestartSec=10s
+TimeoutStartSec=0
+ExecStartPre=-/bin/sh -c "mkdir -p /storage/%p/config /storage/%p/data"
+ExecStart=/storage/.kodi/addons/service.system.docker/bin/docker run \
+ --rm \
+ --name=%p \
+ --hostname=libreelec-%p \
+ --volume=/storage/%p/config:/config \
+ --volume=/storage/%p/data:/data \
+ --publish=5050:5050 \
+ timhaak/%p
+ExecStop=/storage/.kodi/addons/service.system.docker/bin/docker stop %p
+
+[Install]
+WantedBy=multi-user.target
diff --git a/packages/addons/service/docker/source/examples/mysql.service b/packages/addons/service/docker/source/examples/mysql.service
new file mode 100644
index 0000000000..77b0667ed1
--- /dev/null
+++ b/packages/addons/service/docker/source/examples/mysql.service
@@ -0,0 +1,26 @@
+[Unit]
+Description=%p container
+Requires=service.system.docker.service
+After=service.system.docker.service
+Befora=kodi.service
+
+[Service]
+Restart=always
+RestartSec=10s
+TimeoutStartSec=0
+ExecStartPre=-/bin/sh -c "mkdir -p /storage/%p/config /storage/%p/data"
+ExecStart=/storage/.kodi/addons/service.system.docker/bin/docker run \
+ --rm \
+ --name=%p \
+ --hostname=libreelec-%p \
+ --volume=/storage/%p/config/:/etc/mysql/conf.d \
+ --volume=/storage/%p/data:/var/lib/mysql \
+ --publish=3306:3306 \
+ --env=MYSQL_ROOT_PASSWORD=libreelec \
+ --env=MYSQL_USER=kodi \
+ --env=MYSQL_PASSWORD=kodi \
+ %p
+ExecStop=/storage/.kodi/addons/service.system.docker/bin/docker stop %p
+
+[Install]
+WantedBy=multi-user.target
diff --git a/packages/addons/service/docker/source/examples/sabnzbd.service b/packages/addons/service/docker/source/examples/sabnzbd.service
new file mode 100644
index 0000000000..e85e4da1b7
--- /dev/null
+++ b/packages/addons/service/docker/source/examples/sabnzbd.service
@@ -0,0 +1,22 @@
+[Unit]
+Description=%p container
+Requires=service.system.docker.service
+After=service.system.docker.service
+
+[Service]
+Restart=always
+RestartSec=10s
+TimeoutStartSec=0
+ExecStartPre=-/bin/sh -c "mkdir -p /storage/%p/config /storage/%p/data"
+ExecStart=/storage/.kodi/addons/service.system.docker/bin/docker run \
+ --rm \
+ --name=%p \
+ --hostname=libreelec-%p \
+ --volume=/storage/%p/config:/config \
+ --volume=/storage/%p/data:/data \
+ --publish=8080:8080 \
+ timhaak/%p
+ExecStop=/storage/.kodi/addons/service.system.docker/bin/docker stop %p
+
+[Install]
+WantedBy=multi-user.target
diff --git a/packages/addons/service/docker/source/examples/sickbeard.service b/packages/addons/service/docker/source/examples/sickbeard.service
new file mode 100644
index 0000000000..573342bb92
--- /dev/null
+++ b/packages/addons/service/docker/source/examples/sickbeard.service
@@ -0,0 +1,22 @@
+[Unit]
+Description=%p container
+Requires=service.system.docker.service
+After=service.system.docker.service
+
+[Service]
+Restart=always
+RestartSec=10s
+TimeoutStartSec=0
+ExecStartPre=-/bin/sh -c "mkdir -p /storage/%p/config /storage/%p/data"
+ExecStart=/storage/.kodi/addons/service.system.docker/bin/docker run \
+ --rm \
+ --name=%p \
+ --hostname=libreelec-%p \
+ --volume=/storage/%p/config:/config \
+ --volume=/storage/%p/data:/data \
+ --publish=8081:8081 \
+ timhaak/%p
+ExecStop=/storage/.kodi/addons/service.system.docker/bin/docker stop %p
+
+[Install]
+WantedBy=multi-user.target
diff --git a/packages/addons/service/docker/source/examples/transmission.service b/packages/addons/service/docker/source/examples/transmission.service
new file mode 100644
index 0000000000..7a248c6934
--- /dev/null
+++ b/packages/addons/service/docker/source/examples/transmission.service
@@ -0,0 +1,24 @@
+[Unit]
+Description=%p container
+Requires=service.system.docker.service
+After=service.system.docker.service
+
+[Service]
+Restart=always
+RestartSec=10s
+TimeoutStartSec=0
+ExecStartPre=-/bin/sh -c "mkdir -p /storage/%p/watch /storage/%p/downloads /storage/%p/incomplete /storage/%p/config"
+ExecStart=/storage/.kodi/addons/service.system.docker/bin/docker run \
+ --rm \
+ --name=%p \
+ --hostname=libreelec-%p \
+ --volume=/storage/%p/watch:/watch \
+ --volume=/storage/%p/downloads:/downloads \
+ --volume=/storage/%p/incomplete:/incomplete \
+ --volume=/storage/%p/config:/config \
+ --publish=9091:9091 \
+ timhaak/%p
+ExecStop=/storage/.kodi/addons/service.system.docker/bin/docker stop %p
+
+[Install]
+WantedBy=multi-user.target
diff --git a/packages/addons/service/docker/source/examples/var-lib-docker.mount b/packages/addons/service/docker/source/examples/var-lib-docker.mount
new file mode 100644
index 0000000000..6744e125c3
--- /dev/null
+++ b/packages/addons/service/docker/source/examples/var-lib-docker.mount
@@ -0,0 +1,14 @@
+[Unit]
+Description=Docker loopback mount
+Requires=local-fs.target
+Before=service.system.docker.service
+
+[Mount]
+What=/storage/btrfs-loop.img
+Where=/var/lib/docker
+
+Options=loop,compress=lzo
+Type=btrfs
+
+[Install]
+WantedBy=multi-user.target
diff --git a/packages/addons/service/docker/source/systemd/service.system.docker.service b/packages/addons/service/docker/source/systemd/service.system.docker.service
new file mode 100644
index 0000000000..0a2d5add32
--- /dev/null
+++ b/packages/addons/service/docker/source/systemd/service.system.docker.service
@@ -0,0 +1,19 @@
+[Unit]
+Description=Docker Application Container Engine
+Documentation=https://docs.docker.com
+After=network.target docker.socket
+Requires=docker.socket
+
+[Service]
+Type=notify
+ExecStartPre=/storage/.kodi/addons/service.system.docker/bin/docker-config
+EnvironmentFile=-/storage/.kodi/userdata/addon_data/service.system.docker/config/docker.conf
+ExecStart=/storage/.kodi/addons/service.system.docker/bin/docker daemon -H fd:// $DOCKER_DAEMON_OPTS $DOCKER_STORAGE_OPTS
+MountFlags=slave
+LimitNOFILE=1048576
+LimitNPROC=1048576
+LimitCORE=infinity
+
+[Install]
+WantedBy=multi-user.target
+Alias=docker.service
diff --git a/packages/addons/service/docker/source/systemd/service.system.docker.socket b/packages/addons/service/docker/source/systemd/service.system.docker.socket
new file mode 100644
index 0000000000..578b38bc98
--- /dev/null
+++ b/packages/addons/service/docker/source/systemd/service.system.docker.socket
@@ -0,0 +1,13 @@
+[Unit]
+Description=Docker Socket for the API
+PartOf=docker.service
+
+[Socket]
+ListenStream=/var/run/docker.sock
+SocketMode=0660
+SocketUser=root
+SocketGroup=root
+
+[Install]
+WantedBy=sockets.target
+Alias=docker.socket