Posts tagged Docker

I played with CHICKEN Scheme, Docker and Alpine Linux

:: IT, Lisp, Scheme, CHICKEN, Docker, Linux

I am looking forward to meet LISP people at the 32c3’s LISP assembly. The last days I played a bit with different Scheme implementations including CHICKEN scheme. The main feature of CHICKEN is that it compiles the Scheme code to C and then creates dynamic libraries and binaries with the C compiler. I thought that combining these binaries with a minimal Docker container could give me a very small deployment. So here are my steps:

Choosing Alpine Linux as a “small” Linux

The smallest Linux image for Docker is undoubtly busybox with a size of about 2.489 MB. But busybox lacks a package manager which makes installing software painful. Therefore I have chosen Alpine Linux which comes with package manager and it’s image’s size is about 5.234 MB. That’s double the size of the busybox image but still quite small compared to the Ubuntu image which is about 266 MB.

Creating a Docker container with CHICKEN

Alpine Linux comes with the musl libc and I thought it would be best to compile all the CHICKEN stuff with that libc. Therefore I created a Docker container with gcc and all the other stuff with this Dockerfile (Github repository):

FROM alpine:3.2

RUN apk update && apk add make gcc musl-dev 
RUN wget -O - http://code.call-cc.org/releases/4.10.0/chicken-4.10.0.tar.gz | tar xz

WORKDIR /chicken-4.10.0

RUN make PLATFORM=linux && make PLATFORM=linux install

RUN rm -fr /chicken-4.10.0 

WORKDIR /

CMD ["csi"]

This image is quite big (about 161.7 MB) and is available for download at the Docker Hub.

Compiling some CHICKEN code

For testing purposes I wanted a minimal web server running in the Alpine Linux image. Therefore I looked through the egg index and found spiffy. I fired up the chicken-alpine container (but I used ash as command instead of the csi Scheme interpreter) and created a small web server that serves some static pages. I wrote a main.scm:

(use spiffy)
(start-server)

and added some static pages to a ./web sub-directory. Then everything had to be compiled and prepared for deployment:

chicken-install spiffy
csc -deploy main.scm
chicken-install -deploy -p $PWD/main spiffy

Deploy in a fresh Alpine Linux image

After the compilation I copied the main and web directories on my host machine using docker cp and created the following Dockerfile:

FROM alpine:3.2

ADD main /main
ADD web main/web
WORKDIR main

CMD /main/main

and let docker build -t krrrcks/spiffy-test . do the job. The size of the resulting image is about 12.37 MB and that’s pretty small. I uploaded that image to the Docker Hub as well.

To serve the pages I did a docker run -d -p 8080:8080 krrrcks/spiffy-test (spiffy listens on port 8080 in the default install) and browsed my static pages.

  1. Docker-Meetup in Frankfurt

:: IT, Docker, Veranstaltungen

Am 13. Januar 2015 fand in Frankfurt das bereits dritte Docker-Meetup statt, hier einige Notizen von mir dazu.

Neues zum Them Orchestrierung

Peter Rossbach hat in einem munteren Vortrag einige Neuerungen aus dem “Docker Universum” zum Thema Orchestrierung vorgestellt. Unter anderem Docker Machine, Docker Swarm, Docker Compose (ehemals fig.sh, das wohl aufgrund von Aussprachemehrdeutigkeiten umbenannt wurde) etc. Ein sehr interessanter Überblick, insbesondere da Peter auch die ganzen Sachen immer mal angefasst und ausprobiert hat. Im Kern scheint es mir jedoch so zu sein, als wäre die Frage nach “Was nimmt man am besten, um Docker auf einer oder mehreren Maschinen im Produktivbetrieb zu nutzen?” noch recht in Bewegung. Für mich kristallisiert sich für meine Anwendungsfälle da bisher noch keine überzeugende Lösung heraus. Was ich jedoch einmal testen werde ist das fig.sh bzw. Docker Compose, da man damit eigentlich sehr schön in einem YAML-Dokument mehrere Container und ihre Abhängigkeiten darstellen kann.

Docker Linking

Erkan Yanar hat in einem Einsteigervortrag die Grundlagen von Links zwischen Containern vorgestellt. Hier scheint die Entwicklung auch noch in Bewegung zu sein, insbesondere Links über mehrere Hosts hinweg scheinen doch noch nicht so ganz einfach handzuhaben zu sein (vorgestellt wurden Ambassador-Ansätze mit socat und anderes).

