Hilfreiche Werkzeuge aus dem Docker-Universum

Docker – Tools und Helferlein
Kommentare

Die Popularität der Container-Virtualisierungstechnologie Docker zeigt sich auch in der schnell wachsenden Zahl von Tools und Helferlein, die um Docker herum entstehen. Diese Tools erleichtern das Arbeiten mit Docker-Images und -Containern. In diesem Artikel wird eine kleine Auswahl an Tools vorgestellt, die besonders beim Einstieg in Docker hilfreich sind.

Diese Tools erleichtern das Arbeiten mit Docker-Images und -Containern. In diesem Artikel wird eine kleine Auswahl an Tools vorgestellt, die besonders beim Einstieg in Docker hilfreich sind.

Ein sehr populäres Tool für die Installation von Docker für nicht-Linux Systeme ist boot2docker, das es ermöglicht, scheinbar wie unter Linux direkt mit Docker auf dem eigenen System, OS X und Windows zu arbeiten. Während der Arbeit mit Docker ist es manchmal sehr nützlich, in einen laufenden Docker-Container direkt hineinzuschauen. Das ermöglicht das Tool nsenter oder mit der kommenden Docker Version 1.3 der Befehl docker exec. Ist die Entwicklung eines Docker-Images abgeschlossen und soll dieses weitergegeben oder womöglich sogar in Produktion gehen, hilft docker-squash, alle Zwischenlayer aus einem Image zu entfernen. Auf diese Weise entsteht ein reduziertes und kleineres Image. Sobald eine Anwendung aus mehreren Docker-Containern besteht, müssen diese orchestriert werden. Fig ermöglicht diese Orchestrierung über eine zentrale Konfigurationsdatei und kümmert sich selbstständig um das Bauen, Starten und Verbinden der Container. Sollte man die eigenen Docker-Images nicht über den öffentlichen Docker-Hub an seine Kollegen und Mitarbeiter verteilen wollen, kann man mit docker-registry eine private Docker-Registry aufsetzen. Im Folgenden werden diese fünf Docker-Tools und Helferlein im Detail vorgestellt.

DevOps Conference 2015

DevOpsConDie neue Konferenz für Docker, Infrastructure as Code, Continuous Delivery, Cloud und Lean Business startet am 1. bis 3. Juni in Berlin. Erleben Sie spannende Erfahrungsberichte und eine Fülle an wertvollem  Praxiswissen von den bekanntesten deutschsprachigen und internationalen DevOps-Experten. Holen Sie sich jetzt den entscheidenden Wissensvorsprung für die IT Ihres Unternehmens! Alle Infos auf www.devopsconference.de.

Docker für OS X und Windows: boot2docker

Die Docker-Laufzeitumgebung besteht aus zwei Teilen: Docker-Daemon und -Client. Der Docker-Daemon verwaltet die Docker-Container und führt die Kommandos aus, die über den Client – das Kommandozeilenprogramm – docker eingegeben werden. Dazu kommunizieren Docker-Daemon und Docker-Client über Sockets. Daemon und Client müssen deshalb nicht auf demselben Rechner laufen. boot2docker macht sich diesen Umstand zu nutze, um Docker auch unter OS X und Windows laufen lassen zu können. Dafür wird im Hintergrund mit Hilfe von VirtualBox eine virtuelle Maschine mit Linux gestartet. Auf dem Wirtsbetriebssystem wird aus einem Terminal per TCP-Socket auf den Docker-Daemon in der virtuellen Maschine zugriffen. So scheint es, als würde Docker direkt auf dem lokalen System laufen. Windows-Nutzer können die virtuelle Maschine direkt über ein Terminalfenster bedienen.

Installation

Die Installation von boot2docker unter OS X und Windows wird in der offiziellen Dokumentation von Docker beschrieben – siehe hier und hier. Dort finden sich auch Links zu grafischen Installern für beide Betriebssysteme. Unter OS X kann man boot2docker auch über homebrew installieren. Docker wird dabei als Abhängigkeit automatisch installiert. Listing 1 zeigt eine gekürzte Darstellung der Installation.

