Seite wählen

Poor man's Docker mit ownCloud

von | Sep 11, 2015 | Linux, Web Services

Docket basketFü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

11 Kommentare

  1. Milan

    Grossartiger Artikel, wenn ich auch den Titel etwas verwirrend finde und die User nicht mit Prozessen „integrieren“ sondern „interagieren“ koennen ;D.

    Antworten
  2. Markus Frosch

    Der Titel soll einfach sagen: Keine große Infrastruktur, ein Server, einfache Nutzung, ohne große Cloud, Kubernetes, oder irgendeine komplexe Software.

    Antworten
  3. Leo

    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?

    Antworten
  4. Markus Frosch

    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

    Antworten
  5. Christoph

    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

    Antworten
    • Markus Frosch

      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.

      Antworten
      • Christoph

        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?

        Antworten
      • Christoph

        Hab ich vergessen, das ist das Logfile vom Host des Apache!

        Antworten
  6. funkypopcorn

    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!

    Antworten
    • funkypopcorn

      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!

      Antworten

Trackbacks/Pingbacks

  1. Monthly Snap September: Tools for Graphite, OSMC and OSBConf, Poor man´s Cloud and much more › NETWAYS Blog - […] Alexander F. looked at the advantages of Perl over PHP and Python while Markus F. followed and showed us…

Einen Kommentar abschicken

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Mehr Beiträge zum Thema Linux | Web Services

CfgMgmtCamp 2024: Unser Rückblick

Vergangene Woche fuhr ein Teil unseres Teams bei NWS bis nach Ghent in Belgien, um am ConfigManagementCamp 2024 teilzunehmen. Hierbei handelt es sich um eine kostenlose Konferenz, direkt im Anschluss an die FOSDEM, was Jahr für Jahr für ein großes Publikum aus Fans...

Effektive Zugriffskontrolle für GitLab Pages

Grundlagen von GitLab Pages GitLab Pages sind eine facettenreiche Funktion, die es ermöglicht, statische Webseiten direkt aus einem GitLab-Repository heraus zu hosten. Diese Funktionalität eröffnet eine breite Palette von Anwendungsmöglichkeiten, von der Erstellung...