Our website is made possible by displaying online advertisements to our visitors. Please consider supporting us by disabling your ad blocker.

Using Couchbase With Docker And Deploying A Containerized NoSQL Cluster

TwitterFacebookRedditLinkedInHacker News

You can do a lot of cool things with Docker, for example containerizing web applications, processes, and a bunch of other things. What happens when you want to deploy your database as a container, or more specifically, your distributed database as containers? Most NoSQL databases are distributed, meaning they can be easily clustered with data replication and a bunch of other awesome features. How do you provision each node or configure the cluster?

We’re going to see how to create a custom Docker image for the popular document-oriented NoSQL database, Couchbase, and cluster a few containers together to make one awesome NoSQL cluster.

Before going further, we’re assuming that you have Docker installed somewhere and are ready to go. We’re not going to be creating a Docker Swarm in this example, so it is alright if all the containers exist on your local machine. In a production environment it is useless to have your distributed database exist on the same machine because if the machine dies, so do all of your database containers and data.

Deploying a Couchbase Server Container

If this is your first time playing around with Couchbase, it would benefit you to configure your Couchbase instance by hand to see what is happening. To take advantage of this, we’re going to deploy the official Couchbase image without first altering it. To deploy a container based on the official image, execute the following from your Docker CLI:

docker run -d -p 8091-8093:8091-8093 couchbase

The above command will deploy a container in detached mode and map the ports that Couchbase Server requires to the Docker host. This allows us to access Couchbase via our host, rather than through another container. The official Docker image is couchbase, as found on Docker Hub.

From your web browser, navigate to the Couchbase administrative dashboard via http://localhost:8091, or swap localhost with that of your Docker host if it is remote. You should see a screen that looks like the following:

Couchbase 4 Configuration Step 0

Choose to set up your node and we’ll be presented with a series of prompts, the first of which will be for configuring the node as the first in a cluster, or for joining an existing cluster. Since this is our first node, we will be defining the memory and services to be used.

Couchbase 4 Configuration Step 1

After choosing the appropriate specifications, proceed to the next step. The second step will allow us to choose optional sample Buckets that contain large amounts of fake data to play around with. These sample Buckets are not useful to us in this particular guide.

Couchbase 4 Configuration Step 2

After choosing from the optional list of sample Buckets, we’re prompted to set up a default Bucket. This Bucket is like any other Bucket in Couchbase, the only difference is that this is the first one we create.

Couchbase 4 Configuration Step 3

You may want to adjust the memory allocation on the default Bucket, but beyond that the default settings should be fine for this example. The fourth step is where we register Couchbase, which is completely optional, but you should do it anyways.

Couchbase 4 Configuration Step 4

This brings us into the fifth and final step of configuring a Couchbase Server node. We need to define an administrative username and password. This is critical for not only managing your Couchbase node, but also controlling your cluster as you have more than one node.

Couchbase 4 Configuration Step 5

At this point Couchbase Server should be completely usable as a single Docker container. While not terribly difficult to do, it was more time consuming than we want it to be. As you end up with more nodes in your cluster, you definitely don’t want to go through this every time.

This is where a custom Docker image would be nice.

Provisioning Couchbase Server Through a Custom Docker Image

By creating a custom Docker image of Couchbase, we can have a series of runtime commands configure Couchbase for us. Somewhere on your computer create a Dockerfile file without an extension. This will be the blueprint of our custom image for Couchbase. Now create a configure.sh file at the same location as your Dockerfile file. This will be the configuration script that is to be executed during the container deployment process.

Open the configure.sh file and include the following:

set -m

/entrypoint.sh couchbase-server &

sleep 15

curl -v -X POST http://127.0.0.1:8091/pools/default -d memoryQuota=512 -d indexMemoryQuota=512

curl -v http://127.0.0.1:8091/node/controller/setupServices -d services=kv%2cn1ql%2Cindex

curl -v http://127.0.0.1:8091/settings/web -d port=8091 -d username=$COUCHBASE_ADMINISTRATOR_USERNAME -d password=$COUCHBASE_ADMINISTRATOR_PASSWORD

curl -i -u $COUCHBASE_ADMINISTRATOR_USERNAME:$COUCHBASE_ADMINISTRATOR_PASSWORD -X POST http://127.0.0.1:8091/settings/indexes -d 'storageMode=memory_optimized'

curl -v -u $COUCHBASE_ADMINISTRATOR_USERNAME:$COUCHBASE_ADMINISTRATOR_PASSWORD -X POST http://127.0.0.1:8091/pools/default/buckets -d name=$COUCHBASE_BUCKET -d bucketType=couchbase -d ramQuotaMB=128 -d authType=sasl -d saslPassword=$COUCHBASE_BUCKET_PASSWORD

fg 1

Because Couchbase can be controlled via HTTP, we’re going to take advantage of this through a series of cURL commands. The first cURL command defines the memory quotas as seen in the first step of our manual deployment process. The second cURL defines the services to be used, also seen in the first step of our walkthrough.

This is where things change a bit.

curl -v http://127.0.0.1:8091/settings/web -d port=8091 -d username=$COUCHBASE_ADMINISTRATOR_USERNAME -d password=$COUCHBASE_ADMINISTRATOR_PASSWORD

The above command will set the administrative username and password for the node, but notice how we’re using $COUCHBASE_ADMINISTRATOR_USERNAME and $COUCHBASE_ADMINISTRATIVE_PASSWORD variables. Instead of hard-coding sensitive data into our custom image, we’re going to use variables that can be passed in during deployment of the container.

