Jhipster my Raspberry Pi!

If you don't know what JHipster is, stop now and go check it out!

Now that you are back, in this blog post, we will build a Netflix Stack using Jhipster on the Raspberry Pi and we will deploy it on a Raspberry Pi Docker Swarm!

But for that to happen, we need to build a Docker Raspberry Pi image for JHipster (and make it more hip if that is possible)

As a plus, we will do a demo, which would go like that:

  1. pull jmkhael/rpi-jhipster (to be created below)
  2. do some jhipster magic to create a Netflix microservice stack
  3. build and deploy the Docker stack on the Raspberry Pi swarm!

Let's Go.

Dockerize the Raspberry Pi

As a pre-requisites, you'd need to have Docker up and running on the Raspberry Pi.

Docker installations on Rasperry Pi
  • install docker: curl -sSL https://get.docker.com | sh
  • install docker-compose for Arm by following the below commands:

bash:

sudo apt-get update
sudo apt-get install -y apt-transport-https
echo "deb https://packagecloud.io/Hypriot/Schatzkiste/debian/ jessie main" | sudo tee /etc/apt/sources.list.d/hypriot.list
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 37BBEE3F7AD95B3F

sudo apt-get update
sudo apt-get install docker-compose

Confirm that everything is fine by running:

docker info
docker-compose --version

Now is the time to build the JHipster Arm image.

Jhipster on Raspberry Pi

We need to adapt the project's Dockerfile so it generates an image which we could run on the Raspberry Pi.

If you try to run the jhipster/jhipster docker image, it would fail with the dreaded panic exec format. or equivalent, depending on your luck :)

Create Dockerfile.rpi

I won't repeat here the Dockerfile, you can see it on my Github.

https://github.com/jmkhael/generator-jhipster/blob/master/Dockerfile.rpi

(I still need to do a pull request on the original project to have this natively.)

Build the image:

docker build -t jmkhael/rpi-jhipster -f Dockerfile.rpi .

Run JHipster the Docker way!

In order to be able to play with (or git commit) the generated files by JHipster, we will create some directories and mount them as volumes in the container.

Create working directory:

mkdir -p jhipster/app
mkdir -p jhipster/app/.m2
mkdir -p jhipster/app/.gradle

Give ownership of this directory to jhipster user (id 1000)

chown -R 1000 jhipster/app

In order to be able to execute Docker commands from within the container, we will need to pass the docker group as the group-add flag, so JHipster container can launch docker commands. (discussed here)

Now we can run Jhipster's Docker container on the raspberry Pi and allow it to execute Docker commands on the host!

docker run --name jhipster \
    --group-add $(cat /etc/group | grep docker | awk -F":" '{print $3}') \
    -v $(which docker):/usr/bin/docker \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v $(pwd)/jhipster/app/.m2:/home/jhipster/.m2 \
    -v $(pwd)/jhipster/app/.gradle:/home/jhipster/.gradle \
    -v $(pwd)/jhipster/app:/home/jhipster/app \
    -p 8080:8080 -p 9000:9000 -p 3001:3001 -d -t jmkhael/rpi-jhipster

At this point, Docker should give you the container id in response. If you see anything else, feel free to share in the comments.

Make sure everything works well by executing a shell in the image, and maybe executing a yo jhipster and a docker info commands in there if you feel adventurous:

docker exec -it jhipster bash

jhipster@9df16edc8e52:~/app$ 

Note that you can stop and start this container if needed using:

docker stop jhipster
docker start jhipster

Sweet! Time to build our application.

Build our application stack

Let's prepare a directory and call JHipster to generate it:

mkdir blog
cd blog
yo jhipster
yo jhipster:docker-compose

Answer this in order to have a monolithic application, Angular 1.x, named blog, MySQL, No caching, Gradle build, Social Login, Websockets, English and French support, Gatling and Cucumber!

./gradlew bootRepackage -Pprod buildDocker

If you need to force the regeneration of the application:

rm -rf src/main
yo jhipster --force --with-entities

(For fun, try running:

bower install bootstrap-material-design#0.3.0 --save

then rebuild the application.)

Once ready, go ahead and deploy the application using the generated docker-compose file:

docker-compose up -d

WARNING: The Docker Engine you're using is running in swarm mode.

Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All    containers will be scheduled on the current node.

To deploy your application across the swarm, use the bundle feature of the Docker experimental build.

More info:
https://docs.docker.com/compose/bundles

Recreating rpiblog_blog-app_1
blog-mysql is up-to-date

Navigate to http://pi1:8080 and see your application:

You can find the resulting application on https://github.com/jmkhael/rpi-blog.

Changes to the (original) Dockerfile

Below are the changes done on the Dockerfile in order to make it compatible with the Arm processor:

  1. Modify the base image to rpi-node
  2. I needed to install oracle jdk8 instead of openjdk, as it suffers from the below stack.
  3. Skip node, npm installation
  4. Skip changing ownership of /usr/lib/node_modules

Stack:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: 
   sun.security.validator.ValidatorException: PKIX path validation failed: 
   java.security.cert.CertPathValidatorException: signature check failed

This is also discussed here

TODO

I still have todo the below when time permits.

rpi-Jhipster

[] pull request for rpi image

[] override Docker image names for rpi in ./node_modules/generator-jhipster/generators/generator-constants.js:const DOCKER_JAVA_JRE = 'openjdk:8-jre-alpine';