Hetzner - DokuWiki

Docker

Inhaltsverzeichnis

Einführung

Ich wurde von einem bekannten gefragt, wie ich die Konfiguration bei [Hetzner](https://www.hetzner.de/) mit Docker genau durchgeführt. Aus dieser Diskussion ist dieser Blog Artikel entstanden, in dem ich detailliert beschreibe, wie ich diese Lösung aufgebaut habe.

Einen groben High-Überblick hatte ich ja bereits unter den folgenden Artikel zu meinen Überlegungen wurde im letzten Monat bereits unter gegeben:

http://www.vr-worlds.de/vr-worlds-de-jetzt-live-auf-shipyard-docker-und-hetzner-infrastruktur/

Auswahl eines Anbieters

Ich wollte weg von dem aktuellen Amazon Konfiguration und hin zu einer selbstgehosteten Lösung. Nach einigen prüfen verschiedener Angebote habe ich mich entschlossen es mit Hetzner(https://www.hetzner.de/) als Anbieter zu probieren, da dieser in Deutschland basiert ist und einen guten Eindruck gemacht hatte. Eine ansprechende Alternative mit ähnlichen Angeboten gab es aber natürlich auch bei 1&1 (https://www.1und1.de/). Ausschlaggebend war, das man relativ neue aber gebrauchte Server bei Hetzner mieten kann: https://serverboerse.de/index.php?country=DE

Hetznerserverboerse.png


Hier fand ich ein günstiges Angebot, dass für meine Ansprüche ausreichend war. Aus meiner bisherigen Erfahrung kann ich sagen, dass ich von Hetzner bisher nicht enttäuscht wurde.

Allerdings möchte ich nicht behaupten eine komplette Marktanalyse gemacht zu haben und kann mir durchaus vorstellen, dass es andere Anbieter mit besseren Angeboten gibt. Der Markt auch wenn man sich nur auf deutsche Anbieter beschränkt ist unüberschaubar groß.

Architektur Überlegungen Basis Betriebsystem

Als nächstes stand für mich an, welches Betriebssystem. Windows fiel dabei sehr schnell raus, da dies hohe Lizenzkosten im Monat verursacht hätte, zudem bin ich seit 1992 mit Unix (AIX) und Linux Systemen vertraut und hatte daher keine Berührungsängste.

Am Ende habe ich mich für CentOS 7.3 entschieden, da es in folgenden Punkten mich überzeugte: [1]

  • Von Hetzner unterstützt
  • Freie Verfügbarkeit
  • Hohe Stabilität
  • Aktive Community
  • Guten Enterprise Support (durch die nähe zu Red Hat Linux [2])

Die einzige ernsthafte Alternative wäre für mich noch „Debian [3] gewesen.

Auswahl.png

Überlegung Basisaufbau von Docker

Für meine Webseite habe ich folgende Basisfunktionen mir vorgestellt.

Als Dienste soll folgendes zur Verfügung stehen:

  • Ghost [4] als Blog-Service
  • ownCloud [5] als Dateispeicher, vor allem um mit Partnern und Kunden Dateien auszutauschen
  • GITLab [6] um zusammen mit Partnern an Software gemeinsam zu Entwickeln. Zudem hat es minimale Wiki und TaskPlanung, um die Projektentwicklung zu koordinieren
  • Shipyard [7] damit auch Remote eine Verwaltung der Docker Container über eine Oberfläche möglich ist.

Damit diese Dienste über einen Port (80 für HTTP bzw. 443 für HTTPS) ansprechbar sein sollen, wird NGINX [8] als Proxy verwendet.

Als Datenbank für Ghost und ownCloud soll MariaDb [9] verwendet werden. Im Schaubild stellt sich dies dann folgendermaßen dar:

Schaubild1.png

Damit das alles korrekt zusammen spielt, müssen die Komponenten in folgender Reihenfolge aufgesetzt werden:

  • Basiskonfiguration von CentOS und Installation von Docker
  • Installation von MariaDb
  • Installation von Ghost als Blog Dienst und anbinden an MariaDb
  • Installation der OwnCloud und anbinden an MariaDb
  • Installation GitLab
  • Installation der NGINX und einrichten des Proxy Routings
  • Shipyard und Einbindung in NGINX
  • Zu guter letzt natürlich noch die Firewall einschränken, damit möglichst wenig Ports offen sind.

Damit man mit der Konfiguration beginnen kann, benötigt man die folgenden beiden Tools, sofern man auf Windows arbeitet. (Wird Linux als Client verwendet müssen keine zusätzlichen Tools installiert werden, da ssh und scp bereits vorhanden sind)

  • Putty als Kommandozeile [10]
  • Und WinScp zum Hoch und Runter laden von Dateien [11]

Basiskonfiguration von CentOS und Installation von Docker

Nach der Installation von CentOS sollte zunächst ein Update durchgeführt werden:

yum -y update

Anschließend kommt die Installation von Docker

yum -y install docker docker-registry

Damit Docker auch automatisch beim neustart läuft, muss der Docker Service noch eingerichtet werden:

systemctl enable docker.service
systemctl start docker.service

Anschließend kann man prüfen, ob alles ordentlich konfiugriert ist in dem man den Status abfragt:

root@CentOS-73-64-minimal ~]# systemctl status docker.service
docker.service - Docker Application Container Engine
  Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor   preset: disabled)
  Active: active (running) since Fri 2017-03-31 22:14:56 CEST; 1 months 0 days ago
    Docs: http://docs.docker.com