Besonders erhellend fand ich den Hinweis, dass ab Docker Version 1.3 nun bei Links zwischen den Containern die /etc/hosts auch nach Neustarts von gelinkten Containern immer deren richtige IP-Adresse erhält, wohingegen die Umgebungsvariablen nur die Ursprungs-IP-Adressen enthalten (also ein klares “Verlasst Euch nicht auf die Umgebungsvariablen!”).

Netzwerken mit Docker

Andreas Schmidt stellte eine ganze Reihe von Varianten vor, mit denen man die Container im Netzwerk auf unterschiedliche Arten und Weisen verknoten kann. Soweit ganz interessant, aber nicht meine “Liga”, wo ich mich gut auskenne.

Fazit

Bei Docker in Bezug auf Orchestrierung und Container-Linken gibt es recht viel Bewegung und für mich kristallisieren sich die überzeugenden Konzepte noch nicht so richtig heraus, um damit in eine Produktivumgebung zu gehen. Im Bereich der Entwicklung und der Tests nutze ich die Container von Docker schon recht gerne, bei Produktiv-Umgebungen schreckt mich die Vielzahl an Werkzeugen und zum Teil auch die Komplexität doch noch etwas.

Jedenfalls wieder ein gutes Meetup mit Ideen und Anregungen. Ich finde das schon sehr außergewöhnlich (besonders wenn man es mit anderen Branchen vergleicht), dass sich Leute zum Austauschen über Technologie treffen, Vorträge vorbereiten etc.

Erfahrungen mit Docker

:: Docker

Ein Bekannter bat mich, einmal von meinen Erfahrungen mit Docker zu berichten. Also hier als Blog-Post dazu. Ich werde nicht beschreiben, was genau Docker ist und wie es funktioniert. Hierzu gibt es mittlerweile schon eine Reihe von guten Quellen (bspw. auf der Docker-Homepage, in der c’t war in Heft 17 (Seiten 146–151) auch eine ganz gute Einführung enthalten).

Hintergrund

Seit einigen Jahren verwende ich zum Ausrollen von Software OpenVZ als Container-Lösung. Das funktioniert sehr gut, schont die Ressourcen, lässt sich gut verwalten und überwachen. In den OpenVZ-Containern befindet sich ein kleines Linux der gewünschten Distribution mit so allem, was man im Standard dafür erwartet. Darin installiert und konfiguriert man seine Software und rollt sie dann auf dem Zielsystem bequem aus. Der einzige Nachteil hierbei ist, dass der Host einen eigenen OpenVZ-Kernel benötigt, da nicht oder noch nicht alle Features im Standard-Kernel bereit stehen. Das macht das Zusammenstellen auf meinem Notebook etwas schwierig, denn dort habe ich den OpenVZ-Kernel in der Regel nicht installiert.

Warum nun Docker?

Im April bin ich eher zufällig (tauchte in den Release-Notes von Ubuntu 14.04 auf) auf das Docker-Projekt gestoßen und habe damit begonnen herumzuexperimentieren.

Rund um Docker und den Einsatz haben sich eine Vielzahl von Projekten angesammelt. Nicht alles verstehe ich auf Anhieb und mir fällt es zum Teil auch schwer, die unterschiedlichen Projekte zum Ausrollen, Verwalten etc. zu bewerten und zu entscheiden, was davon auch “zukunftsfähig” ist. Wahrscheinlich muss man hier auch ein bisschen Geduld haben.

Einsatzbereiche

Für mich haben sich im Wesentlichen zwei Haupteinsatzbereiche herauskristallisiert: * als Werkzeug in der Software-Entwicklung und * als Werkzeug zum Ausrollen und dauerhaften Betrieb von Anwendungen

Werkzeug in der Software-Entwicklung

Ich arbeite in Teams zusammen, bei denen die Entwickler mal nen Windows-Notebook und mal nen Linux-Notebook ihr Eigen nennen. Docker bot sich hier an, eine definitierte Test- und Entwicklungsplattform bereit zu stellen. Ich habe dazu alles, was man so braucht in ein Image zusammengeworfen, dies lässt sich mit dem aktuellen Source Code starten.

Dauerhafter Betrieb

Eigenarten und Erfahrungen

Was toll ist:

  • Sehr leicht zu installieren und man kann schnell damit anfangen herumzuspielen.
  • docker build / Dockerfile
  • Es entwickelt sich sehr schnell eine aktive Gemeinschaft, so habe ich auch schon an MeetUps in Frankfurt und Darmstadt mit Gewinn teilgenommen.
  • Nicht zu vergessen das Logo.

