Earlier in the year I wrote about containerizing applications written in various development technologies that communicate with Couchbase Server. For example, I had written about deploying a Golang application with Docker, a Java application with Docker, and a Node.js application with Docker. This time around we’re going to take a look at how to deploy a PHP container that communicates with a Couchbase Server container.
We’re going to create an automatically provisioned Couchbase node and simplistic PHP application that writes and reads data from the Couchbase NoSQL node.
Let’s first define the project structure that will represent both containers:
1 2 3 4 5 6 7 8 9 10 11 |
root -- couchbase -- -- configure.sh -- -- Dockerfile -- php -- -- application -- -- -- index.php -- -- configuration -- -- -- php.ini -- -- Dockerfile -- docker-compose.yml |
Each container will have its own Dockerfile which will contain blueprint information for our setup. The docker-compose.yml file will build and deploy the containers using defined port and environment variable information.
Containerizing the PHP Application
Since this is a PHP tutorial, we’ll start by building our simple PHP application and containerizing it. Because we want to automate the deployment, we’ll be developing our php.ini file locally and copying it over during the build process.
Before we get to that part, let’s add some code to the index.php file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?php header("Content-Type: application/json"); $cluster = new CouchbaseCluster("couchbase://" . getenv("COUCHBASE_HOST")); $bucket = $cluster->openBucket(getenv("COUCHBASE_BUCKET_NAME"), getenv("COUCHBASE_BUCKET_PASSWORD")); try { $result = $bucket->get("nraboy"); } catch (CouchbaseException $e) { $bucket->insert("nraboy", array( "name" => "Nic Raboy", "social_media" => array( "twitter" => "https://www.twitter.com/nraboy", "website" => "https://www.thepolyglotdeveloper.com" ) )); $result = $bucket->get("nraboy"); } echo json_encode($result->value); ?> |
In the above code we’re saying that any data printed will be JSON format. We’re establishing a connection to a Couchbase cluster and opening a particular Bucket in that cluster. The catch here is that we’re using environment variables to define the cluster and Bucket. These will be set in the deployment process.
With the application connected, it will try to get a document from Couchbase by key. If that document doesn’t exist, it will be created and then obtained. The obtained document will be printed as a result.
Like I mentioned earlier, this is a simple application, nothing fancy. Now we can focus on the Docker aspect of this application.
Open the Dockerfile and include the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
FROM php:5.6.30-apache RUN apt-get update RUN apt-get install -y wget lsb-release RUN wget http://packages.couchbase.com/releases/couchbase-release/couchbase-release-1.0-2-amd64.deb RUN dpkg -i couchbase-release-1.0-2-amd64.deb RUN rm couchbase-release-1.0-2-amd64.deb RUN apt-get update RUN apt-get install -y libcouchbase-dev build-essential php5-dev zlib1g-dev RUN pecl install pcs-1.3.3 RUN pecl install couchbase WORKDIR /var/www/html COPY ./configuration/php.ini /usr/local/etc/php/ COPY ./application/ /var/www/html/ RUN chown www-data:www-data . -R |
The above says that we’re going to be using an Apache image. If you’ve ever used Couchbase with PHP, what comes next will look very familiar. All the dependency gather was taken straight from the Couchbase PHP documentation. The RUN
command means that the dependencies will be gathered at build time, not run time.
With the dependencies available, the php.ini file is copied into the image as well as the index.php file. This brings us to the php.ini file.
Instead of pasting a long and nasty chunk of configuration, it is best you just download the php.ini file from the official PHP GitHub repository. The only change we’re making is in regards to the extensions. Per the Couchbase PHP documentation, we need to add the following:
1 |
extension=couchbase.so |
Find the extensions section and add it there.
At this point the PHP image can be built and we can deploy it as a container. However, we’re going to plan ahead and create a Compose file.
Open the docker-compose.yml file and include the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
version: '2' services: php: build: ./php ports: - 8080:80 environment: - COUCHBASE_HOST=couchbase - COUCHBASE_BUCKET_NAME=default - COUCHBASE_BUCKET_PASSWORD= restart: always |
The above defines a service called php
with port mappings and environment variables. These variables match what we have in the PHP application. The image will be built from the Dockerfile found in the PHP project.
If you set the COUCHBASE_HOST
to something remote, we’re good to go, but for this example we’re going to use another container.
Containerizing Couchbase Server
The goal in containerizing Couchbase is that we’ll be automating it. There already exists a Docker image for Couchbase, but it isn’t pre-provisioned which can take time during a deployment process.
Open the Dockerfile file the Couchbase project and include the following:
1 2 3 4 5 |
FROM couchbase COPY configure.sh /opt/couchbase CMD ["/opt/couchbase/configure.sh"] |
The above says that we’re going to use the official Couchbase image, but we’re going to copy a script into it and then run it at runtime. This script will provision the instance automatically.
Open the configure.sh file and include the following commands:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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 sleep 15 curl -v http://127.0.0.1:8093/query/service -d "statement=CREATE PRIMARY INDEX ON `$COUCHBASE_BUCKET`" fg 1 |
Couchbase Server has its own RESTful API which we’re trying to consume with a bunch of cURL commands. We are defining memory quotas, which services exist in the node, and authentication information.
Notice that many of the commands include environmental variables like $COUCHBASE_ADMINISTRATOR_USERNAME
. This is because we’re going to pass them in via the docker-compose.yml file just like we did with the PHP application.
Open the docker-compose.yml file and make it look like the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
version: '2' services: couchbase: build: ./couchbase ports: - 8091:8091 - 8092:8092 - 8093:8093 environment: - COUCHBASE_ADMINISTRATOR_USERNAME=Administrator - COUCHBASE_ADMINISTRATOR_PASSWORD=password - COUCHBASE_BUCKET=default - COUCHBASE_BUCKET_PASSWORD= php: build: ./php ports: - 8080:80 environment: - COUCHBASE_HOST=couchbase - COUCHBASE_BUCKET_NAME=default - COUCHBASE_BUCKET_PASSWORD= restart: always |
We’ve included another service called couchbase
with a bunch of port mappings and environment variables. There is something important to note here though. Remember the COUCHBASE_HOST
in the PHP section? It has a host which must match the service name of our database which is couchbase
.
Deploy the Containers with Docker
With the foundation in place, it is time to deploy the two containers so we have a functional set of microservices.
From the Docker CLI, execute the following:
1 2 |
docker-compose run -d --service-ports --name couchbase couchbase docker-compose run -d --service-ports --name php php |
The above commands will build and deploy each of the images with the ports defined in the Compose file. From the web browser, http://localhost:8091 should get you to the Couchbase Server dashboard, and http://localhost:8080 should get you to your PHP application.
With success, you should see information saved to the database and displayed on the screen.
Conclusion
You just saw how to containerize and deploy a PHP application that communicates with a Couchbase NoSQL container. While our choice of application was simple, it can easily be extended to something more complicated using any of the available PHP frameworks.
This same guide can be seen with Node.js, Golang, and Java. If you’d like to learn more about containerizing Couchbase Server, I wrote a more thorough version here.
For more information on the Couchbase PHP SDK, check out the Couchbase Developer Portal.
It is too old, Can we have sdk 3.0?