Docker is a tool that allows us to package, ship, and run our applications in an isolated environment called a container. Using Docker, we can simplify the deployment process by isolating our applications in their own container and abstracting them from the host environment.
In this tutorial, we are going to learn how to build a Docker image for our ZIO application and then how to deploy it. Instead of writing the
Dockerfile from scratch, we will use the sbt-native-packager to build our Docker image.
Running The Examples
All the source code associated with this article is located on the
dockerize branch of this quickstart repository.
In this quickstart, we developed a web service containing 4 different HTTP Applications. Now in this article, we want to dockerize this web application.
To access the code examples, you can clone the repository and switch to the
$ git clone email@example.com:zio/zio-quickstart-restful-webservice.git
$ cd zio-quickstart-restful-webservice
$ git checkout dockerize
Before we can dockerize our web service, we need to download and install Docker. So we assume that the reader has already installed Docker.
Adding SBT Native Packager Plugin
The sbt-native-packager is an sbt plugin that enables us an easy way to package the application as a docker image and deploy that as a docker container.
First, we need to add the plugin to our
addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.9.9")
Now it's time to enable the
DockerPlugin plugins. So we need to add the following lines in the
Building The Docker Image
DockerPlugin plugin of sbt-native-packager is responsible for configuring and building the docker image. We can run the following command to build the docker image:
$ sbt docker:publishLocal
After the docker image is built, we can run the
docker images command to see the list of images that are currently available in the local docker registry:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
zio-quickstart-restful-webservice 0.1.0 c9ae81ee8fa6 17 hours ago 558MB
Note that, to see the generated
Dockerfile we can use the
$ sbt docker:stage
Dockerfile will be generated in the
Deploying The Docker Image
Now we can create a new container from this image by using the
docker run command:
$ docker run -p 80:800 zio-quickstart-restful-webservice:0.1.0
-p flag, we can specify the port that the container will listen to. As the web service is running on port
8080, we bind this port to the host port
80. Therefore, we can access the web service from the host machine through the port
$ curl -i "http://localhost/greet?name=Jane&name=John"
HTTP/1.1 200 OK
Hello Jane and John!
Configuring The Docker Image
By default, the
sbt-native-packager plugin will build the docker image using some predefined settings. So without any configuration we can use the
sbt docker:publish or
sbt docker:publishLocal commands to build and publish the docker image to the remote or local docker registry.
However, it is possible to configure the docker image, and it has lots of options to configure. We can find the list of available options in the sbt-native-packager documentation.
Exposing Container Ports
For example, when we build a docker image, we can specify which ports the container will listen to, by using the
EXPOSE instruction in the
Dockerfile. In the similar way, we can expose the ports using sbt-native-packager, by using the
exposePorts setting in the
dockerExposePorts := Seq(8080)
Now, when we build the docker image and create a container from it, the new container has the port
8080 exposed. So when we run the
docker ps command, we can see that the new container has the port
8080 exposed under the
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
29982b053379 zio-quickstart-restful-webservice:0.1.0 "/opt/docker/bin/zio…" 3 seconds ago Up 2 seconds 8080/tcp bold_liskov
Publishing The Docker Image to a Remote Registry
In a CI/CD pipeline, we might want to publish the docker image to a remote registry other than the local registry. We can do this by configuring the
dockerRepository settings in the
dockerUsername := sys.props.get("docker.username")
dockerRepository := sys.props.get("docker.registry")
Now, we can use the following command to publish the docker image to the remote registry:
$ export DOCKER_USERNAME=<username> // e.g: johndoe
$ export DOCKER_REGISTRY=<registry> // e.g: docker.io
$ sbt -Ddocker.username=$NAMESPACE -Ddocker.registry=$DOCKER_REGISTRY docker:publish
In this tutorial, we learned how to build a docker image using sbt-native-packager, and how to deploy the docker image to the local or remote Docker registry.
The complete working example of this tutorial is available on the
dockerize branch of our ZIO Quickstart: Building RESTful Web Service quickstart on GitHub.