Was nicht so toll ist:

  • Images und Container erhalten zur Identifikation Hash-Werte; man kann Images und Container auch mit Namen versehen. Ist man allerdings ein wenig am experimentieren und herumbasteln, so sammeln sich schnell eine Reihe von Containern mit wenig sprechenden Ids an und zumindest ich verliere da schnell den Überblick.

  • Eigentlich sind die Container nicht so mobil, wie die Analogie es vermuten lässt. Am ehesten sind es noch die Images, die man in eine Registry einspielen und dann auf unterschiedlichen Systemen herunterlädt. Mir würde allerdings auch so etwas wie Live Migration (funktioniert beispielsweise bei OpenVZ für meine Einsatzzwecke ganz hervorragend) gefallen.

  • Für den dauerhaften Betrieb gibt es eine Reihe von für mich offenen Fragen. Hierzu gibt es zwar Lösungsansätze oder Produkte, aber viele entwickeln sich erst. Ich will einmal exemplarisch einige offene Enden herausgreifen:

  • Irgendwie muss man sich um seine Logfiles kümmern, wo die so landen sollen. Hat man in einem “normalen Linux” (oder auch einem Standard-OpenVZ-Container) meist so etwas wie ein logrotated am laufen, so fehlt das (wenn man der Docker-Philosophie folgt, die Container so schlank wie möglich zu halten) in einem Docker-Deployment. Also muss man für jede Anwendung prüfen: Schreibt sie ihr Log auf Platte? Dann muss man das da irgendwie herausholen (bspw. über einen Log-File-Volume) oder überwachen, nutzt sie syslogd muss man das auch irgendwie in den Griff bekommen oder rotzt sie ihre Meldungen über die Standardausgabe heraus, dann sammelt immerhin Docker die auf und man kann darin blättern (die können dort aber auch recht groß werden).

  • Was tut man mit persistenten Daten? Also beispielsweise einer Datenbank? Der Docker-Weg-zum-Glück bietet an, dass man einen Container mit der Datenbank erstellt und dann einen für die jeweilige Anwendung (ist bspw. für das Wordpress-Image auch so gut zu studieren). Damit die Daten der Datenbank nicht in dem Container herumliegen, kann man diese noch in ein Volume packen. Damit die beiden Container nun miteinander kommunizieren können, kann man deren Daten über Links einander bekannt machen. Da man sich als Container und Anwendung nicht um IP-Adressen etc. kümmern “soll”, ist das auch ganz fein. So erhält man im Anwendungscontainer dann Umgebungsvariablen zum Datenbankcontainer sowie auch einen Eintrag in /etc/hosts. Dumm nur, wenn der Datenbankcontainer mal abschmiert und neu gestartet werden muss, denn dann erhält er in der Regel eine neue IP-Adresse und der Link vom Anwendungscontainer zur Datenbank funktioniert nicht mehr. Sicher, es gibt nun Mittel und Wege damit umzugehen (DNS-Geschichten, Entdecken der Dienste, etc.), aber ich fände es eigentlich toll, wenn das Out-of-the-box funktionieren würde.

Fazit

Ich finde es ein spannendes Projekt und wenn sich für mich die einen oder anderen Unklarheiten lichten, werde ich es sicherlich auch für den Produktiveinsatz in Erwägung ziehen. Ich vermute, dass das Projekt sich noch deutlich weiterentwickeln wird, die knapp 65 Mio Venture Capital werden neben Marketing hoffentlich auch ins Produkt gesteckt.

Mind the storage driver for Ubuntu cloud images (on Azure)

:: Azure, Docker, IT

A few days ago I wanted to build Firefox OS’ newest release for a friend. Because I did not wanted these GB of code, binaries etc. on my notebook I fired up an Ubuntu image on Microsoft Azure. I feared that at a certain point in the build process I may had to download everything to my local machine and therefore I installed Docker via a simple

sudo apt-get install docker.io

Then I started the build process as laid out on Mozilla’s Developer Network. But, during downloading the source code (that’s about 12 GB of Git repositories from Mozilla and Android), I got a “no more space left on device”. That was strange: I had a 100 GB volume attached to the VM and enough space and inodes left. After some searching I asked on the IRC channel and got a good hint: “What’s your storage driver?”

