Für mich privat betreibe ich momentan 3 eigene Server, für WordPress, ownCloud, GitLab, E-Mail und lauter anderer Kleinkram der mich privat interessiert, oder einfach nicht in die Cloud legen möchte.
Früher habe ich von Hand einen Apache Server kompiliert, dann Pakete verstanden und genutzt, und jetzt gibt es da diese Docker… – Magie für viele.
Ich habe mich längere Zeit gefragt, wie ich, oder eine kleinere Firma effektiv mit Containern arbeiten kann. Ganz ohne eine große Cloud, und komplexe Prozesse die man erst aufbauen muss.
Eigentlich ist es ganz einfach, nur ein paar Grundregeln muss man verstehen:
- Eine Anwendung pro Container
- Mehrere Container zusammen geben eine große Anwendung
- Ggf. sorgt ein Webserver davor für Bereitstellung ans Internet, und SSL
- Der Server auf dem die Container laufen sollte eingeschränkt werden
Im folgenden möchte ich erklären wie ich meine eigene private ownCloud betreibe, vielleicht hilft es jemandem.
Mein Basis System, auf dem möglichst wenig Anderes laufen sollte:
- Debian Jessie, mit Apache und Firewall Regeln
- Docker 1.7.1
- systemd (hilft immens!)
- Partition für /var/lib/docker und /data/docker
Docker Images: mariadb (Quellen) und owncloud (Quellen)
Datenbank
Als erstes legen wir ein Datenverzeichnis an.
mkdir -p /data/docker/mariadb/data chmod 700 /data/docker/mariadb
So kann man jetzt den Docker container einfach per Hand starten:
docker pull mariadb:10 docker run \ --name mariadb # persitenter name \ -p 3306:3306 # den port oeffentlich machen (aussen:innen) (Firewall!) \ -v /data/docker/mariadb/data:/var/lib/mysql # Datenverzeichnis fuer den Tablespace \ -e MYSQL_ROOT_PASSWORD=seeehrgeheim # das feste Rootpasswort \ -it # interaktiv mit tty \ mariadb:10 # das image \ mysqld --log-bin= --binlog-format=MIXED # Startbefehl mit Optionen
Der Datenbankserver läuft jetzt im Vordergrund, man kann das Log sehen, und kann jetzt in einer 2. Sitzung selbigen einrichten:
mysql -h 127.0.0.1 -pseeehrgeheim mysql> CREATE DATABASE clouddingens; mysql> GRANT ALL ON clouddingens.* TO clouddingens@'172.17.%' IDENTIFIED BY 'auchgeheim';
Nun haben wir zwar die Datenbank, ich möchte die aber eigentlich von systemd starten lassen, also beenden wir den Server mit CTRL-C und legen ein Unitfile an:
/etc/systemd/system/mariadb.service
[Unit] Description=MariaDB database BindsTo=docker.service # Abhängigkeit und Neustart mit dem Docker Service [Service] ExecStartPre=-/usr/bin/docker kill mariadb # sicherstellen dass der Container gestoppt ist ExecStartPre=-/usr/bin/docker rm mariadb # den alten Container löschen ExecStartPre=-/usr/bin/docker pull mariadb:10 # das Image auf den neusten Stand bringen # und den Container starten ExecStart=/usr/bin/docker run --name mariadb -p 3306:3306 -v /data/docker/mariadb/data:/var/lib/mysql mariadb:10 mysqld --log-bin= --binlog-format=MIXED # den Container sanft beenden ExecStop=/usr/bin/docker stop mariadb [Install] WantedBy=multi-user.target
Mit diesem Unitfile kann systemd alles andere übernehmen:
systemctl daemon-reload systemctl start mariadb.service systemctl enable mariadb.service systemctl status mariadb.service mysql -h 127.0.0.1 -pseeehrgeheim
ownCloud
Im Prinzip funktioniert owncloud fast genau so.
mkdir -p /data/docker/owncloud/data chmod 700 /data/docker/owncloud
Die Besonderheit hier ist, dass der mariadb Container in den ownCloud Container verlinkt ist. Das sorgt für einen Hosteintrag in „owncloud„, nämlich „mysql„, damit der Container auch weiß wo seine Datenbank ist.
/etc/systemd/system/owncloud.service
[Unit] Description=ownCloud BindsTo=docker.service BindsTo=mariadb.service [Service] ExecStartPre=-/usr/bin/docker kill owncloud ExecStartPre=-/usr/bin/docker rm owncloud ExecStartPre=-/usr/bin/docker pull owncloud:8.1 ExecStart=/usr/bin/docker run \ --name owncloud \ -p 8013:80 \ --link mariadb:mysql \ -v /data/docker/owncloud/data:/var/www/html \ owncloud:8.1 ExecStop=/usr/bin/docker stop owncloud [Install] WantedBy=multi-user.target
Und wieder kann der Dienst einfach mit systemd gestartet werden:
systemctl daemon-reload systemctl start owncloud.service systemctl enable owncloud.service
Wenn man direkten Zugriff auf den Server hat kann man schon auf die ownCloud http://server:8013, dort kann mit dem Datenbank Host „mysql“, und den Zugangsdaten von oben, die Cloud schon fertig eingerichtet werden.
Apache
Auf meinem Hostsystem ist nun ein Apache eingerichtet, der die ownCloud an das Internet freigibt und mit TLS abgesichert ist.
So sieht meine Konfiguration aus:
<VirtualHost *:80> ServerAdmin webmaster@lazyfrosch.de ServerName cloud.lazyfrosch.de Redirect / https://cloud.lazyfrosch.de/ ErrorLog ${APACHE_LOG_DIR}/cloud.lazyfrosch.de_error.log LogLevel warn CustomLog ${APACHE_LOG_DIR}/cloud.lazyfrosch.de_access.log combined </VirtualHost> <IfModule mod_ssl.c> <VirtualHost *:443> ServerAdmin webmaster@lazyfrosch.de ServerName cloud.lazyfrosch.de ProxyPreserveHost On ProxyPass / http://localhost:8013/ ProxyPassReverse / http://localhost:8013/ ErrorLog ${APACHE_LOG_DIR}/cloud.lazyfrosch.de_error_ssl.log LogLevel warn CustomLog ${APACHE_LOG_DIR}/cloud.lazyfrosch.de_access_ssl.log combined SSLEngine on SSLCertificateFile /etc/ssl/cloud.lazyfrosch.de.crt SSLCertificateKeyFile /etc/ssl/private/cloud.lazyfrosch.de.key SSLCACertificatePath /etc/ssl/certs/ SSLCertificateChainFile /etc/ssl/startssl-sub.class1.server.ca.pem </VirtualHost> </IfModule>
Updates
Bei diesem Setup sind Updates relativ leicht, es reicht ein Neustart des Containers, um das aktuelle Image zu laden und zu benutzen.
Ich arbeite gerade an einem Skript um sauber festzustellen ob es ein neues Image gibt.
Hinweise zur Sicherheit
- Benutzer auf dem Hostsystem können mit Prozessen der Container integrieren, wenn die UID identisch ist, z.B. kill
- Geben sie möglichst keinem Nutzer Zugriff auf die docker Gruppe – diese Gruppe ist mit root-Rechten gleich zu setzen, besser sudo verwenden
Grossartiger Artikel, wenn ich auch den Titel etwas verwirrend finde und die User nicht mit Prozessen „integrieren“ sondern „interagieren“ koennen ;D.
Der Titel soll einfach sagen: Keine große Infrastruktur, ein Server, einfache Nutzung, ohne große Cloud, Kubernetes, oder irgendeine komplexe Software.
Hallo und danke für die Vorstellung deines Ansatzes! Ich spiele auch mit dem Gedanken meine Owncloud in Container einzupacken, da mein Wirt-System Wheezy basiert ist (und noch einige bleiben muss) und man Owncloud-Seitig langsam aber sicher auf php5.6 umsattelt.
Wheezy nutzt allerdings noch kein systemd, das heißt ich müsste mir ähnliche Skripte für sysvinit basteln, korrekt?
Wieso verwendest du einen separaten Webserver auf dem Wirt-System und konfigurierst nicht den des Owncloud Containers nach deinen Wünschen?
Hallo Leo,
1. Ich würde von Wheezy als Docker host system abraten, der Kernel ist alt, Funktionen wir btrfs, cgroups, systemd sind sehr anzuraten
2. Natürlich ist es auch möglich mit systemV zu starten, das ist aber viel gefrickel, und die Logs muss man irgendwie anders archivieren, das macht Systemd sonst für dich (Output)
3. Ich habe mehrere Container und ordentliche SSL Einstellungen, da es ein Multi-Purpose host ist bräuchte ich sonst für jeden Docker container eine eigene IP
Man könnte natürlich diesen Apache in einem Container packen, aber es taugt so ganz gut. Und die Idee ist ja die PHP Applikation zu isolieren.
Gruß
Markus
Hallo,
danke für das kleine Howto. Du hast einmal einen falschen Port (8011) angegeben.
Ich habe das jetzt probiert, erhalte aber immer folgende Meldung im Error.log des Apache:
[Thu Jul 14 08:45:55.769195 2016] [:error] [pid 1023] [client xx.xxx.xxx.xxx:58511] script ‚/var/www/html/index.php‘ not found or unable to stat
Ist ja auch logisch. Die index.php liegt ja im Container, nur wie bringe ich das dem Apache bei?
Gruß
Christoph
Oh danke für den Hinweis mit dem Port.
In welchem Apache wird dieser Fehler geloggt?
Der Weg ist ja:
Apache (mit SSL) –(proxy)–> Apache in Docker (mit PHP) -> WordPress
Der Container kopiert beim ersten Starten die WordPress Installation an Ort und Stelle, bei mir im Beispiel nach /data/docker/owncloud/data. Prüfe mal ob da auch Daten liegen.
Ich habe es mit nextcloud probiert. Er zeigt die Seite an aber wahrscheinlich ohne css. D.h. die Umleitung funktioniert teilweise! Kann ich dir einen Link per Mail zukommen lassen?
Hab ich vergessen, das ist das Logfile vom Host des Apache!
Das hört sich danach an als würde der Proxy nicht passen, kann aber auch sein dass es an diesem Bug im php Base container liegt:
https://github.com/docker-library/php/pull/255
https://github.com/docker-library/php/issues/254
Ich habe die nextcloud Container noch nicht probiert.
Sorry aber Privatsupport ist nicht kostenfrei 🙂
Hi,
erstmal danke für die super Anleitung! Mein Docker-Know-How ist gerade erst 3h alt. Also nicht erschrecken, falls der nachgelagerte Text keinen Sinn ergeben sollte. 😉
Hätte ne Frage bezgl. deinem Setup! Verstehe nicht ganz den Sinn, einem Webserver nativ auf dem Hostsystem zu betreiben bzw. davor zu schalten!
Aus einem Security-Gesichtspunkt, läuft deine owncloud dann nämlich wieder auf dem Host und nicht innerhalb des Dockercontainers, oder sehe ich das falsch? D.h. falls dein Webserver oder einer deiner Services z.B. owncloud exploitable wäre, hätte ein Angreifer direkten Zugriff auf dein /-Dateisystem und alle Containerfiles (priviledge escalaption vorausgesetzt).
Wäre es nicht besser den apachen im owncloud Container so zu konfigurieren, dass er SSL spricht. Oder aber bei mehreren Services einen eigenen Container für Apache einzurichten und ihn an die entsprechenden anderen Container, die Webserver benötigen zu linken?
Danke nochmals für die Anleitung, hat mir wirklich sehr geholfen!
ok, ich glaube ich kann meine Frage selbst beantworten 🙂 Habe wohl was in der apache-conf übersehen. Du nutzt ihn ja quasi nur als Proxy:
ProxyPreserveHost On
ProxyPass / http://localhost:8013/
ProxyPassReverse / http://localhost:8013/
Denke ich setzte das genauso um, gefällt mir ganz gut!