Local development with Java
Author: Cesar Tron-Lozai (@CesarTronLozai)
Install Telepresence with Homebrew/apt/dnf
You will need the following available on your machine:
kubectlcommand line tool (here's the installation instructions).
- Access to your Kubernetes cluster, with local credentials on your machine. You can test this by running
kubectl get pod- if this works you're all set.
On OS X you can install Telepresence by running the following:
brew cask install osxfuse brew install socat datawire/blackbird/telepresence
Ubuntu 16.04 or later
Run the following to install Telepresence:
curl -s https://packagecloud.io/install/repositories/datawireio/telepresence/script.deb.sh | sudo bash sudo apt install --no-install-recommends telepresence
If you are running another Debian-based distribution that has Python 3.5 installable as
python3, you may be able to use the Ubuntu 16.04 (Xenial) packages. The following works on Linux Mint 18.2 (Sonya) and Debian 9 (Stretch) by forcing the PackageCloud installer to access Xenial packages.
curl -sO https://packagecloud.io/install/repositories/datawireio/telepresence/script.deb.sh sudo env os=ubuntu dist=xenial bash script.deb.sh sudo apt install --no-install-recommends telepresence rm script.deb.sh
A similar approach may work on Debian-based distributions with Python 3.6 by using the Ubuntu 17.10 (Artful) packages.
Fedora 26 or later
Run the following:
curl -s https://packagecloud.io/install/repositories/datawireio/telepresence/script.rpm.sh | sudo bash sudo dnf install telepresence
If you are running a Fedora-based distribution that has Python 3.6 installable as
python3, you may be able to use Fedora packages. See the Ubuntu section above for information on how to invoke the PackageCloud installer script to force OS and distribution.
See the Windows support documentation.
Install from source
On systems with Python 3.5 or newer, install into
/usr/local/bin by running:
sudo env PREFIX=/usr/local ./install.sh
Install the software from the list of dependencies to finish.
Install into arbitrary locations by setting other environment variables before calling the install script. See the install script for more information. After installation you can safely delete the source code.
Don't see your favorite platform? Let us know and we'll try to add it. Also try installing from source.
Telepresence can help you speed up your development process for any technology, as long as you deploy your service as a Docker image into a Kubernetes container.
In this tutorial we will focus on how to setup a local development environment for a (micro)-service
Foo written in Java.
This is is very useful if your application is formed of many such services which cannot run on a single development machine. In which case it's easy to setup a separate Kubernetes cluster dedicated for development.
Telepresence will help us locally develop our service
Foo as if it was still inside the Kubernetes cluster. It's a win-win!!
The idea is quite simple,
Telepresence will start a Docker container on your local machine, remove the running pod for
Foo and replace it with a two-way proxy to your local docker container.
If other services in your cluster want to talk to
Foo, they'll get redirected to your local process. If your local process wants to talk to any other services running in your cluster,
Telepresence will redirect the calls to your cluster.
It will also maintain all the environment variables defined in your deployment. It's magical.
In order to run our Java application in a local Docker container, we can simply start a container which has Java and Maven/Gradle installed, mount the source directory to our code, and do a Maven/Gradle build.
In this tutorial we will be using Maven and a Spring Boot project but this would work exactly the same with Gradle or any other Java Framework.
Building inside a docker container
As mentioned above, the goal is to compile and run our code inside a Docker container which
Telepresence can use to replace the pod running in your cluster.
Let's build the command step by step.
--swap-deployment fooAssumes we already have a
foodeployment running in our clusters. For different options check the documentation!
Telepresenceto run a Docker containers
--rmTells Docker to discard our image when it terminates (no need to clutter your computer)
-v$(pwd):/buildMounts the current directory (result of the
pwdcommand) into a
/buildfolder inside the Docker container. This is where your source code will be; in this case used by Maven.
-v $HOME/.m2/repository:/m2Mounts the Maven cache folder so we don't have to download Maven artifacts every time we run the container
-p 8080:8080That's optional. If your container is running a server on, for example, port
8080, you can map that port if you need to make requests to your service directly
maven:3.5.3-jdk-8-slimThat's the image which we will use to build and run our service. Here this is a prebuilt image containing Maven and Java 8. Use any other image to match your need
mvn -Dmaven.repo.local=/m2 -f /build spring-boot:runCommand to be run in the Docker container. Here it uses the Spring Boot Maven plugin but you can use whatever command required by your build tool. It tells maven to point to the mounted repository cache and where the source code located
And that's it! You can easily create a
telepresence.sh file in the root of your project with the following:
telepresence --swap-deployment foo --docker-run --rm -v$(pwd):/build -v $HOME/.m2/repository:/m2 -p 8080:8080 maven-build:jdk8 mvn -Dmaven.repo.local=/m2 -f /build spring-boot:run
If you are using a Kubernetes client like this one, you need to make sure the client can access service account information. This can be done with the
--mount command introduced in
We need to add the following to the command:
TELEPRESENCE_ROOTto a known folder
-v=/tmp/known/var/run/secrets:/var/run/secretsThis is another Docker mounting command to mount the known folder to
/var/run/secretsin the local container. The Fabric8 Kubernetes client can find the secrets there as it would inside Kubernetes
telepresense.sh file would look like that
telepresence --mount /tmp/known --swap-deployment foo --docker-run --rm -v$(pwd):/build -v $HOME/.m2/repository:/m2 -v=/tmp/known/var/run/secrets:/var/run/secrets -p 8080:8080 maven-build:jdk8 mvn -Dmaven.repo.local=/m2 -f /build spring-boot:run
For more details about the
mount command check the documentation
Debugging your code
If you need to debug your code with your favourite IDE that's super easy too. You only need to pass a JVM argument and forward the remote port:
-e MAVEN_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005Creates a Docker environment variable that Maven will use to set a JVM argument and awaits for a remote connection on port
5005. This is for Java 8+, check the Java documentation if you are running a lower version.
-p 5005:5005Tells docker to forward that ports from your local machine.
Then you can use your IDE to start a debug remote session on your local port
telepresence --swap-deployment foo --docker-run --rm -e MAVEN_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 -v$(pwd):/build -v $HOME/.m2/repository:/m2 -p 8080:8080 -p 5005:5005 maven-build:jdk8 mvn -Dmaven.repo.local=/m2 -f /build spring-boot:run
Hot code replace
If you have a JRebel Licence you can also integrate it with Telepresence.
Normally you would need to use JRebel remote when your application is running inside a Docker container. However your docker container shares the source folder so you can use that directly.
First you need to create a
rebel.xml file that will tell JRebel where the source code is, that is in the
"1.0" encoding="ISO-8859-1" xml version=<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.zeroturnaround.com" xsi:schemaLocation="http://www.zeroturnaround.com http://update.zeroturnaround.com/jrebel/rebel-2_1.xsd"> <classpath> <dir name="/build/target/classes"> </dir> </classpath> </application>
You should copy
rebel.xml in your
If you haven't downloaded JRebel yet, do so here and unzip it somewhere.
You can create a
JREBEL environment variable that point to this folder. That means
$JREBEL/jrebel.jar should be a valid file.
To activate JRebel, you need the following:
-v $JREBEL:/jrebelMounts the JRebel folder
jrebel.jaravailable to JREBEL
-v $HOME/.jrebel:/root/.jrebelMounts your JRebel home folder, this gives access to the licence and JRebel stats. This assumes the home folder of the process in your docker image is
/root, change if required
-Drun.jvmArguments="-agentpath:/jrebel/lib/libjrebel64.so"Tells the JVM to use the Linux64 JRebel agent
telepresence --swap-deployment foo --docker-run --rm -v $JREBEL:/jrebel -v $JREBEL/jrebel.jar:/jrebel.jar -v $HOME/.jrebel:/root/.jrebel -v$(pwd):/build -v $HOME/.m2/repository:/m2 -p 8080:8080 maven-build:jdk8 mvn -Drun.jvmArguments="-agentpath:/jrebel/lib/libjrebel64.so" -Dmaven.repo.local=/m2 -f /build spring-boot:run
If you want to see a simple Spring boot project using telepresence have a look at https://github.com/cesartl/telepresence-k8s