Category Archive for: ‘Uncategorized’

GitPod: Web IDE for GitHub

1

Recently I stumbled upon GitPod, a Web based IDE for GitHub projects. GitPod is based on Theia, an extensible, VS Code-powered IDE for browser and desktop. While playing around with GitPod, I got the feeling: This is awesome! For me there are several use cases, but the most important one was: Could I use GitPod as tool for giving workshops with lots of coding exercises. As an example I tried out my Web App Tutorial that I regularly give at conferences. Usually I prepare a VM using Vagrant, containing all the labs, the tooling, etc., but those VMs are around 6 GB of data and need a decent notebook so that everything runs smoothly. And in every training there are notebook configurations having trouble running these VMs. What if I just could say: Bring your favorite Web browser, we will do all labs and running all tests in the browser? That’s what I wanted to try out with GitPod. Here is my setup: During the workshop we develop a small microservice with an Angular 7 based frontend and a Spring Boot 2.0.6 based backend. How easy would it be to compile and start the backend in GitPod, start the frontend, see the result, making a change to the frontend Typescript code and immediately see the result in a browser window? Additionally I wanted to run Headless-Chrome based tests on the frontend code. This was actually pretty easy with GitPod. I only had to create a GitPod configuration file in my Git repo:

tasks:
  - command: "npm install && export CHROME_BIN=/usr/bin/chromium-browser"
ports:
  - port: 8080
    protocol: "http"
  - port: 4200
    protocol: "http"

The first statement tells GitPod to run npm install which is needed to install all Node.js modules. To run the tests in Chrome I had to set the CHROME_BIN environment variable to point to Chromium. The last thing was to expose the ports 8080 for the backend, to browse the REST API and 4200 for the frontend development server to have fast turnarounds during frontend development. The picture shows how this looks in GitPod:

If you want to try this out yourself, follow the steps:

  • Open https://gitpod.io/#https://github.com/toedter/webapp-tutorial in a Web browser
  • Wait until npm install is finished
  • Open a new terminal (File menu) to start the backend
  • Type cd lab7/complete/backend in this terminal
  • Type ../../../gradlew bootrun in this terminal and wait until you see a log like: Started Application in 2.198 seconds
  • At the top, GitPod informs you that a service is running on port 8080, click Open
  • In the embedded Web browser you see the Spring default error page, which is totally OK
  • If you add /api/users in the embedded Web browser you should see the JSON response of the backend
  • So the Spring Boot based backend is up and running
  • Switch back to the first terminal
  • Type cd lab7/complete/frontend in this terminal
  • Now type npm run gitpod-start to run the frontend in its own development server
  • Open port 4200 in the embedded Web browser
  • Now you should see the Angular based frontend, like on the screenshot.
  • Open file (with double click): /lab7/complete/frontend/src/app/user/users.component.html
  • Edit the file and change the content in the h4 tag to GitPod Users
  • Now the new frontend should immediately re-compile and you should see the change in the UI

All in all, I see great potential to run labs with coding exercises completely in the browser using GitPod. Once the debugging server protocols are in place I hope that I could both debug the frontend as well the backend also directly in GitPod.

Heroku Docker Deployment Update

0

Last Friday I gave a presentation for the Java User Group Thüringen that included a live deployment to Heroku using Docker. The deployment did not work and I found out about it one day later: Heroku has changed the workflow, Docker push to the Heroku registry does not release the app anymore. The reason for that change is explained here. In my Travis-CI builds, I added a small bash script using the Heroku API to trigger a release. Here is an example script that I use in my microservice in 60 minutes demo.

#!/bin/bash
imageId=$(docker inspect registry.heroku.com/microservice-60min/web --format={{.Id}})
payload='{"updates":[{"type":"web","docker_image":"'"$imageId"'"}]}'
curl -n -X PATCH https://api.heroku.com/apps/microservice-60min/formation \
-d "$payload" \
-H "Content-Type: application/json" \
-H "Accept: application/vnd.heroku+json; version=3.docker-releases" \
-H "Authorization: Bearer $HEROKU_AUTH_TOKEN"

