Developing and Deploying Ballerina Microservices in Docker in 5 Minutes

Rajkumar Rajaratnam
4 min readSep 15, 2018

--

It’s easier now than ever before to develop and deploy microservices so quick with Ballerina.

We are going develop a Ballerina microservice and deploy it in Docker in just 5 minutes.

Prerequisites

Developing a Ballerina Microservice

Following is the simple Ballerina rest service that we are going to use in this blog. Learn more from official documents.

You can use ballerina run command to compile and deploy this service locally in your laptop.

$ ballerina run utility.bal
ballerina: initiating service(s) in 'utility.bal'
ballerina: started HTTP/WS endpoint 0.0.0.0:8280

Service should be up now and listening on your host IP and port 8280. You can send a request and verify.

$ curl -i http://localhost:8280/utility/hello
HTTP/1.1 200 OK
content-type: text/plain
content-length: 31
server: ballerina/0.981.1
date: Fri, 14 Sep 2018 22:28:56 -0500
Congratulations, let's dance!

If you want to ship and deploy this service in any other computing system such as bare metal, virtual machine or containers, you would want to generate the compiled binary file (.balx) for the above program. This compiled binary bundles all your packages and their dependencies. You can just run it anywhere, provided that Ballerina is installed there. You can use ballerina build command to generate compiled binary file.

$ ballerina build utility.bal
Compiling source
utility.bal
Generating executable
utility.balx

The utility.balx is the compiled binary. You can deploy this compiled binary using ballerina run command. Try deploying it locally in your laptop.

$ ballerina run utility.balx
ballerina: initiating service(s) in 'utility.balx'
ballerina: started HTTP/WS endpoint 0.0.0.0:8280

All good, let’s move on to deploying this compiled binary in Docker container.

Creating Docker Artifacts Manually : Hard Way

Ballerina provides an extremly convenient way of automatically generating Dockerfile. We will see that in detail later in this blog. But for now, let’s try to create Dockerfile manually so that we can understand the process bettter.

Let’s start by writing a Dockerfile. I’m using ballerina/ballerina:0.981.1 as the base image which has OpenJDK and Ballerina v0.981.1 installed. This is the smallest base image available as of now.

Above Dockerfile is self explanatory, you just need to copy the compiled binary to the home directory, expose the service port and run the compiled binary using ballerina run command.

Let’s build the docker image and tag it as utility:v1

$ docker build -t utility:v1 .
Sending build context to Docker daemon 9.216kB
Step 1/5 : FROM ballerina/ballerina:0.981.1
---> a65975411327
...
Successfully built 87a50ea2712a
Successfully tagged utility:v1

Deploying in Docker

Use the following command to deploy a container from the image we’ve built with our service. Port 8281 of the docker host is mapped to port 8280 of the docker container.

$ docker run -d -p 8281:8280 --name utility_api utility:v1
147a2ea17b08e757894883b49022e975bb69fb6e671b5038b89b3eb778278ec7

Use the following command to check if the container is up.

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
147a2ea17b08 utility:v1 "/bin/sh -c 'balleri…" 46 seconds ago Up 45 seconds 0.0.0.0:8281->8280/tcp utility_api

Use the following command to check the service logs inside the docker container. By default Ballerina writes all the logs to stdout and stderr and that is the reason why docker logs shows us the ballerina logs too.

$ docker logs utility_api
ballerina: initiating service(s) in 'utility.balx'
ballerina: started HTTP/WS endpoint 0.0.0.0:8280

All good, our service is up and running inside the docker container. Send a request and verify.

$ curl -i http://localhost:8281/utility/hello
HTTP/1.1 200 OK
content-type: text/plain
content-length: 31
server: ballerina/0.981.1
date: Sat, 15 Sep 2018 04:56:07 GMT
Congratulations, let's dance!

Let’s now move on to generating docker files automatically using Ballerina’s builtin docker annotations.

Generating Docker Artifacts Automatically : Easy Way

Ballerina provides builtin support for automatically generating Docker and Kubernetes artifacts as part of the build process. You just need to annotate your Ballerina program with Docker and Kubernetes annotations and Ballerina build process will generate Docker and Kubernetes artifacts for you. Very convenient.

Here is how you need to annotate your Ballerina program with docker annotations. See here for the list of supported annotations.

Let’s build this updated program and see the outputs.

$ ballerina build utility.bal
Compiling source
utility.bal
Generating executable
utility.balx
@docker - complete 3/3
Run the following command to start a Docker container:
docker run -d -p 8280:8280 utility:v2

Let’s have a look at the generated files.

$ tree
.
├── docker
│ └── Dockerfile
├── utility.bal
└── utility.balx
1 directory, 3 files

This time ballerina build command has done three things for me. 1) It has generated the compiled binary as we’ve already seen earlier. 2) It also has generated the Dockerfile for me. This Dockerfile is excatly same as the Dockerfile we created manually earlier in this blog.

$ cat docker/Dockerfile
# Auto Generated Dockerfile
FROM ballerina/ballerina:0.981.1
LABEL maintainer="dev@ballerina.io"
COPY utility.balx /home/ballerinaEXPOSE 8280CMD ballerina run utility.balx

3) Additionally, it has built the docker image too for me. The utility:v2 docker image was automatically built by ballerina build command.

$ docker images
REPOSITORY TAG IMAGE ID
utility v2 1c5c9f5196b8
utility v1 87a50ea2712a

You can deploy a container from utility:v2 docker image. Use a different name and port mapping than what we used earlier in the blog.

$ docker run -d -p 8282:8280 --name utility_api_2 utility:v2
f621409f585ff42aeabaa042140e51469bffd40ac03edf98a495f4267645142e

See if the logs looks okay.

$ docker logs utility_api_2
ballerina: initiating service(s) in 'utility.balx'
ballerina: started HTTP/WS endpoint 0.0.0.0:8280

Send a request and verify if service works okay.

$ curl -i http://localhost:8282/utility/hello
HTTP/1.1 200 OK
content-type: text/plain
content-length: 31
server: ballerina/0.981.1
date: Sat, 15 Sep 2018 05:25:03 GMT
Congratulations, let's dance!

Summary

Ballerina provides awesome builtin support for

  • Dockerfile generation using @docker:* annotations.
  • Docker image generation.
  • Docker push support with docker registry.
  • Docker based ballerina debug support.
  • Copying files to containers.

Learn more about Ballerina’s builtin Docker support here.

--

--

Rajkumar Rajaratnam

Drawing from a decade of hands-on experience developing large-scale Middleware applications – a journey through challenges, solutions, and valuable lessons.