phantomjs on raspberry

Basics

Okay, what I am doing here? I want to use phantomjs as part of an application that spiders my servers for tests. This testing environment is thought to be executed on raspberry instances. Why? It’s cheap, it’s silent, it’s perfect for me.

So, how do I deploy it? The easiest way is to use docker. Why? It enables me to simply to docker-compose for my instances and to start phantomjs-docker as standalone container with an interface to run it via selenium (see phantomjs –webdriver=<PORT>).

First tries were very promising.  I simply built up a phnatomjs-docker version. It’s amazing: docker can automatically build your image via Github Dockerfiles. See github.com/ollihoo/phantomjs-docker for more information.

Well, there is one problem: raspberry is not a x86 architecture, it bases on ARM. Luckily there are lots of linux packages, that run on this platform. This also suits to docker that has been built by Hypriot. This is where you will find more information:   Hypriot – getting started.

So, there is only one question left. Is there an ARM-based, raspberry-compatible docker package for raspberry? Well, yeaooooo…. No:

Okay, so I should try to build it for myself…

Build phantomjs on raspberry in a docker container

I don’t want to re-invent the wheel. There are lots of instructions in the web. This one is the most promising: how to compile phantomjs on the raspberry pi 2.

Okay, some remarks to the article. Of course, you should use the most current branch. Ariya Hidayat, the founder of phantomjs, works on branches for every new version. When I tried out (26.3.2016), I used 2.0 which threw – very late – an error and stopped. This bug is solved, fortunately. So, my finding: it makes sense to use the most recent branch.

Another remark: the instructions recommend to use a hdd or ssd to build. Do that!! It really speeds up compiling. The second thing is: use this f***ing –jobs 2 parameter. Without it, it gets a nightmare, because it builds and builds and… stops, because of full RAM.

To avoid more problems, I also decided to build phantomjs in a docker container. The image I used was hypriot/rpi-node:latest. Just start it with this command:

docker run -ti hypriot/rpi-node:latest /bin/bash

And voilà: 6 hours later, the build was perfectly done.

It works! What’s next?

I really tried to save the development state into a docker container. I doesn’t make sense. The building job produces changes of more than 1.5 GB. That’s nothing, you would like to get into a repository.

So, there is an alternative. In fact, the only thing we want to get, is this phantomjs binary. So copy it, and simply put it in this hypriot/rpi-node:latest container via a normal Dockerfile. This is it. You’ll find the project with this binary here:

https://github.com/ollihoo/phantomjs-docker-rpi

Ah and of course, you also can download it from hub.docker.com:

https://hub.docker.com/r/ollihoo/phantomjs-docker-rpi/

Any questions, comments? Don’t hesitate to write me.

Docker mit Spring Boot: wie baue ich ein Image?

Szenario

Ziel

Ich möchte ein funktionsähiges docker-Image bauen, das die Applikation beherbergt und dessen Container mit einem neo4j-Container kommunizieren kann.

application-wo-docker docker-application

Voraussetzungen

Ich arbeite auf einem Linux-System (Ubuntu 14.0 LTS), auf dem docker 1.9.1 läuft. Um die Platformvoraussetzungen zu erfüllen, lade ich die entsprechenden Images:

docker pull neo4j
docker pull java:8

Damit wäre die Pakete, die ich brauche, schon mal auf meinem Rechner.

Einrichtung von Java

Das Java-8-Image ist die Basis für das Applikations-Image. Daher möchte ich dieses in meiner privaten Registry speichern.

docker pull java:8

Mit dem Tag ‚java8‘ kann ich dann später die Applikation aufsetzen.

Einrichtung von neo4j

Neo4j bietet einen Container an, der die eigentlichen Nutzdaten außerhalb des Containers speichert. Um dieses Feature zu nutzen, mache ich die folgenden Schritte (als root, mit kurzem Wechsel zu einem neuen Nutzer namens neo4j):

useradd -U -m neo4j
sudo su - neo4j
mkdir geohierarchy
exit

Den Container starte ich als root mit diesem Kommando:

docker run --detach --restart=always --name=neo4j --publish=7474:7474 --volume=/home/neo4j/geohierarchy:/data neo4j