> brew search docker
boot2docker  docker
> brew install boot2docker
==> Installing boot2docker dependency: go
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/go-1.3.3.yosemite.b...
==> Pouring go-1.3.3.yosemite.bottle.tar.gz
==> Installing boot2docker
==> Cloning https://github.com/boot2docker/boot2docker-cli.git
==> Checking out tag v1.3.0
==> go get -d
==> make goinstall

Initialisierung und Starten

Der erste Schritt nach der Installation von boot2docker ist die Initialisierung, die die aktuellen Images für die virtuelle Maschine lädt:

> boot2docker init
Latest release for boot2docker/boot2docker is v1.3.0
Downloading boot2docker ISO image...
Success: downloaded https://github.com/boot2docker/boot2docker/releases/download/v1.3.0/boot...
	to /Users/lukas/.boot2docker/boot2docker.iso

Nun kann man ähnlich wie bei Vagrant die virtuelle Maschine mit boot2docker up starten.

> boot2docker up
Waiting for VM and Docker daemon to start...
........................oooooooooooooooooooo
Started.
Writing /Users/lukas/.boot2docker/certs/boot2docker-vm/ca.pem
Writing /Users/lukas/.boot2docker/certs/boot2docker-vm/cert.pem
Writing /Users/lukas/.boot2docker/certs/boot2docker-vm/key.pem

To connect the Docker client to the Docker daemon, please set:
    export DOCKER_HOST=tcp://192.168.59.103:2376
    export DOCKER_CERT_PATH=/Users/lukas/.boot2docker/certs/boot2docker-vm
    export DOCKER_TLS_VERIFY=1

boot2docker nutzen

Läuft die virtuelle Maschine von boot2docker, kann man mit Docker loslegen. Dafür ist es jedoch notwendig, dem Docker-Client das oben beschriebene Socket sowie die Verschlüsselungsoptionen mitzuteilen. Dies kann man über die Umgebungsvariablen DOCKER_HOST, DOCKER_CERT_PATH und DOCKER_TLS_VERIFY machen – siehe die letzten drei Zeilen in der Ausgabe oben oder durch eval $(boot2docker shellinit). Über den Kommandozeilenparameter -H kann man den Socket auch direkt an docker übergeben. Den Pfad zu Zertifikaten kann man über die Parameter –tlscacert, –tlscert und –tlskey festlegen und die Verifizierung über –tlsverify.

> alias docker='docker -H tcp://192.168.59.103:2376'
> docker run ubuntu:14.04 /bin/echo 'Hello world'
Unable to find image 'ubuntu:14.04' locally
Pulling repository ubuntu
826544226fdc: Download complete
511136ea3c5a: Download complete
b3553b91f79f: Download complete
ca63a3899a99: Download complete
ff01d67c9471: Download complete
7428bd008763: Download complete
c7c7108e0ad8: Download complete
Hello world

Portweiterleitungen

Der Docker-Daemon-Host ist die virtuelle Maschine. Das heißt, dass alle Ports von Docker-Containern auf dem Gast- und nicht auf Wirtssystem veröffentlicht werden. Mit Hilfe von boot2docker ip kann man aber leicht die aktuelle, von der virtuellen Maschine für boot2docker genutzten IP-Adresse einsehen und sich so zu den Docker-Containern verbinden:

> docker run -d --P --name web nginx
> docker ps
CONTAINER ID        IMAGE               PORTS                   NAMES
d9064b318573        nginx:latest        0.0.0.0:49154->80/tcp   web
> curl http://localhost:49154
curl: (7) Failed connect to localhost:49154; Connection refused
> curl http://$(boot2docker ip 2> /dev/null):49154
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
…
</html>

Mehr zu boot2docker

Die GitHub-Seite von boot2docker zeigt weitere Details des Tools, das auch für Windows- und Linux-Benutzer interessant ist. Besonders detailliert wird in “How to Use Docker on OS X: The Missing Guide“ auf die Installation und mögliche Probleme samt Lösungen mit boot2docker eingegangen.

Eintritt in den Container: nsenter

Manchmal ist es notwendig, in einen laufenden Docker-Container hineinzuschauen, um zum Beispiel Logdaten einzusehen oder Änderungen am Container zu machen. Hierfür ist nsenter aus den Linux Kernel Utils gedacht.

