Apache Karaf & Docker
Apache Karaf 4.2.1 has been released two weeks ago. It’s a major upgrade on the Karaf 4.2.x series, bringing lot of fixes, improvements and new features. Especially:
- Better support of Java 9, 10 & 11
- Sets of examples directly available in the Karaf distribution, allowing you to easily starts with Karaf
- Better
KarafTestSupport
allowing you to easily creates your own integration tests.
One of new interesting feature added in Apache Karaf 4.2.1 is the support of Docker.
Docker is a great system container platform. Mixing Docker (system container) and Apache Karaf (application container) together gives a great flexibility and very powerful approach for your applications and ecosystem. You decide of the provisioning approach you want to adopt:
- a static approach using Karaf static profile directly running in Docker
- a dynamic approach with a regular Karaf distribution running in Docker
Apache Karaf 4.2.1 brings two tools around Docker:
- Build tooling (scripts) allows you to easily create Docker Karaf image and use it to create Docker containers.
- A
docker
feature that you can install in a running Apache Karaf instance, allowing you to manipulate Docker directly from Karaf.
Creating Docker Karaf images
Since Apache Karaf 4.2.1, the Apache Karaf assembly provides new Docker scripts: https://github.com/apache/karaf/tree/master/assemblies/docker.
In order to use it, you need:
docker
installeddocker-compose
installed
Now, Apache Karaf provides a build.sh
script to easily create your Karaf image. The generated image is based on the official Java Alpine (OpenJDK 8) image.
The build.sh
script is pretty easy to use.
Alternatively, you can also use the “classic” docker build
command. Apache Karaf assembly/docker
folder provides the Dockerfile
used by docker build
.
Let’s take a look on build.sh
. This script is convenient as:
- you can create a Docker image based on a local Karaf distribution you create or an official Karaf distribution available on Apache mirror.
- you can provide an image name.
- you can provide a Karaf version (when you create the Docker image using an official Karaf distribution).
Docker image using Karaf vanilla distribution
The first classic usage of build.sh
is to create a Docker image using an official Karaf distribution (“vanilla”) available on Apache mirrors.
For instance, we want to create a Docker image using Apache Karaf 4.2.1. We can simply do:
$> assembly/docker/build.sh --from-release --karaf-version 4.2.1 --image-name karaf<br/>Downloading apache-karaf-4.2.1.tar.gz from http://mirrors.standaloneinstaller.com/apache/karaf/4.2.1/Sending build context to Docker daemon 22.06MBStep 1/10 : FROM java:8-jre-alpine8-jre-alpine: Pulling from library/java709515475419: Pull complete 38a1c0aaa6fd: Pull complete cd134db5e982: Pull complete Digest: sha256:6a8cbe4335d1a5711a52912b684e30d6dbfab681a6733440ff7241b05a5deefdStatus: Downloaded newer image for java:8-jre-alpine ---> fdc893b19a14Step 2/10 : ENV KARAF_INSTALL_PATH=/opt ---> Running in dadbe0fbb5d7Removing intermediate container dadbe0fbb5d7 ---> 4d14737dd37dStep 3/10 : ENV KARAF_HOME $KARAF_INSTALL_PATH/apache-karaf ---> Running in b146df1354a1Removing intermediate container b146df1354a1 ---> 27f504e74175Step 4/10 : ENV PATH $PATH:$KARAF_HOME/bin ---> Running in f7e262e47d31Removing intermediate container f7e262e47d31 ---> aeb7757dee5cStep 5/10 : ARG karaf_dist=NOT_SET ---> Running in d3d0ac0b66d8Removing intermediate container d3d0ac0b66d8 ---> 1f9456e1edfdStep 6/10 : ADD $karaf_dist $KARAF_INSTALL_PATH ---> 828362c5401aStep 7/10 : RUN set -x && ln -s $KARAF_INSTALL_PATH/apache-karaf* $KARAF_HOME ---> Running in f59a3e5139cdln -s /opt/apache-karaf-4.2.1 /opt/apache-karafRemoving intermediate container f59a3e5139cd---> b05d4af0df6bStep 8/10 : COPY docker-entrypoint.sh /---> 003ed84df94fStep 9/10 : EXPOSE 8101 1099 44444 8181---> Running in 35bceaa38fe9Removing intermediate container 35bceaa38fe9---> 439a85a3d6f0Step 10/10 : ENTRYPOINT ["/docker-entrypoint.sh"]---> Running in fa51274dbbf3Removing intermediate container fa51274dbbf3---> e595c47809e5Successfully built e595c47809e5Successfully tagged karaf:latest
We can see that build.sh
automatically downloaded the Apache Karaf 4.2.1 distribution from a Apache mirror. It also retrieves the Alpine Java base Docker image.
Now, we can see the image in our Docker:
$> docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEkaraf latest e595c47809e5 4 minutes ago 133MBjava 8-jre-alpine fdc893b19a14 18 months ago 108MB
We can run a Docker container using our karaf
image.
First way to do that is to use the “classic” docker run
command:
$> docker run -p 1099:1099 -p 8101:8101 -t --name mycontainer karafStarting Apache Karafkaraf: Ignoring predefined value for KARAF_HOMEApache Karaf (4.2.1)Hit '' for a list of available commandsand '[cmd] --help' for help on a specific command.Hit '' or type 'system:shutdown' or 'logout' to shutdown Karaf.karaf@root()>
We can see the container running:
$> docker ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES477b3cec3b76 karaf "/docker-entrypoint.…" 3 minutes ago Up 3 minutes 0.0.0.0:1099->1099/tcp, 8181/tcp, 0.0.0.0:8101->8101/tcp, 44444/tcp mycontainer
When you use docker run
you have to remember to expose the network ports using the -p
option. When you expose 8101
you can connect to the Karaf running inside the Docker container using ssh
or Karaf bin/client
.
An alternative to docker run
(or docker start
) is to use docker-compose
. Apache Karaf now provides docker-compose.yml
to simplify the way to starting and stopping Apache Karaf in docker.
To start Apache Karaf Docker image, you can do:
$> docker-compose run karafStarting Apache Karafkaraf: Ignoring predefined value for KARAF_HOME...
The behavior is exactly the same as using docker run
however, the ports binding is configured in Karaf docker-compose.yml
.
You can also start in daemon mode (without the shell console) using:
$> docker-compose upCreating docker_karaf_1 … Creating docker_karaf_1 … doneAttaching to docker_karaf_1karaf_1 | Starting Apache Karaf
You can stop an existing container using
$> docker-compose kill
Docker image with custom Karaf distribution
You have created your own Karaf custom distribution based and you want to create a Docker image with it ? Very simple with build.sh
script ! You just have to provide the archive of your custom distribution.
$> ./build.sh --from-local-dist --archive /home/jbonofre/my-karaf.tar.gz --image-name my-karafUsing karaf dist: /home/jbonofre/my-karaf-1.0.0.tar.gzSending build context to Docker daemon 22.11MBStep 1/10 : FROM java:8-jre-alpine ---> fdc893b19a14Step 2/10 : ENV KARAF_INSTALL_PATH=/opt ---> Running in 620e32d745a9Removing intermediate container 620e32d745a9 ---> f773a2c25001Step 3/10 : ENV KARAF_HOME $KARAF_INSTALL_PATH/apache-karaf ---> Running in 2445bbea610dRemoving intermediate container 2445bbea610d ---> 1974f31ada89Step 4/10 : ENV PATH $PATH:$KARAF_HOME/bin ---> Running in 20b5bc409c29Removing intermediate container 20b5bc409c29 ---> 3e73907f5b14Step 5/10 : ARG karaf_dist=NOT_SET ---> Running in e7603a1c7117Removing intermediate container e7603a1c7117 ---> 5de9504336ccStep 6/10 : ADD $karaf_dist $KARAF_INSTALL_PATH ---> 1eba7c16ffd0Step 7/10 : RUN set -x && ln -s $KARAF_INSTALL_PATH/apache-karaf $KARAF_HOME ---> Running in d3c685bd2bcdln -s /opt/apache-karaf-4.2.2-SNAPSHOT /opt/apache-karafRemoving intermediate container d3c685bd2bcd---> 1e9306813e59Step 8/10 : COPY docker-entrypoint.sh /---> e28f024ad48eStep 9/10 : EXPOSE 8101 1099 44444 8181---> Running in 960627ec7597Removing intermediate container 960627ec7597---> 9a3d6017498dStep 10/10 : ENTRYPOINT ["/docker-entrypoint.sh"]---> Running in 9d7fc90c19c8Removing intermediate container 9d7fc90c19c8---> 98ee7d5ef992Successfully built 98ee7d5ef992Successfully tagged my-karaf:latest
We now have a Karaf Docker image with our custom distribution:
$> docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEmy-karaf latest 98ee7d5ef992 About a minute ago 133MBjava 8-jre-alpine fdc893b19a14 18 months ago 108MB
It’s exactly the same as before to start a Docker container using docker run
or docker-compose
.
Official Apache Karaf Docker images
I’m preparing a pull request to DockerLib to add official Apache Karaf Docker images based on these scripts.
Karaf docker feature
assembly/docker/build.sh
is not the only new stuff in Apache Karaf 4.2.1.
A new docker
feature has been added too, allowing you to interact with Docker directly from a running Apache Karaf instance.
Prerequisites
The Apache Karaf docker
feature interacts with Docker using tcp
. You have to enable it by passing an option to the Docker daemon:
/usr/bin/dockerd -H fd:// -H tcp://localhost:2375
For instance, on a Ubuntu system, you can configure the Docker daemon in /lib/systemd/system/docker.service
file, changing the ExecStart
property:
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://localhost:2375
You have to restart the Docker daemon after you changed the docker.service
file:
>$ service docker restart
You can check the status of the Docker:
$> service docker status● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; disabled; vendor preset: enabled) Active: active (running) since Tue 2018-09-11 11:30:08 CEST; 3min 7s ago Docs: https://docs.docker.com Main PID: 31978 (dockerd) Tasks: 38 CGroup: /system.slice/docker.service ├─31978 /usr/bin/dockerd -H fd:// -H tcp://localhost:2375 └─32004 docker-containerd --config /var/run/docker/containerd/containerd.tomlsept. 11 11:30:07 precision dockerd[31978]: time="2018-09-11T11:30:07.569933812+02:00" level=warning msg="Your kernel does not support cgroup rt period"sept. 11 11:30:07 precision dockerd[31978]: time="2018-09-11T11:30:07.569949221+02:00" level=warning msg="Your kernel does not support cgroup rt runtime"sept. 11 11:30:07 precision dockerd[31978]: time="2018-09-11T11:30:07.570903883+02:00" level=info msg="Loading containers: start."sept. 11 11:30:08 precision dockerd[31978]: time="2018-09-11T11:30:08.258633531+02:00" level=info msg="Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred IP address"sept. 11 11:30:08 precision dockerd[31978]: time="2018-09-11T11:30:08.289844901+02:00" level=info msg="Loading containers: done."sept. 11 11:30:08 precision dockerd[31978]: time="2018-09-11T11:30:08.360892312+02:00" level=info msg="Docker daemon" commit=7390fc6 graphdriver(s)=overlay2 version=17.12.1-cesept. 11 11:30:08 precision dockerd[31978]: time="2018-09-11T11:30:08.361071172+02:00" level=info msg="Daemon has completed initialization"sept. 11 11:30:08 precision dockerd[31978]: time="2018-09-11T11:30:08.365804009+02:00" level=info msg="API listen on 127.0.0.1:2375"sept. 11 11:30:08 precision dockerd[31978]: time="2018-09-11T11:30:08.365826737+02:00" level=info msg="API listen on /var/run/docker.sock"sept. 11 11:30:08 precision systemd[1]: Started Docker Application Container Engine.
This Docker service can be used locally or remotely by the Karaf Docker feature.
Installing Karaf Docker feature
It’s really easy to install the docker
feature on a running Apache Karaf instance:
karaf@root()> feature:install docker
Once docker
feature is installed, you have new docker:*
shell commands available in Karaf.
You can use docker:info
to get some details about the Docker service:
karaf@root()> docker:info Containers: 0Debug: falseDriver: overlay2ExecutionDriver: nullIPv4Forwarding: trueImages: 1IndexServerAddress: https://index.docker.io/v1/InitPath: nullInitSha1: nullKernelVersion: 4.15.0-33-genericMemoryLimit: trueNEventsListener: falseNFd: 20NGoroutines: 33SwapLimit: false
By default, Karaf Docker uses http://localhost:2375 URL to interfact with Docker. If you want to connect to another Docker service (remote for instance), you can use the --url
option:
karaf@root()> docker:info --url http://localhost:2375
docker:version
command provides some details about the Docker service you are using:
karaf@root()> docker:versionVersion: 17.12.1-ceOs: linuxKernel version: 4.15.0-33-genericGo version: go1.10.1Git commit: 7390fc6Arch: amd64API version: 1.35Build time: 2018-02-28T17:46:05.000000000+00:00Experimental: null
Any Docker action can be performed using the Karaf shell command, or directly in the DockerMBean
provided by Karaf.
Use case: elasticsearch docker with http proxy
The Apache Karaf documentation describes all docker:*
commands: http://karaf.apache.org/manual/latest/#_docker.
In this blog, I would like to show a first use case of Karaf Docker feature: manipulating Docker container directly within Karaf and expose in Karaf.
To illustrate this use case, I gonna use a Docker image providing elasticsearch.
First, let’s search for image directly in Karaf using the docker:search
shell commands:
karaf@root()> docker:search elasticsearchName │ Description │ Automated │ Official │ Star Count────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────┼──────────┼───────────elasticsearch │ Elasticsearch is a powerful open source search and analytics engine that makes data easy to explore. │ false │ true │ 3027...
Let’s pull the elasticsearch
image using the docker:pull
command:
karaf@root()> docker:pull -v elasticsearch
We can see the images available in the Docker service using docker:images
command:
karaf@root()> docker:imagesId │ RepoTags │ Created │ Labels │ Size │ Virtual Size────────────────────────────────────────────────────────────────────────┼────────────────────────┼────────────┼────────┼───────────┼─────────────sha256:362c5cb1669b144eef89d39a6e9153c546c14923e10fde17701920615c0e2add │ [elasticsearch:latest] │ 1536162308 │ │ 485920188 │ 485920188
Now, we can create a container using the elasticsearch image and control it directly from Karaf:
karaf@root()> docker:create --cmd '/docker-entrypoint.sh' --tty --image elasticsearch --exposedPort 9200/tcp --hostPortBinding 9200 elasticsearch
We can see our elasticsearch
container available with docker:ps
command:
karaf@root()> docker:ps -aId │ Names │ Command │ Created │ Image │ Image ID │ Status │ State │ Ports │ Size │ Size Root─────────────────────────────────────────────────────────────────┼─────────────────┼─────────────────────────────────────────────┼────────────┼───────────────┼─────────────────────────────────────────────────────────────────────────┼─────────┼─────────┼───────┼──────┼──────────6db4369b07eb3894034c77ea3e28b08e80ec723a711ee90ff6f1a3917256a57b │ [elasticsearch] │ /docker-entrypoint.sh /docker-entrypoint.sh │ 1536674098 │ elasticsearch │ sha256:362c5cb1669b144eef89d39a6e9153c546c14923e10fde17701920615c0e2add │ Created │ created │ │ 0 │ 0
We start our elasticsearch
container:
karaf@root()> docker:start elasticsearch
The elasticsearch instance is running and binding port 9200. You can check that it works fine by accessing to http://localhost:9200/ in your browser.
Now, we want to “hide” direct access to elasticsearch, and access to elasticsearch docker container “via” Karaf. To do that, let’s install the http
feature:
karaf@root()> feature:install http
The http
feature brings the support of HTTP proxies. So, we can simply add a proxy from Karaf HTTP service to Elasticsearch Docker container:
karaf@root()> http:proxy-add /elasticsearch http://localhost:9200
We can see our HTTP proxy available in Karaf:
karaf@root()> http:proxies URL │ ProxyTo───────────────┼──────────────────────/elasticsearch │ http://localhost:9200
Now, we can access elasticsearch “via” Karaf using http://localhost:8181/elasticsearch.
Basically, the Karaf docker
feature is a way of interacting with the Docker service as you can do directly with the docker commands.
However, it also provides an unique feature: the provisioning.
Karaf Docker provisioning
You have a running Karaf instance where you install bunch of features, bundles, change configuration, …
You want to create a Docker container using this instance ? Simpy use the docker:provision
command. It will create a Docker container with your instance as a container volume, starting it automatically.
Let’s create the container:
karaf@root()> docker:provision mykaraf
We can see a new container mykaraf
has been created:
karaf@root()> docker:ps -aId │ Names │ Command │ Created │ Image │ Image ID │ Status │ State │ Ports │ Size │ Size Root─────────────────────────────────────────────────────────────────┼───────────┼─────────────────────────────┼────────────┼───────────────────┼─────────────────────────────────────────────────────────────────────────┼─────────┼─────────┼───────┼──────┼──────────d3f3feb99f7f63735fed24946b2d4fe76d83742db0cada4c743ba3535cb73ed4 │ [mykaraf] │ /opt/apache-karaf/bin/karaf │ 1536681767 │ java:8-jre-alpine │ sha256:fdc893b19a147681ee764b2edab6c494d60fe99d83b14b8794bbcbc040ec7aa7 │ Created │ created │ │ 0 │ 0
Now, we can start the container, even outside of the Karaf instance:
$> docker start mykaraf
We can see our mykaraf
container started:
$> docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESd3f3feb99f7f java:8-jre-alpine "/opt/apache-karaf/b…" 3 minutes ago Up 1 second 0.0.0.0:1099->1099/tcp, 0.0.0.0:8101->8101/tcp, 0.0.0.0:8181->8181/tcp, 0.0.0.0:44444->44444/tcp mykaraf
As Karaf Docker automatically created the port binding, we can connect to our Karaf instance running in Docker container using ssh:
$> ssh -p 8101 karaf@localhost...karaf@root()>
Conclusion
I hope you will enjoy the new Docker feature available in Apache Karaf 4.2.1. It opens new possibility for devops to build a complete and very flexible ecosystem powered by Apache Karaf.
As usual, feel free to share bugs you might find, improvements, new features or just ideas !
Thanks !
Comments
Post a Comment