Then, the .travis.yml script part looks like:

  - docker tag kaitoedter/ms60min registry.heroku.com/microservice-60min/web
  - docker login --username=_ --password="$HEROKU_AUTH_TOKEN" registry.heroku.com
  - docker push registry.heroku.com/microservice-60min/web
  - ./heroku-container-release.sh

Now, releasing Docker images after pushing them to Heroku is working again.

Optimizing Docker Images for Spring Boot

4

Spring Boot creates fat jars as a result. It is very easy to run them in containers, just create an image that contains the appropriate Java version, copy the jar, start java => that’s basically it. Most likely you want to push this image to a Docker registry and here one disadvantage of this method becomes obvious: If you just change one line in one of your own Java classes, you create a layer in the Docker image, which contains not only your own stuff bat also all dependencies. So when you push an image after a small change, you are probably pushing between 30 and 60 MB, depending on your dependencies. This block post explains how you can optimize your Docker images so that you only push your stuff, which in the best case is only KB or a few MB.

The first step is to separate your own stuff and your dependencies. For that, you can use extra Gradle or Maven build steps. I will show how this is done using Gradle. The idea is that after Gradle has created the Spring Boot fat jar, unzip it, and copy the result to 2 separate directories: docker/lib for the external dependencies and docker/app for your very own stuff. Then create a Dockerfile including 2 lines: One line copies docker/lib to /app/BOOT-INF/lib/ in one Docker image layer and the second line copies docker/app/ to /app/ in another Docker image layer.

The Dockerfile looks then like:

FROM java:openjdk-8-jre-alpine
COPY docker/lib/ /app/BOOT-INF/lib/
COPY docker/app/ /app/
CMD java -cp /app/ org.springframework.boot.loader.JarLauncher
EXPOSE 8080

The Gradle code looks like:

task deleteDockerDir(type: Delete) {
    delete "${buildDir}/docker"
}

task unzipBoot(type: Copy) {
    def zipFile = file("${buildDir}/libs/" + project.name + '-' + project.version + '.jar')
    def outputDir = file("${buildDir}/docker/app")

    from zipTree(zipFile)
    into outputDir

    def copyDetails = []
    eachFile { copyDetails << it } doLast { copyDetails.each { FileCopyDetails details ->
            def target = new File(outputDir, details.path)
            if (target.exists()) {
                target.setLastModified(details.lastModified)
            }
        }
    }
}
unzipBoot.dependsOn deleteDockerDir

task moveBootExplodedLib() {
    doLast {
        ant.move(file: "${buildDir}/docker/app/BOOT-INF/lib", toFile: "${buildDir}/docker/lib")
    }
}
moveBootExplodedLib.dependsOn unzipBoot

task createDockerfile () {
    doLast {
        def dockerfile = new File("$buildDir/Dockerfile")
        dockerfile.write 'FROM java:openjdk-8-jre-alpine\n'
        dockerfile << 'COPY docker/lib/ /app/BOOT-INF/lib/\n'
        dockerfile << 'COPY docker/app/ /app/\n'
        dockerfile << 'CMD java -cp /app/ org.springframework.boot.loader.JarLauncher\n'
        dockerfile << 'EXPOSE 8080\n'
    }
}
createDockerfile.dependsOn moveBootExplodedLib

You find working example projects using this optimization in my Github repos:

Creating colorful Banners for Spring Boot Applications

5

Often it is nice if a service provides its own banner. Then you can easily recognize the start of the service, even when you just take a quick glimpse. Its even nicer if the banner could provide colors, just in case you have a log or a terminal that supports colored output. With the release 1.3.0 of Spring Boot it is possible to display colorful banners.

For my Chatty demo, I quickly created a banner using an ASCII art generator, like http://patorjk.com/software/taag/#p=display&f=Graffiti&t=Chatty. if you save it in a file named banner.txt and put it under src/main/resources, it would be displayed like:

chatty-banner1

With a little bit of ANSI colors I got

chatty-banner2

You find the current Chatty banner.txt here.

If you want to have it really colorful, you could create a banner like

chatty-banner3

You find the source for the above banner.txt here.

All in all, it was fun creating a new banner for my Spring Boot based demo service.

 

Continuous Delivery with Travis-CI & Giant Swarm

1