Installation

nsenter ist seit Version 2.23 Teil der Linux Kernel Utils. Leider ist diese Version noch nicht in allen populären Distributionen angekommen, so dass man sich nicht der entsprechenden Paketmanager bedienen kann. So bleibt erst einmal nur das Selbstkompilieren. Wenn man jedoch Binarys von GitHub traut, so kann man der Anleitung folgen, die einen Docker-Container nutzt, um nsenter auf dem eigenen System unter /usr/local/bin zu installieren.

> docker run --rm -v /usr/local/bin:/target jpetazzo/nsenter
Anschließend sollte man das gerade ausgeführte Docker Image löschen:
> docker rmi jpetazzo/nsenter

nsenter nutzen

Einmal installiert, gelangt man mit folgenden Befehlen zunächst an die PID eines Containers und kann anschließend in dessen Kontext eintreten:

> PID=$(docker inspect --format {{.State.Pid}} <container_name_or_ID>)
> nsenter --target $PID --mount --uts --ipc --net —pid
root@6685573a2db7:~#

Folgt man der Installation von nsenter über das oben erwähnte Repository, so wird gleichzeitig zu nsenter das kleine Shellskript docker-enter installiert, das die beiden oberen Schritte zu einem einzigen Kommando verbindet. Es erleichtert damit das Eintreten in einen Container.

Es gibt noch mehr

Es gibt noch weitere Tools und Möglichkeiten, in einen Docker Container hineinzuschauen. Die verschiedenen Wege werden in hier ausführlich vorgestellt. Darüber hinaus bietet Docker 1.3 das Kommando docker exec.

Docker Images zusammenquetschen: docker-squash

Jedes Kommando eines Dockerfiles löst einen Commit aus und somit einen neuen Layer auf das gestapelte Dateisystem eines Docker-Images hinzufügt. Dies ist ein sinnvoller Mechanismus, der Wiederwendung und leichte Änderungen ermöglicht. Schließlich muss nicht das ganze Image neu gebaut werden, wenn man nur eine Datei ändern will. Es genügt, die Datei zu ändern und einen weiteren Layer hinzuzufügen. Führen diese Änderungen jedoch dazu, dass viele Dateien geändert werden oder gar nicht mehr benötigte Dateien gelöscht werden, so wächst das Image über seine Layer weiter an, obwohl eigentlich Dateien entfernt werden. Ein Beispiel hierfür ist das Übersetzen eines Programms aus seinem Quellcode, nachdem die Quellen nicht mehr benötigt und entfernt werden sollen. docker-squash bietet hier einen Ausweg, indem es ermöglicht, ein Docker-Image von allen Zwischenlayern zu befreien. Es geht dabei intelligent vor, indem es nur die Layer zwischen dem ersten Basisimage und dem letzten Image entfernt. Auf diese Weise wird weiterhin vom Basisimage abgeleitet – es muss bei einem docker push oder docker pull nicht übertragen werden – und alle Dockerfile-Laufzeitkommandos wie ENV, CMD, etc. bleiben erhalten.

Installation

Die Installation gestaltet sich recht einfach, setzt jedoch GNU tar in Version 1.27 oder neuer voraus. Dies ist zum Beispiel unter Ubuntu 14.04. gegeben.

> wget https://github.com/jwilder/docker-squash/releases/download/v0.0.8/docker...
> sudo tar -C /usr/local/bin -xzvf docker-squash-linux-amd64-v0.0.8.tar.gz

docker-squash nutzen

Anschließend kann man docker-squash auf seine Images anwenden. Der Workflow ist hierbei stets derselbe. Zunächst muss man das gewählte Image über docker save in eine Datei speichern. Anschließend reduziert man die Layer mit docker-squash. Hierbei muss docker-squash als root ausgeführt werden, so dass die Dateirechte erhalten bleiben. Anschließend kann man mit docker load das reduzierte Image wieder laden und mit docker tag einen Namen vergeben:

> docker save <image id> > image.tar
> sudo docker-squash -i image.tar -o squashed.tar
> cat squashed.tar | docker load
> docker images 
	<new image id>