The final two cURL commands will create and configure our default Bucket.

Now that we have a configuration script, we can complete the Dockerfile file and build our custom image. Open the Dockerfile file and include the following:

FROM couchbase

COPY configure.sh /opt/couchbase

CMD ["/opt/couchbase/configure.sh"]

The above says we are using the official Couchbase image as the base of our image. During build time we are copying the configuration script into the image, and at runtime we are executing the script.

To build our image, execute the following from the Docker CLI:

docker build -t couchbase-custom /path/to/directory/with/dockerfile

To learn more about creating custom Docker images, check out a previous article I wrote on the subject called Build a Custom Docker Image for Your Containerized Web Application.

With the image available, execute the following to deploy a container with it:

docker run -d -p 8091-8093:8091-8093 couchbase-custom

When you navigate to http://localhost:8091 via your web browser, you’ll be able to log in with your administrative credentials and be ready to go. Very convenient for deploying many nodes of Couchbase.

Joining Couchbase Nodes into a NoSQL Cluster via the Administrative Dashboard

At this point we should have a custom image that we can deploy into any number of containers. The goal now is to deploy more than one container and create an actual cluster with replication.

We’re going to do something slightly different than what was already seen. We need to give each container a name and define the network that the containers operate on. We also need to define each variable that was used within the configuration script. Execute the following two commands:

docker run -d \
    -p 8091-8093:8091-8093 \
    -e COUCHBASE_ADMINISTRATOR_USERNAME=Administrator \
    -e COUCHBASE_ADMINISTRATOR_PASSWORD=password \
    -e COUCHBASE_BUCKET=default \
    -e COUCHBASE_BUCKET_PASSWORD= \
    --network="docker_default" \
    --name couchbase1 couchbase-custom

docker run -d
    -p 9091-9093:8091-8093 \
    -e COUCHBASE_ADMINISTRATOR_USERNAME=Administrator \
    -e COUCHBASE_ADMINISTRATOR_PASSWORD=password \
    -e COUCHBASE_BUCKET=default \
    -e COUCHBASE_BUCKET_PASSWORD= \
    --network="docker_default" \
    --name couchbase2 couchbase-custom

The above command will deploy two containers on the docker_default network. To prevent port mapping errors, each container will be mapped on a different set of ports on the host machine.

From the Couchbase administrative dashboard click the Server Nodes tab, then choose to add a new server. Enter the information of the other node. It is important to keep in mind that when two containers communicate to each other, they are not using localhost. First find the container IP and use that instead. On my machine they typically look like 172.19.0.x, but they could be different for you.

After the node has been added to the cluster, rebalance the cluster so the data is distributed evenly. Since Couchbase is a peer-2-peer architecture, it doesn’t matter which node you visit from here on out. You’ll get the same results.

Joining Couchbase Nodes into a NoSQL Cluster via the Command Line Interface or Scripts

The Couchbase administrative dashboard isn’t the only way to add nodes to the NoSQL cluster. In fact, you’ll probably not want to do it in production because it is time consuming. Instead you’ll probably want to use scripts.

Go ahead and deploy a few containers based on your custom image:

docker run -d \
    -p 8091-8093:8091-8093 \
    -e COUCHBASE_ADMINISTRATOR_USERNAME=Administrator \
    -e COUCHBASE_ADMINISTRATOR_PASSWORD=password \
    -e COUCHBASE_BUCKET=default \
    -e COUCHBASE_BUCKET_PASSWORD= \
    --network="docker_default" \
    --name couchbase1 couchbase-custom

docker run -d
    -p 9091-9093:8091-8093 \
    -e COUCHBASE_ADMINISTRATOR_USERNAME=Administrator \
    -e COUCHBASE_ADMINISTRATOR_PASSWORD=password \
    -e COUCHBASE_BUCKET=default \
    -e COUCHBASE_BUCKET_PASSWORD= \
    --network="docker_default" \
    --name couchbase2 couchbase-custom

Since they are launched in detached mode, we need to connect to one of them via interactive mode. This is essentially like connecting to a container via SSH.

Connect to one of the containers by executing the following:

docker exec -it couchbase1 bash

More information on connecting to detached Docker containers in interactive mode can be found in a previous article I wrote titled Connecting to a Detached Docker Container for Terminal Interaction.

Once connected we’re going to use the Couchbase CLI to control the cluster. From the command line, execute the following to add a different node to the currently connected to node:

/opt/couchbase/bin/couchbase-cli server-add \
    --cluster=localhost:8091
    --user Administrator \
    --password password \
    --server-add=172.19.0.3 \
    --server-add-username=Administrator \
    --server-add-password=password

Remember to pay attention to the container IP of the node you wish to add. It is not a local or standard network IP, it is that of your container network.

Conclusion

You just saw how to deploy a Couchbase NoSQL database cluster as Docker containers. This included creating a custom Docker image with a custom provisioning script, as well as running various commands for establishing a cluster.

You might be wondering why we didn’t use Docker volumes with our Couchbase containers. You could for data recovery, but ultimately when a container goes down, it should be re-added to the cluster and rebalanced without the expectation that it will work as is. After all, what if the data is stale?

While we did everything locally, this can easily be taken to the cloud. Using cloud solutions such as Digital Ocean and Linode work quite well, however, remember that you should only use one Couchbase container per node to prevent data loss in the event of a catastrophe.

A video version of this article can be seen below.

Nic Raboy

Nic Raboy

Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in C#, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Unity. Nic writes about his development experiences related to making web and mobile development easier to understand.