Main PID: 13307 (dockerd-current)
  Memory: 107.5M
  CGroup: /system.slice/docker.service

Konfiguration der MariaDB und Einführung in Grundlegende Docker Befehle

Damit Ghost und die ownCloud auf eine zentrale Datenbank zugreifen können, muss diese als erster Container installiert werden.

Auch wenn Docker viel Arbeit abnimmt sind ein paar Vorüberlegungen zu treffen: (Es ist hilfreich sich auch die Dokumentation vom Docker Hub hierzu anzusehen [12] )

  • Welchen Namen soll die MariaDb verwenden? Ich habe „nicht perfekt leider ghost-mysql verwendet“.
  • Über welchen Port möchte man gehen? Ich habe mich entschlossen, den Standard Port 3306 zu verwenden.
  • An welcher Stelle soll die Daten abgelegt werden?
  • Wie lautet das Root Passwort?

Die Daten werden im Home abgelegt. Ein entsprechendes Data Verzeichnis wurde erzeugt:

mkdir /home/data
mkdir /home/data/MariaDb

Auf Basis dieser Überlegungen habe ich folgende Konfiguration gewählt:

  • Name: ghost-mysql
  • Datenverzeichnis nach: /home/data/MariaDb/ mappen
  • SQL Password: XXXXXXX
  • Docker Image das zu verwenden ist: mariadb

docker run --name ghost-mysql -v /home/data/MariaDb/:/var/lib/mysql:z -e MYSQL_ROOT_PASSWORD=XXXXXXX -d -p 3306:3306 mariadb

Mit „docker ps“ kann man sich nun ansehen, ob die Datenbank korrekt läuft:

[root@CentOS-73-64-minimal ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d952d2b55a4e mariadb "docker-entrypoint.sh" 3 weeks ago Up 3 weeks 0.0.0.0:3306->3306/tcp ghost-mysql

Das Verzeichnis hat auch die entsprechenden Daten der MariaDB:

Mariadb.png

Möchten Sie einen laufende Container löschen, dann können Sie das mit „docker rm“ durchführen. Sollte der Container noch laufen, kann man mit „-f“ das löschen erzwingen:

Dockerrm.png

Mit den Kommando „docker start“ kann man einen stehenden Container wieder neu starten. Mit „restart“ beenden und neu starten und mit „docker stop“ natürlich den Container beenden:

Dockerrestart.png

Sollte das Docker-Image nicht starten, kann man ggf. ohne die Detach Option „-d“ den Fehler erkennen:

Detach.png

In diesem Fall „chown“ error, hat die Option „:z“ gefehlt, damit das Verzeichnis auch korrekt gemounted wird, so wäre es korrekt:

Mount.png

Die installierten Images (also die Basisplattform für jeden Container) kann man mit „docker images“ angezeigt bekommen:

Images.png

Mit dieser Konfiguration ist es anschließend möglich auch mit bspw. HeidiSQL (https://www.heidisql.com/download.php) auf die Datenbank zugreifen zu können.

Allerdings muss man in diesen Fall (ich würde es immer nur temporär machen) die Firewall des Servers um eine Regeln bei Hetzner erweitern und die IP auf die eigene Einschränken:

Firewall1.png

Anschließend sollte es möglich sein, sich mit der mySQL/MariaDb Datenbank zu verbinden:

Mysqlconnect.png

Mit dem Kommando „docker logs ghost-mysql“ ist es möglich das Log des Container anzusehen:

Dockerlogs.png

Konfiguration von Ghost als Blog

Als nächstes ist Ghost auf der Maschine zu installieren.

Hier sind auch ein paar Grundüberlegungen durchzuführen:

  • Welcher Port ist zu verwenden? Ich habe hier auch den Standard port 2368 verwendet, der vom Internet nicht erreichbar ist (Zum testen kann man diesen öffnen, wie bei der MariaDb)
  • Der Name soll einfach „blog“ sein.
  • Und die Ablage soll natürlich auch in einem Verzeichnis für die Daten liegen. In diesen Fall haben ich „/home/data/Ghost“ gewählt.
  • Die mySQL Datenbank wird zu ghost-mysql gemapped.

Der Start von Docker beläuft sich hier dann auf:

mkdir /home/data/Ghost
docker run --name blog -p 2368:2368 -v /home/data/Ghost/:/var/lib/ghost:z -d --link ghost-mysql:mysql ghost

Auf die gesamte Konfiguration werde ich in diesem Artikel nicht eingehen, da dies ein eigener Artikel wert wäre. Ich beschränke mich hier nur auf das wesentliche, nämlich das Ghost intern auf die SQL Datenbank umgestellt werden muss, statt die interne zu verwenden:

Hier muss die Datei „config.js“ angepasst werden. Am einfachsten geht dies über WinSCP. Man kann natürlich auch „vi“ verwenden auf den Server, wenn man sich damit sicher genug fühlt:(https://scotch.io/tutorials/getting-started-with-vim-an-interactive-guide)

Configjs.png

Hier ist die Datenbank konfiguration entsprechend einzutragen. Als Hostnamen verwendet man „mysql“ da dies auch so im Docker definiert wurde. Als User habe ich „blog_user“ verwendet und ein password vergeben: (ACHTUNG: Die Konfiguration muss in "development" gemacht werden)

Editconfigjs.png

Jetzt muss noch in der MariaDb die Datenbank angelegt und der User eingerichtet werden.

Zunächst wird die Datenbank erstellt über HeidiSQL:

Createdbblog.png

Und in diesem Dialog folgendes eingeben:

Dbcreateheidi.png

Anschließend ist der User noch zu berechtigen auf der Datenbank:

Adduser1.png

Und für diesen das Passwort vergeben und alle notwendigen Rechte:

Userrights2.png

Anschließend muss der Blog neu gestartet werden, damit die neuen Konfigurationen aus der config.js gezogen werden:

Restart.png

Hat alles geklappt, dann ist der Blog wieder über „http“ verfügbar und in der MariaDb sind jetzt zahlreiche Tabellen verfügbar: (Neu laden mit F5, damit dies auch in der HeidiSQL sichtbar wird!)

Displaydbheidi.png

ownCloud und GitLab einrichten

Prinzipiell ist für diese beiden Dienste ähnlich vorzugehen, wie bereits für Ghost beschrieben.

Für die ownCloud ist auch ein User einzurichten in MariaDb, während sich das bei GitLab einfacher gestaltet. Ich fasse daher nur die wichtigsten Punkte zusammen.

Eine entsprechende Datenbank in der MariaDB anlegen:

Showdb.png

Für die ownCloud habe ich folgendes Kommando verwendet:

docker run --name owncloud -v /home/data/owncloud:/var/www/html:z -p 8082:80 --link ghost-mysql:mysql -d owncloud:8.1

Die entsprechenden Konfigurationen für die ownCloud MariaDB auch einstellen:

Configown.png

Anschließend sind in der MariaDB auch die entsprechenden Tabellen:

Dbtables.png

Für Gitlab habe ich folgendes Kommando verwendet:

docker run --detach --name gitlab --hostname git.vr-worlds.de --sysctl net.core.somaxconn=1024 --ulimit sigpending=62793 --ulimit nproc=131072 --ulimit nofile=60000 --ulimit core=0 --publish 8443:443 --publish 8083:80 --publish 8022:22 --publish 8060:8060 --restart always --volume /home/data/gitlab/config:/etc/gitlab:z --volume /home/data/gitlab/logs:/var/log/gitlab:z --volume /home/data/gitlab/data:/var/opt/gitlab:z --volume /etc/localtime:/etc/localtime gitlab/gitlab-ce

NGINX Einrichten

Nun kommt der spannende Teil des Artikels. Die NGINX soll so konfiguriert werden, dass Anfragen an den Port 80 an die entsprechenden Docker-Container durchgereicht werden. Erfolgen soll dies aufgrund der angegebenen Sub-Domain:

  • www.vr-worlds.de -> Weiterleitung zum Blog
  • cloud.vr-worlds.de -> Weiterleitung an die ownCloud
  • git.vr-worlds.de -> Weiterleitung an GitLab

Hierzu müssen zunächst alle diese Sub-Domains zur gleichen IP Adresse des Servers eingerichtet werden: (hier verwende ich leider noch Route53 (https://aws.amazon.com/route53) von AWS Amazon, da GoDaddy leider keine DE Domänen übernehmen kann (https://de.godaddy.com/help/about-de-domains-5825)).

Awsdns.png

Es kann einige Zeit dauern, bis die neuen Adressen entsprechend über DNS verfügbar sind. Man kann dies vom eigenen PC regelmäßig mit „nslookup“ prüfen:

Nslookup.png

Für die NGINX benötigen wir folgende Vorüberlegungen:

  • Welche Ports werden nach aussen gegben? Natürlich 80 (HTTP) und 443 (HTTPS) in diesen Fall
  • Wir benötigen Links zu den anderen Docker Containern: blog, gitlab, owncloud
  • Der Name soll „nginxserver“ lauten
  • Datenablage für sites-enabled, certs, logs soll im /home/data/Nginx Verzeichnissen erfolgen

Entsprechend könnte man folgendes Kommando verwenden (das wir aber nicht verwenden werden):

docker run -v /home/data/Nginx/sites-enabled/:/etc/nginx/conf.d/ -v /home/data/Nginx/certs/:/etc/nginx/certs -v /home/data/Nginx/logs/:/var/log/nginx --name nginxserver -p 80:80 -p 443:443 -d --link blog:blog --link gitlab:gitlab --link owncloud:owncloud

Da man diese Konfiguration öfters ändern muss, bspw. wenn neue Hosts hinzukommen empfiehlt es sich die Konfiguration des Docker-Containers in einer Datei abzulegen und „docker-compose“ zu verwenden. (https://docs.docker.com/compose/install/)

Die Installation erfolgt so direkt über „curl“:

curl -L https://github.com/docker/compose/releases/download/1.12.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

Docker Compose hat anschließend noch keine Ausführungsberechtigung, diese müssen mit chmod noch hinzugefügt werden: Chmodax.png

Nun können wir testen, ob „docker-compose“ korrekt funktioniert:

Testdockercompose.png

Hierzu legen wir ein Verzeichnis im Root Homeverzeichnis an und dort ein „docker-compose.yml“:

Compose2.png

Die Datei sollte wie folgt aussehen:

version: '2'
services:
 nginxserver:
   container_name: nginxserver
   image: nginx
   network_mode: bridge
   external_links:
      - blog:blog
      - gitlab:gitlab
      - owncloud:owncloud
   ports:
      - "80:80"
      - "443:443"
   volumes:
      - /home/data/Nginx/sites-enabled/:/etc/nginx/conf.d:z
      - /home/data/Nginx/certs/:/etc/nginx/certs:z
      - /home/data/Nginx/logs/:/var/log/nginx:z

Anschließend kann man mit „docker-compose“ die „nginx“ starten:

Startcompose.png

Nachdem Nginx gestartet ist muss die Konfiguration erstellt werden. Für jede Subdomain ist das durchreichen zum entsprechenden gemappten Docker Container einzutragen:

Map.png

Nachdem die Konfiguration durchgeführt wurde, kann die „nginx“ neu gestartet werden:

Restartnginx.png

Sollte es nicht funktionieren, kann „docker logs“ hier weiterhelfen: Loghelp.png

Konfiguration von Shipyard

Als letztes Element habe ich noch Shipyard hinzugefügt, damit auch remote eine Verwaltung der Docker Container möglich ist.

Die Installation ist sehr einfach und benöigt kaum überlegungen:

  • DNS soll ship.vr-worlds.de werden (Nginx Configuration ist hierfür anzupassen)

Das Deployment erfolgt hier nicht über "docker run" sondern über curl:

curl -sSL https://shipyard-project.com/deploy | bash -s

Anschließend ist shipyard über Port 8080 verfügbar und es wurde einige Container installiert:

[root@CentOS-73-64-minimal ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 48f5cd2ce123 shipyard/shipyard:latest "/bin/controller --de" 2 weeks ago Up 2 weeks 0.0.0.0:8080->8080/tcp shipyard-controller ec4955037d0f swarm:latest "/swarm j --addr 176." 2 weeks ago Up 2 weeks 2375/tcp shipyard-swarm-agent 48487fb7223c swarm:latest "/swarm m --replicati" 2 weeks ago Up 2 weeks 2375/tcp shipyard-swarm-manager fee6b7fcc71e shipyard/docker-proxy:latest "/usr/local/bin/run" 2 weeks ago Up 2 weeks 0.0.0.0:2375->2375/tcp shipyard-proxy 2058c074314b alpine "sh" 2 weeks ago Up 2 weeks shipyard-certs d710310dae40 microbox/etcd:latest "/bin/etcd -addr 176." 2 weeks ago Up 2 weeks 0.0.0.0:4001->4001/tcp, 0.0.0.0:7001->7001/tcp shipyard-discovery 0fe8eb95b8fb rethinkdb "rethinkdb --bind all" 2 weeks ago Up 2 weeks 8080/tcp, 28015/tcp, 29015/tcp shipyard-rethinkdb

Nun muss “Shipyard” nur noch in die nginx eingebunden werden und konfiguiert. In die nginx Konfiguration ist folgendes zu ergänzen: (/home/data/Nginx/sites_enabled)

SiteEnabled.png

Jetzt zahlt es sich erstmals aus über „docker-compose“ die Konfiguration für Nginx gemacht zu haben, dann diese ist nun einfach zu erweitern:

Addshipyard.png

Anschließend kann der Container neu gebaut werden mittels „docker-compose up -d“:

Compose3.png

Konfiguration über Docker-Compose zentral steuern

Damit die Automatisierung von Docker wirklich zum tragen kommt, werde ich nun die komplette Konfiguration in einem neuen Docker-Compose File zusammen führen:

Compose4.png

Die Datei hat folgendes aussehen:

version: '2.1'
services:
 ghost-mysql:
   container_name: ghost-mysql
   image: mariadb
   network_mode: bridge
   ports:
      - "3306:3306"
   volumes:
      - /home/data/MariaDb/:/var/lib/mysql:z
   environment:
      - MYSQL_ROOT_PASSWORD=rosi2511
 blog:
   container_name: blog
   image: ghost
   network_mode: bridge
   links:
      - ghost-mysql:mysql
   ports:
      - "2368:2368"
   volumes:
      - /home/data/Ghost/:/var/lib/ghost:z
 owncloud:
   container_name: owncloud
   image: owncloud:8.1
   network_mode: bridge
   links:
      - ghost-mysql:mysql
   ports:
      - "8082:80"
   volumes:
      - /home/data/owncloud:/var/www/html:z
 gitlab:
   container_name: gitlab
   image: gitlab/gitlab-ce
   network_mode: bridge
   ports:
      - "8443:443"
      - "8083:80"
      - "8022:22"
      - "8060:8060"
   volumes:
      - /home/data/gitlab/config:/etc/gitlab:z
      - /home/data/gitlab/logs:/var/log/gitlab:z
      - /home/data/gitlab/data:/var/opt/gitlab:z
      - /etc/localtime:/etc/localtime
   sysctls:
      - net.core.somaxconn=1024
   ulimits:
      sigpending: 62793
      nproc: 131072
      nofile: 60000
      core: 0
 nginxserver:
   container_name: nginxserver
   image: nginx
   network_mode: bridge
   links:
      - blog:blog
      - gitlab:gitlab
      - owncloud:owncloud
   external_links:
      - shipyard-controller:shipyard-controller
   ports:
      - "80:80"
      - "443:443"
   volumes:
      - /home/data/Nginx/sites-enabled/:/etc/nginx/conf.d:z
      - /home/data/Nginx/certs/:/etc/nginx/certs:z

Nun können wir alle Container wieder löschen und dann mit „docker-compose“ neu anlegen:

Test2.png

Konfiguration der Firewall bei Hetzner

Meine Firewall Konfiguration bei Hetzner, sieht wie folgt aus: Hetzner.png

Die Regel #1 ermögicht es, dass ICMP Packete, bspw. Ping aber auch Requests bezüglich ermitteln der Netzwerkbandbreite (MTU-Size etc.) ermittelt werden können. Es empfiehlt sich daher dies auf „accept“ stehen zu lassen.

Die Regel #2 ermöglicht es, sich auf dem Server mit ssh zu verbinden. Man muss diesen Port nicht immer auf lassen und kann diesen, wenn keine Wartung ansteht auf „discard“ stellen. Anschließend ist eine Verbindung mittels „ssh“ nicht mehr möglich und daher können „putty“ und „winscp“ sich dann nicht mehr verbinden:

Firewall2.png

Die Regel #3 ist dafür zuständige damit mittels „http“ (port 80) und „https“ (Port 443) auf das System zugegriffen werden kann.

Die Regel #4 ist notwendig, damit der Linux Host auch antworten kann. Selbstverständlich kann man die Regeln noch weiter optimieren.

Zusammenfassung

In diesem Artikel habe ich gezeigt welche Dinge im einzelnen zu tun sind, damit eine Konfiguration mit einem NGINX Proxy und ein paar anderen Container miteinander zusammen spielen. Ich hoffe das dieses recht Praxisnahe Beschreibung hilfreich ist.

Wenn Sie Unterstützung bei einer Docker Umgebung benötigen, dann kommen Sie genre auf mich zu und kontaktieren Sie mich unter christian.mueller@vr-worlds.de



© 2018. Hetzner Online GmbH. Alle Rechte vorbehalten.