Erklärungen: der Prozess soll im Hintergrund gestartet werden (–detach) und auch dann neu starten, wenn er gestoppt wurde (–restart=…). Die Einführung des Namens ist notwendig, um später aus der Applikation heraus die Datenbank ansprechen zu können. Im Verzeichnis /home/neo4j/geohierarchy wird die eigentliche Datenbank abgelegt. Diese wird in gemounteten Verzeichnis gespeichert und bleibt auch dann erhalten, wenn der Container gelöscht wird.

Der einfachste Test der Funktionalität: im Browser http://localhost:7474 eingeben und ggf. einrichten (z.B. Passwort setzen).

Applikation

docker gibt einiges an Infrastruktur vor, das jetzt in Zusammenarbeit mit Spring Boot in Einklang gebracht werden muss. Das ist der Überblick:

  • neo4j erhält einen eigenen Container mit einem eindeutigen Namen: ’neo4j‘
  • der Spring-App-Container erhält den Namen ‚web‘
  • ‚web‘ wird mit dem Container ’neo4j‘ verlinkt (siehe 3.), dadurch kann die Server-Adresse automatisiert abgefragt werden (siehe 4.)
  • ‚web‘ benötigt außerdem noch eine Konfiguration für die Credentials. Dies wird über ein separat gemountetes Konfigurations-Directory erledigt (siehe unten).

Dockerfile aufsetzen

Hier zunächst der Link zum Dockerfile. Dies sind die zentralen Elemente, auf die ich mich beziehe:

FROM java:8 
ADD geographicalHierarchy-0.0.1-SNAPSHOT.jar app.jar 
RUN bash -c 'touch /app.jar' 
RUN mkdir /config 
VOLUME /config 
ENTRYPOINT ["java","-jar","/app.jar", "--neo4j.serverUrl=http://${NEO4J_PORT_7474_TCP_ADDR}:7474"]

Zeile 1: das Basispaket ist java:8 (siehe oben)

Zeile 2: die Applikation wird in app.jar umbenannt und später im ENTRYPOINT gestartet.

Zeile 4 und 5 legen ein Directory config/ an, das später automatisch von Spring Boot zur Konfiguration der App eingelesen wird. Dieses Directory kann von außen gemountet werden, um Konfigurationen einzuspielen (siehe 1).

Zeile 6 ist der Befehl, der ausgeführt wird, wenn der Container gestart wird. Man sieht, dass hier auch ein Parameter namens neo4j.serverUrl gesetzt wird. Die dort befindliche Variable NEO4J_PORT_7474_TCP_ADDR wird später vom Neo4j-Container bereitgestellt, wenn dieser mit der App verbunden wird. Hier erfolgt zunächst nur die Annahme, dass dies der Fall ist.

docker image bauen

Zum Bauen des Containers sollte eigentlich das Target buildDocker genügen. Im Hintergrund passiert folgendes: das Application-Jar und das docker-File wird in ein Verzeichnis kopiert (build/docker). Dort kann man dann den folgenden Befehl ausgeführen:

docker build -t localhost:5000/ollihoo/geohierarchy:0.5 .

Das Label 0.5 sollte entsprechend gesetzt werden. Als Ergebnis steht nun  ein docker-Image namens   localhost:5000/ollihoo/geohierarchy:0.5 zur Verfügung.

 

Konfiguration zur Verfügung stellen

Wie im Readme des Projektes beschrieben, sollte nun ein Konfigurationsverzeichnis mit einer application.properties angelegt werden. Diese Konfiguration ist dazu gedacht, die Credentials setzen zu können. Im Beispiel wird dieses Verzeichnis hier abgelegt: /opt/geoHierarchyConfig

 

Den Container zum Laufen bringen

Nun muss nur noch alles verbunden werden:

docker run -p 8080:8080 --link=neo4j -d --volume=/opt/geoHierarchyConfig:/config localhost:5000/ollihoo/geohierarchy:0.5

Erläuterungen:

Durch -p wird der Port 8080 nach außen verfügbar gemacht. –link=neo4j zeigt an, dass der Container neo4j verfügbar sein muss. Ist dies der Fall, exponiert er Variablen, die von der App benutzt werden (siehe oben). -d lässt der Prozess im Hintergrund laufen. —volume sorgt dafür, dass die Konfiguration zur Verfügung steht.

Das war’s. Die Applikation sollte laufen.

Feedback?

Was ist noch unklar? Was fehlt? Was ist falsch oder kann besser gemacht werden? Schreibt mir 🙂

 

Links

  1. Spring Boot: external configuration
  2. github: GeohierarchyGraph project
  3. docker – network
  4. docker hub: neo4j