> docker tag <new image id> <name>

Weitere Details zu docker-squash findet man hier.

[ header = Seite 3: Docker-Container orchestrieren: fig ]

Docker-Container orchestrieren: fig

Docker-Container miteinander zu verbinden, um so einzelne Dienste in Container einzusperren, ist eine Standardanwendung von Docker. Beispielsweise könnte man einen Webserver mit einer MongoDB-Instanz verbinden wollen und dafür jeweils einzelne Container nutzen. Dieser Blogpost beschreibt, wie das für dieses Beispiel funktioniert. fig nimmt einem Entwickler die Arbeit des manuellen Vernetzens ab, indem über eine einzige Konfigurationsdatei die Interaktion der Container beschrieben wird. Den Rest, also das Erstellen der Images, das Starten der Container und das Vernetzen, übernimmt fig anhand dieser Datei.

Installation

Die Installation von fig ist einfach. Es genügt, mit Hilfe des Python-Paketmanagers pip fig über das Kommando pip install fig zu installieren. pip ist in allen gängigen Linux-Distributionen enthalten. Sollte fig nach der Installation mit Python-Tracebacks fehlschlagen, hilft häufig das Kommando sudo pip install –upgrade distribute.

fig nutzen

fig wird über ein Konfigurationsdatei im YML-Format gesteuert. Listing 2 zeigt die entsprechende fig-Konfiguration für das oben erwähnte Beispiel aus Webserver und MongoDB — das vollständige Beispiel ist bei GitHub zu finden.

webserver:
  build: webserver
  ports:
    - "8080:8080"
  command: /bin/bash -c "/opt/webserver/webserver.py 8080 $MONGO_1_PORT_27017_TCP_ADDR $MONGO_1_PORT_27017_TCP_PORT"
  links:
    - mongo

mongo:
  build: mongodb

Es werden zunächst zwei Docker-Container webserver und mongo definiert, deren Dockerfiles sich gemäß der build-Anweisung in den Verzeichnissen webserver bzw. mongodb befinden müssen. Für den Webserver wird der interne Port 8080 auf den externen Port 8080 veröffentlicht. Über die links-Anweisung wird über docker link die Verbindung zum mongo-Container hergestellt. Dazu werden die Variablen MONGO_1_PORT_27017_TCP_ADDR und MONGO_1_PORT_27017_TCP_PORT automatisch aus dem veröffentlichten Port 27017 des mongo-Containers abgeleitet und gesetzt. Diese Variablen können dann in der command-Anweisung des webserver-Containers genutzt werden, um das Python-Skript des Webservers entsprechend zu parameterisieren. Listing 3 zeigt dafür das Dockerfile des mongodb-Images. Darin ist zu sehen, dass der Port 27017 veröffentlicht werden soll.

# Dockerfile for mongodb
# Version 1.0
FROM lukaspustina/docker_network_demo_base

MAINTAINER Lukas Pustina <lukas.pustina@codecentric.de>

RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10 && echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | tee /etc/apt/sources.list.d/mongodb.list
RUN apt-get update; apt-get install -y mongodb-10gen

VOLUME ["/data/mongodb"]

EXPOSE 27017

ENTRYPOINT ["/usr/bin/mongod"]
CMD ["--port", "27017", "--dbpath", "/data/mongodb", "--smallfiles"]

Über die Kommandozeilenbefehle fig build und fig up werden zunächst die Images gebaut und anschließend gestartet (Listing 4).

> fig build
…
> fig up -d
Creating figdemogit_mongo_1...
Creating figdemogit_webserver_1...
Attaching to figdemogit_mongo_1, figdemogit_webserver_1
mongo_1     | Tue Sep  9 12:27:52.404 [initandlisten] MongoDB starting : pid=1 port=27017 dbpath=/data/mongodb 64-bit host=c2723a73972f
…
mongo_1     | Tue Sep  9 12:27:52.772 [initandlisten] connection accepted from 172.17.0.49:50404 #1 (1 connection now open)
webserver_1 | 2014-09-09 12:27:52,772 Started
…