Recently I enhanced my Travis-CI build for Chatty:

  • I create a docker image on the fly
  • I push it to Docker Hub
  • I push it to Giant Swarm and update the chatty-server component

So every time I push a commit to GitHub, just a few minutes later the new version of Chatty is alive at http://chatty-toedter.gigantic.io/.

Here are the relevant parts of my .travis.yml to accomplish this:

sudo: required

services:
  - docker

before_script:
  - curl -O https://downloads.giantswarm.io/swarm/clients/0.24.1/swarm-0.24.1-linux-amd64.tar.gz
  - sudo tar xzf swarm-0.24.1-linux-amd64.tar.gz -C /usr/local/bin

script:
  - docker build -t kaitoedter/chatty .
  - docker login --email="$DOCKER_EMAIL" --username="$DOCKER_USERNAME" --password="$DOCKER_PASSWORD"
  - docker push kaitoedter/chatty

  - swarm login $SWARM_USER -p $SWARM_PASSWORD
  - sudo docker tag -f kaitoedter/chatty registry.giantswarm.io/toedter/chatty-boot
  - docker push registry.giantswarm.io/toedter/chatty-boot
  - swarm update chatty/chatty-server

The credentials for Docker Hub and Giant Swarm can be stored in environment variables using the Travis-CI Web UI.

Deploy Multi-Language Projects to Heroku

0

In my current technology playground chatty I use Java, TypeScript and JavaScript as programming languages. For the TypeScript/HTML based Web UI I use a node/grunt based build, for the Java parts I use Gradle. Heroku is a great cloud platform, deploying software is done using a git push. Using the predefined build-packs, it is pretty easy to deploy Java OR Node based applications, but how to deploy a multi-language project that uses both?

Here the heroku-buildpack-multi helps a lot. Simply invoke

$ heroku config:add BUILDPACK_URL=https://github.com/ddollar/heroku-buildpack-multi.git

and add all buildpacks to a top-level .buildpack file, that’s it. Then, each build is done sequentially as specified in the .buildpack file. The .buildpack for chatty looks like

https://github.com/mbuchetics/heroku-buildpack-nodejs-grunt.git
https://github.com/heroku/heroku-buildpack-gradle.git

Another important thing to know about these buildpacks assume that the corresponding project is located at top-level. So the node build expects a package.json in the root directory. Since chatty is a multi-project build, the web part is located in subprojects/com.toedter.chatty.client.web. For me, the easiest solution was to copy the package json to the root directory, and the provide a grunt file, that copies all node_modules to the subproject. Additionally I use the grunt contribution grunt-hub to invoke the gruntfile located in the subproject with target distBoot (to provide a distribution of the JacaScript/HTML/CSS/libs that can be deployed together with the Spring Boot based server part. The last thing is to define a grunt task named ‘heroku’ that is invoked by the buildpack. The whole top-level grunt file looks like:

module.exports = function (grunt) {
    'use strict';

    grunt.initConfig({
        hub: {
            all: {
                src: ['subprojects/com.toedter.chatty.client.web/Gruntfile.js'],
                tasks: ['distBoot']
            }
        },
        copy: {
            node_modules: {
                expand: true,
                src: 'node_modules/**/*',
                dest: 'subprojects/com.toedter.chatty.client.web/'
            }
        }
    });

    grunt.loadNpmTasks('grunt-hub');
    grunt.loadNpmTasks('grunt-contrib-copy');

    grunt.registerTask('heroku', ['copy:node_modules', 'hub']);
}

The Java part is pretty straight forward since gradle is the master build system of chatty. The only subproject I want to deploy to heroku is the Spring Boot based server, located in subprojects/com.toedter.chatty.server.boot. In the gradle.build file I just added a new gradle task ‘stage’:

task stage(dependsOn: ['jar', 'bootRepackage'])

that creates the fat jar for the chatty spring boot application. The resulting web application demo is then deployed to Heroku, you can check it out at https://chatty42.herokuapp.com/chatty/chatty.html.

Regarding IDE integration there are Heroku plugins for IntelliJ IDEA and Eclipse. In the next blog of this series, I will explain how to use Travis-CI for a continuous delivery, including the automatic deployment to Heroku after a successful build.