Well, I thought that it’s AUFS; I wanted to add “as usual” because AUFS was available on my notebook from the beginning. But a docker.io info gave me:

$ sudo docker.io info
Containers: 0
Images: 0
Storage Driver: devicemapper
 Pool Name: docker-8:1-131188-pool
 Data file: /var/lib/docker/devicemapper/devicemapper/data
 Metadata file: /var/lib/docker/devicemapper/devicemapper/metadata
 Data Space Used: 291.5 Mb
 Data Space Total: 102400.0 Mb
 Metadata Space Used: 0.7 Mb
 Metadata Space Total: 2048.0 Mb
Execution Driver: native-0.1
Kernel Version: 3.13.0-29-generic
WARNING: No swap limit support

I then learned that somehow the DeviceMapper driver only allows a certain amount of diffs and I reached that amount with my build process. (Maybe it’s possible to relax that restriction but I do not know how.)

I learned as well that the Ubuntu cloud image that is provided by Microsoft Azure doesn’t have AUFS support. Therefore Docker uses the DeviceMapper storage driver instead. After I installed the AUFS support I could export the images, change the storage driver and import the images again.

It would be nice seeing the Docker documentation being more detailed on those storage drivers.

(Update 2014–10–23) Thanks to this blog post from Iron.io I found some documentation of the devicemapper storage driver. It is located in the Repository.

Unicode support for Octopress

:: Docker, Octopress, IT

Well, it seems Octopress/Jekyll would like to have a locale set for UTF–8 support. I followed this (text in German) hint and now my Dockerfile looks like this:

# dockerfile for octopress

FROM ubuntu:14.04
MAINTAINER krrrcks <krrrcks@krrrcks.net>
ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update; \
  apt-get -q -y upgrade
RUN /usr/sbin/locale-gen en_US.UTF-8; \
  update-locale LANG=en_US.UTF-8
RUN apt-get -q -y install git curl; \
  apt-get clean
RUN git clone git://github.com/imathis/octopress.git /opt/octopress
RUN curl -L https://get.rvm.io | bash -s stable --ruby
ENV HOME /root
RUN echo "export LC_ALL=en_US.UTF-8" >> /root/.bashrc
RUN echo "export LANG=en_US.UTF-8" >> /root/.bashrc
RUN echo "source /usr/local/rvm/scripts/rvm" >> /root/.bashrc; 
RUN /bin/bash -l -c "source /usr/local/rvm/scripts/rvm; \
  rvm install 1.9.3; \
  rvm use 1.9.3; \
  rvm rubygems latest; \
  cd /opt/octopress; \
  gem install bundler; \
  bundle install; \
  rake install" 
RUN echo "rvm use 1.9.3" >> /root/.bashrc

WORKDIR /opt/octopress
EXPOSE 4000
CMD ["/bin/bash"] 

After playing around with Docker and Octopress I put the whole /opt/octopress folder on my host machine and then restarted the image with the -v flag. Therefore I can edit the files on my host machine with my favorite editor and use the container only for producing the HTML files, for preview and for publishing.

The rake preview is a neat feature because the server always looks for changed files and produces the HTML files on the fly. That means I can edit the files in my editor and could see the resulting pages in a browser nearly the same time.

My Dockerfile for setting up Octopress

:: Docker, Octopress, IT

After my trouble with installing all the dependencies for Octopress I came up with the following Dockerfile for Docker. This follows the instructions from the Octopress homepage and uses RVM for managing the ruby dependencies.

# dockerfile for octopress

FROM ubuntu:14.04
MAINTAINER krrrcks <krrrcks@krrrcks.net>
ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update; \
  apt-get -q -y upgrade
RUN apt-get -q -y install git curl; \
  apt-get clean
RUN git clone git://github.com/imathis/octopress.git /opt/octopress
RUN curl -L https://get.rvm.io | bash -s stable --ruby
ENV HOME /root
RUN echo "source /usr/local/rvm/scripts/rvm" >> /root/.bashrc; 
RUN /bin/bash -l -c "source /usr/local/rvm/scripts/rvm; \
  rvm install 1.9.3; \
  rvm use 1.9.3; \
  rvm rubygems latest; \
  cd /opt/octopress; \
  gem install bundler; \
  bundle install; \
  rake install" 
RUN echo "rvm use 1.9.3" >> /root/.bashrc

WORKDIR /opt/octopress
EXPOSE 4000
CMD ["/bin/bash"]