Der Parameter -d sorgt dafür, dass die Container im Hintergrund laufen – die Ausgabe wird dann nicht angezeigt, sondern dient hier nur zur Anschauung. Nun kann man auf den Webserver über Port 8080 zugreifen. Falls man boot2docker einsetzt sieht das zum Beispiel so aus:

> curl -X POST -H "Content-Type: application/json" -d '{"name":"James Clerk Maxwell","birthday":"13.06.1831"}' http://$(boot2docker ip 2> /dev/null):8080
> curl http://$(boot2docker ip 2> /dev/null):8080
name = James Clerk Maxwell, birthday = 13.06.1831

Mit fig ps behält man die aktuellen Docker-Container im Auge. Herunterfahren lässt sich das Docker-Netzwerk mit fig stop.

Es gibt noch mehr

fig unterstützt noch sehr viel mehr Kommandos und Optionen. Spannend ist insbesondere die Möglichkeit, mit fig scale einzelne Container eines Netzwerkes zu skalieren und so mehrere Instanzen eines Images zu starten. Wie bei boot2docker wertet fig die Umgebungsvariable DOCKER_HOST aus, so dass man mit fig Docker lokal, in boot2docker oder sogar remote auf einem entfernen Host Docker-Container orchestrieren kann.

Der private Docker Hub: docker-registry

Der Docker-Hub ist die zentrale und öffentliche Registry für Docker-Images. Es ist somit das Pendant zu öffentlichen Repositorys bei GitHub für Docker-Images. Es gibt zahlreiche Gründe, warum es sinnvoll ist, seine eigenen Images nicht zu veröffentlichen, zum Beispiel weil sie Zugangsdaten oder Geschäftsgeheimnisse beinhalten. docker-registry ist ein von Docker geführtes Projekt, dass es erlaubt eine eigene, private Docker Registry zu betreiben.

Installation

Gemäß dem Motto “eat your own dog food” ist der einfachste Installationsweg, die Docker-Registry als Docker-Image direkt vom Docker-Hub zu ziehen – die zur Zeit aktuelle Version ist 0.8.1:

> docker pull registry:0.8.1

docker-registry nutzen

Um die eigene Docker-Registry zu erstellen, genügt es docker run registry auszuführen und so einen Testbetrieb zu starten. Für einen Produktivbetrieb ist es jedoch sinnvoll, das Storage-Backend für die Images sowie den veröffentlichten Port anzugeben. Dies lässt sich über Umgebungsvariablen steuern. So kann man zum Beispiel das Storage-Backend wie folgt auf Amazon S3 und den Port auf 5000 konfigurieren. Das Suchbackend wird hierbei mit dem Python ORM SQLAlchemy angebunden:

> docker run 
         -e SETTINGS_FLAVOR=s3 
         -e AWS_BUCKET=acme-docker 
         -e STORAGE_PATH=/registry 
         -e AWS_KEY=AKIAHSHB43HS3J92MXZ 
         -e AWS_SECRET=xdDowwlK7TJajV1Y7EoOZrmuPEJlHYcNP2k4j49T 
         -e SEARCH_BACKEND=sqlalchemy 
         -p 5000:5000 
         registry

Dieses Beispiel bezieht sich auf das Flavor S3 aus der Beispielkonfiguration des Docker-Images für die Registry. Flavors erlauben es, unterschiedliche Laufzeitkonfigurationen in einer Konfigurationsdatei zu speichern und sie beim Start – wie im obigen Beispiel – über die Umgebungsvariabel SETTINGS_FLAVOR auszuwählen. Ein Auszug aus der Beispielkonfigurationsdatei findet sich in Listing 5. Das Format der Datei ist YML und alle Schlüssel können über Umgebungsvariablen angepasst werden. Der Flavor local setzt das Storage-Backend auf ein lokales Verzeichnis.

# All other flavors inherit the `common' config snippet
common: &common
   loglevel: _env:LOGLEVEL:info
   debug_versions: _env:DEBUG_VERSIONS:false

local: &local
   <<: *common
   storage: local
   storage_path: _env:STORAGE_PATH:/tmp/registry

s3: &s3
   <<: *common
   storage: s3
   s3_region: _env:AWS_REGION
   s3_bucket: _env:AWS_BUCKET
   boto_bucket: _env:AWS_BUCKET
   storage_path: _env:STORAGE_PATH:/registry
   s3_encrypt: _env:AWS_ENCRYPT:true
   s3_secure: _env:AWS_SECURE:true
   s3_access_key: _env:AWS_KEY
   s3_secret_key: _env:AWS_SECRET

Man kann natürlich die Konfigurationsdatei austauschen, indem man ein eigenes Dockerfile benutzt und darin die Umgebungsvariable DOCKER_REGISTRY überschreibt und auf eine eigene Konfigurationsdatei verweisen lässt. Listing 6 zeigt ein Bespiel dafür.

FROM registry:0.8.1
MAINTAINER Lukas Pustina <lukas.pustina@codecentric.de>
ADD config.yml /etc/docker/
env DOCKER_REGISTRY_CONFIG /etc/docker/config.yml
cmd exec docker-registry

Es gibt noch mehr

Die Docker-Registry bietet über die hier gezeigten Basisfunktionalität hinaus noch weitere nützliche Funktionen, wie weitere Storage-Backends, Indizierung der gespeicherten Images, etc. Es lohnt sich deswegen, einen Blick auf die GitHub-Seite des Projekts zu werfen.

Das war noch längst nicht alles

Die fünf in diesem Artikel vorstellten Tools und Helferlein sind nur die Spitze des Eisbergs eines ständig wachsenden Ökosystems rund um Docker. DockerUI, ein junges und noch nicht ganz stabiles Projekt, das eine WebUI für Docker-Container entwickelt, ist beispielsweise definitiv einen Blick wert. Um einen Eindruck vom Ressourcenverbrauch von Containern zu bekommen, kann man cadvisor ausprobieren. Mit Flynn, Deis und Dokku gibt es weitere Projekte, die aufbauend auf Docker einen Platform as a Service ähnlich zu Heroku schaffen wollen. CoreOS ist eine Linux-Distribution, die speziell auf das Betreiben von Docker-Containern ausgelegt ist. In eine ähnliche Richtung stößt Project Atomic. Eine spannende Neuentwicklung zur Orchestrierung von Docker-Containern ist Kubernetes von Google. Ein Projekt, das den gesamten Lebenszyklus von Docker-Containern samt Orchestrierung, UI und eigener Registry beinhaltet ist Panamax. Es gibt jedoch noch viel mehr zu entdecken – viel Spaß dabei!


Inside Docker: Wenn Sie mehr über Docker wissen möchten, empfehlen wir Ihnen das Entwickler Magazin Spezial Vol. 2: Docker zum leichten Einstieg in die Container-Virtualisierung.

docker-coverMit Docker feiern Linux-Container momentan ein eindrucksvolles Comeback. Während der Einsatz von virtuellen Maschinen viele Vor-, aber auch zahlreiche Nachteile mit sich bringt, ist Docker eine leichtgewichtige, containerbasierte Alternative, die die System-Level-Virtualisierung auf ein neues Level hebt. Dabei ergänzt Docker das Deployment von Betriebssystemen und Webanwendungen um die Lösungen, die man beim Original schmerzlich vermisst. In diesem Jahr hat Docker eine hohe Dynamik entwickelt und wird in allen aktuellen Linux-Distributionen wie Redhat, SUSE oder Ubuntu ausgeliefert. Firmen wie Spotify, Google, BBC, eBay und seit kurzem auch Zalando setzen Docker bereits produktiv ein. Das Entwickler Magazin Spezial „Docker“ informiert kompetent über diese revolutionäre Technologie, von der viele meinen, dass sie eine neue Ära in der IT einläuten wird. Wir erklären technische Hintergründe, demonstrieren Best Practices und zeigen, wie Docker effektiv eingesetzt werden kann. Das Sonderheft vereint umfangreiches Wissen über die wichtigsten Aspekte von Docker, spannende Ideen für eigene Docker-Projekte und wertvolle Impulse für ihre strategische Planung.
Aufmacherbild: shipping container yard closeup in shanghai seaport von Shutterstock / Urheberrecht: chungking
Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -