Running Cron Jobs on Cloud Foundry

Many cloud applications need to run some sort of scheduled tasks for chores like processing statistics or doing internal housekeeping. There are two different strategies to implement scheduled tasks to cloud applications running on Cloud Foundry. You can either build scheduling and tasks into the application itself or schedule and run the task in separate containers

Some application frameworks like Spring include some built-in scheduling support. However, this scheduling support does not include a distributed coordination mechanism. This means that an application horizontally scaled to multiple instances will each run the scheduled task individually. Depending on the nature of the task, this may cause observable side effects like sending emails to your customers to be repeated.

It's thus preferable to have a central entity for scheduling. You could of course use e.g. a Java Spring App that needs approximately 1G of RAM to do that for you, but that would be very wasteful. Instead, we can build a simple cron scheduler that runs on 16 MB of RAM to get reliable task scheduling for just a few cents per month.

The task scheduler can then execute arbitrary scripts or code, for example to:

  • invoke an https endpoint on your application to perform the task
  • queue a message on RabbitMQ for processing by a worker
  • trigger execution of the job in a seperate Cloud Foundry Task Container

meshcloud\'s cf-cron scheduler

Our sample repository demonstrates how to run scheduled tasks on Cloud Foundry with a very small footprint (8 to 16 MB RAM) using a traditional crontab. Traditional cron daemons need to run as root and have opinionated defaults for logging and error notifications. This makes them unsuitable for running in a containerized environment like Cloud Foundry. Instead of a system cron daemon we\'re thus using supercronic to run our cron tab.

How it works

This application is built using the binary buildpack and executes supercronic on the crontab file. The crontabfile specifies all your cron jobs. To add additional jobs, simply add a new line which specifies a schedule and command to the crontab.

Note: By default, supercronic will log all output to stderr so we redirect that to stdout in our cf manifest.

You can also include additional scripts and binaries to execute more complex actions. This example allows you to install apt and debian packages to use in your cronjobs. You can specify these packages in apt.yml and they will be installed during staging by apt-buildpackcourtesy of the magic multi-buildpack.

After cf pushing this sample app to Cloud Foundry, you can see that it happily executes the jobs from the crontab in the log output:

2018-03-05T10:59:00.00+0100 [APP/PROC/WEB/0] OUT time="2018-03-05T09:59:00Z" level=info msg=starting iteration=237 job.command="echo "hello world, every 2 seconds"" job.position=1 job.schedule="*/2 * * * * * *"
2018-03-05T10:59:00.00+0100 [APP/PROC/WEB/0] OUT time="2018-03-05T09:59:00Z" level=info msg="hello world, every 2 seconds" channel=stdout iteration=237 job.command="echo "hello world, every 2 seconds"" job.position=1 job.schedule="*/2 * * * * * *"
2018-03-05T10:59:00.00+0100 [APP/PROC/WEB/0] OUT time="2018-03-05T09:59:00Z" level=info msg="job succeeded" iteration=237 job.command="echo "hello world, every 2 seconds"" job.position=1 job.schedule="*/2 * * * * * *"
2018-03-05T10:59:00.05+0100 [APP/PROC/WEB/0] OUT time="2018-03-05T09:59:00Z" level=info msg="cf version 6.34.1+bbdf81482.2018-01-17" channel=stdout iteration=7 job.command="cf --version" job.position=0 job.schedule="*/1 * * * *"
2018-03-05T10:59:00.05+0100 [APP/PROC/WEB/0] OUT time="2018-03-05T09:59:00Z" level=info msg="job succeeded" iteration=7 job.command="cf --version" job.position=0 job.schedule="*/1 * * * *"

Scheduling Cloud Foundry Tasks

While the cron container here is designed to be small and lightweight, you may want to use it to trigger more resource intensive tasks and processes. When a simple curl to an http endpoint is not enough to kick off such a task on your existing app, Cloud Foundry Tasks are a great solution to run these processes.

This sample repository thus includes instructions to install the cf cli tool which you can use to trigger such a task using a meshcloud Service User.


Connect Database to Cloud Foundry

Securely connecting to Service Instances on Cloud Foundry

To connect to a managed service instance on your Cloud Foundry space, most developers use service keys. A service key is a set of authentication credentials that allows you to connect to your database instance via a public IP address and port. While this is quick and easy to do, we do not recommend keeping service keys open for extended periods of time. Instead, you should delete them as soon as possible and create a new service key anytime you need access again.

A more secure approach that does not involve exposing a connection to your database on a public IP is to spin up a shell container on Cloud Foundry and connect to it via cf ssh. This approach is also more suitable for long running or high performance operations that require close proximity between the database and the shell.

Here\'s how to do it showcased for MongoDB, but a similar approach also works for our other managed services like MySQL or PostgreSQL.

  1. Create an app named MARKDOWN_HASH8dbc90b062fdf4d2f370bf28f06aa883MARKDOWN<em>HASH</em> based on a docker container image containing the mongo cli. Tip: you can also specify a specific version using the appropriate container image tag, the example below uses :latest. Note that we tell Cloud Foundry that we need only very little RAM (128 MB), don\'t want a health-check on the App and that it doesn\'t need an HTTP route to be reachable from the outside. After all, we just want to ssh into this app.

    cf push -o mongo:latest mongocli --no-route --no-start -u none -m 128M
  2. Create a binding of the service instance to your new app. This makes a connection string available to the mongocli app that it can use to connect to the database instance on a private network, just like your proucution app does.

    cf bind-service mongocli my-mongodb
  3. Start the container, let it just run a bash

    cf push -o mongo:latest mongocli --no-route -u none -m 128M -c bash

That\'s it, now we can easily ssh into the container using cf ssh mongocli and run env to find our connection string in the VCAP_SERVICES variable. The connection string looks approximately like this:

VCAP_SERVICES={"MongoDB":[{
"credentials": {
"password": "abc",
"database": "db",
"uri": "mongodb://user:pw@ip1:27017,ip2:27017,ip3:27017/db",
"username": "xxx"
},
"syslog_drain_url": null,
"volume_mounts": [

],
"label": "MongoDB",
"provider": null,
"plan": "S",
"name": "my-mongodb",
"tags": [

]
}]}

Now you can simply run mongo mongodb://user:pw@ip1:27017,ip2:27017,ip3:27017/db and you're securely connected to your managed database instance - on a docker container running mongo shell on Cloud Foundry - connected via ssh.


Deploying Meteor Apps on Cloud Foundry

This repository demonstrates different ways to deploy Meteor applications on Cloud Foundry. There are at least three different ways to deploy Meteor JS applications on Cloud Foundry:

  • using a specialized meteor-js buildpack
  • using the general node-js buildpack
  • using your own docker container image

While a specialized meteor buildpack like meteor-buildpack-horse or cf-meteor-buildpack is a useful option, recent versions of meteor support simplified deployment on servers that provide just a node.js runtime environment. For this demonstration repository, we\'re focusing on this approach because the node.js buildpack is more widely used and better maintained.

The application we\'re going to deploy is located in the ./try-meteor folder of this repository. We also assume you have provisioned a Mongo DB service on your space. In Cloud Foundry you can create a dedicated service instance suitable for use with meteor like this:

cf create-service MongoDB M meteor-mongo

Using the node.js Buildpack

Build a meteor app bundle

On your local machine with the meteor cli installed, build a distributable package into the deploy-buildpack folder:

cd try-meteor && meteor build ../deploy-buildpack/. --server-only --architecture os.linux.x86_64

Building generates a try-meteor.tar.gz file with the meteor application bundled as a plain node.js application, with some helfpful instructions in its README.md file:

This is a Meteor application bundle. It has only one external dependency:
Node.js v8.9.3. To run the application:

$ (cd programs/server && npm install)
$ export MONGO_URL='mongodb://user:password@host:port/databasename'
$ export ROOT_URL='http://example.com'
$ export MAIL_URL='smtp://user:password@mailhost:port/'
$ node main.js

Use the PORT environment variable to set the port where the
application will listen. The default is 80, but that will require
root on most systems.

node.js buildpack wrapper

To deploy this tar.gz file on Cloud Foundry with the node.js buildpack we need to:

  1. upload and unpack the tar.gz bundle
  2. run npm install on the extracted bundle
  3. set the correct environment variables using a launcher js script

We can easily achieve that through a custom package.json that uses npm\'s postinstall and start script to execute these actions. You can find the package.json and all required files for the deployment in the ./deploy-buildpack folder.

Note: at the time of writing the bundles generated by meteor 1.6.0.1 machine lack the meteor-deque dependency so we just explicitly add that by hand.

{
  "name": "try-meteor",
  "private": true,
  "scripts": {
    "start": "node launcher.js",
    "postinstall": "tar -xf try-meteor.tar.gz && (cd bundle/programs/server && npm install)"
  },
  "engines": {
    "node": "8.9.3"
  },
  "dependencies": {
    "meteor-deque": "~2.1.0",
    "cfenv": "1.0.4"
  }
}

Have a look at the launcher.js file if you want to change service names etc. The final bit that we need is a Cloud Foundry Manifest file to describe our application:

---
applications:
- name: try-meteor-app
  memory: 512M
  instances: 1
  buildpack: https://github.com/cloudfoundry/nodejs-buildpack
  services:
    - meteor-mongo

We're all set now, a simple cf push and your app should be up and running on the cloud.

Using a Docker Container

The next option is to use a docker-based deployment of the application. This requires that we build our own docker image of the application and publish it to a docker registry.

You can find the code for the docker-based deployment of our sample application in the MARKDOWN_HASHd786272e16707f3074a294d21f8b83a0MARKDOWN<em>HASH</em> folder. The docker image used in this example is based on the node:8-alpine base image. However, before we can build our container we need to build our meteor application and extract it:

cd try-meteor && meteor build ../deploy-docker/. --server-only --architecture os.linux.x86_64
cd ../deploy-docker && tar -xf try-meteor.tar.gz && rm try-meteor.tar.gz

The docker deployment demonstrated in this repository also uses the same launcher.js script introduced above to automatically initialize meteor environment variables from their Cloud Foundry counterparts. With that out of the way, let\'s build and push the docker image

docker build -t meshcloud/meteor-cf-example .
docker push meshcloud/meteor-cf-example:latest

With the container available in a docker registry, we can push it to Cloud Foundry by specifying the docker image in the manifest:

---
applications:
- name: try-meteor-app-docker
  memory: 512M
  instances: 1
  docker:
  image: meshcloud/meteor-cf-example
  services:
  - meteor-mongo

Now all that\'s left to do is a simple cf push and your app should be up and running on Cloud Foundry in no time.

iDevBook01:deploy-docker jr (master *) $ cf push
Pushing from manifest to org meshcloud-demo / space aproject as c9f7d64c-404d-4b29-b719-b2359f6c8157...
Using manifest file /Users/jr/dev/demo/meteor/deploy-docker/manifest.yml
Getting app info...
Updating app with these attributes...
name: try-meteor-app-docker
docker image: meshcloud/meteor-cf-example
command: node launcher.js
disk quota: 1G
health check type: port
instances: 1
memory: 512M
stack: cflinuxfs2
services:
meteor-mongo
routes:
try-meteor-app-docker.cf.eu-de-darz.msh.host

Updating app try-meteor-app-docker...
Mapping routes...

Stopping app...

Waiting for app to start...

name: try-meteor-app-docker
requested state: started
instances: 1/1
usage: 512M x 1 instances
routes: try-meteor-app-docker.cf.eu-de-darz.msh.host
last uploaded: Mon 12 Feb 10:25:29 CET 2018
stack: cflinuxfs2
docker image: meshcloud/meteor-cf-example
start command: node launcher.js

state since cpu memory disk details
#0 running 2018-02-12T10:12:23Z 0.1% 38.2M of 512M 1.3M of 1G

iDevBook01:deploy-docker jr (master *) $

Cloud native deployment for Single Page Applications

Single Page Applications (SPAs) are a popular way to deliver modern web apps. With SPAs, users download executable Javascript code that dynamically renders content in their browser, rather than retrieving pre-rendered pages from a server application. The server application is freed from rendering HTML and instead is only responsible for providing a re-usable API to its data. In this post, we're going to look at how we can leverage Cloud Foundry to do cloud native deployments for SPAs.

Delivering SPAs on Cloud Foundry

To deliver an SPA to its users, a web server only needs to serve the static assets making up the SPA. This also means that the web server can leverage HTTP caching to optimize delivery. On Cloud Foundry, the best way to serve an SPA is by using the Staticfile buildpack. A cf push using this buildpack will bundle your artifacts with an nginx server. To get started, let\'s assume you have all files of your web-root in your current working directory. We now create a short manifest.yml for Cloud Foundry:

---
applications:
- name: my-spa
  instances: 1
  memory: 64M
  buildpack: https://github.com/cloudfoundry/staticfile-buildpack.git

All we need to do now is to execute cf push and your SPA will be up and running in the cloud under a randomly-assigned URL shortly.

Scaling your SPA

The nginx container built for serving your files does not need a lot of memory, which makes it very cost-efficient to run on Cloud Foundry. To achieve high-availability and scale the service under load, we can easily use Cloud Foundry to scale it to two or more instances using cf scale my-spa -i $X.

Injecting Configuration

Cloud native applications should adhere to the 12-factor principles. One of the twelve factors is configuration through the environment. This allows us to deploy the same artifacts to different environments (e.g. dev and production) while keeping all configuration data separately. Cloud Foundry optimally supports workloads that implement this principle by providing configuration through environment variables.

At runtime, we need to inject this configuration data into the application. Because we want to keep serving our application as static SPA assets through nginx for optimum performance, there\'s no server side code execution like with PHP or a different backend language. However, we can still achieve dynamic injection of configuration data through the use of environment variables and server side includes.

The staticfile buildpack has a lot of useful configuration options. The most powerful of course is that it allows us to provide our own template for nginx.conf, which is evaluated during staging. In this template, we can access environment variables configured for the app on Cloud Foundry. For reference, here\'s the default config used by the buildpack.

For our custom template, we\'ll start with this portion of an nginx.conf file:

server {
  listen <%= ENV["PORT"] %>;
  server_name localhost;

  <% if ENV["INJECT_ENVIRONMENT"] %>
  location /inject-environment {
    default_type application/json;
    return 200 '<%= ENV["INJECT_ENVIRONMENT"] %>';
  }
  <% end %>

location / {
  root <%= ENV["APP_ROOT"] %>/public;
  index index.html index.htm Default.htm;
  ssi on;
 }
}

This creates a location mapping in nginx for the path /inject-environment that will respond with HTTP Status Code 200 OK and a static string read from the INJECT_ENVIRONMENT environment variable. This is useful if we can buid our SPA to retrieve this configuration data at runtime. But what if we want to load configuration data before the JavaScript in our application executes?

We can leverage an HTML feature called server-side-includes for this, which we enabled using the ssi on instruction in the nginx.conf above. In the index.html document that loads the javascript code of our SPA, we add a SSI instruction to include the string returned by the /inject-environment endpoint:

<!--#include virtual="/inject-environment" -->

Because a server-side-include does just plain text concatenation, we need to define our environment variable to be a "smart" string. So let\'s make it a <script> tag that executes some javascript that will put a JSON object into the global window. The easiest way to define this variable is to edit our app\'s Cloud Foundry manifest file:

---
applications:
- name: my-spa
  instances: 1
  memory: 64M
  buildpack: https://github.com/cloudfoundry/staticfile-buildpack.git
  env:
    INJECT_ENVIRONMENT: |
      <script type="text/javascript">window["INJECTED_ENVIRONMENT"] = {
        production: false,
        baseUrls: {
          api: "https://api.example.com"
        }
      };</script>

To access configuration data, your SPA can simply pick it up from the global window["INJECTED_ENVIRONMENT"] variable.

Pro tip: To dynamically reconfigure your application on Cloud Foundry at runtime, change your environment variables and restage the application. To stage the new version of the application while keeping the current one available, you can use the bg-restage cli plugin.

Monitoring

Cloud Foundry automatically collects your application\'s requests as they pass through the Cloud Foundry router. Entries like this are tagged with [RTR/$] in the logs. Additionally, Cloud Foundry will also collect all logs emitted by nginx, indicated by the [APP/$] tag in the logs. Here\'s how that looks like in practice:

Retrieving logs for my-spa panel in org meshstack / space production as demo@meshcloud.io...

2018-01-28T15:46:59.99+0100 [APP/PROC/WEB/0] OUT 95.222.25.157, 172.16.105.69 - https - - - [28/Jan/2018:14:46:59 +0000] "GET / HTTP/1.1" 200 1044
2018-01-28T15:46:59.99+0100 [RTR/0] OUT panel.meshcloud.io - [28/01/2018:14:46:59.994 +0000] "GET / HTTP/1.1" 200 0 1032 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36" 172.16.105.69:38656 x_forwarded_for:"95.222.25.157, 172.16.105.69" x_forwarded_proto:"https" vcap_request_id:908529e7-3f5a-4a5c-40c2-d79419a3e5ae response_time:0.003193066 app_id:bc1e736b-6b8c-48b0-a390-8c8ac1aeae0a app_index:0

You can customize this logging in your nginx.conf file using the log_format configuration option.


Step-by-Step: Deploying a Java Spring App to Cloud Foundry

You are a developer and have been dreaming of someone to take care of deploying and operating your cloud-native applications? With Cloud Foundry you might have found a solution to this.

What is Cloud Foundry?

Cloud Foundry is a container-based open-source software for application deployment. It enables developers to deploy apps of all common programming languages, such as Java, Python, Node.js, .NET Core or Go within minutes. The platform takes care of deployment, scaling and administration of cloud-native applications throughout their lifecycle.

What you need to get started

  • An account to use Cloud Foundry. As Cloud Foundry is an open-source platform there are multiple providers.
  • If not done yet, you should get started by installing the Cloud Foundry CLI. Type cf to your terminal to confirm that the installation was successful.
  • If not there already, you need to install Gradle.

So let's get our hands dirty now and deploy an application on the platform.

Step 1: Deploying an application to Cloud Foundry

In general Cloud Foundry offers 2 ways to deploy applications. You can either let the platform build a container out of your application and the integrated buildpacks or, in case you already have a Docker container up and running, you can deploy your Docker container to Cloud Foundry. We will choose the first way in this example and will show how to deploy a Java Spring application.

To start, we need to login to Cloud Foundry. If you are using meshcloud you do this, by choosing a location in the meshPanel and then executing the command shown in the CLI-Access tab.

It will be something like this, depending on the location you chose.

$ cf api https://api.cf.eu-de-netde.msh.host

Now, we need to authenticate against this endpoint, by executing:

$ cf login -sso

You will be asked for a passcode, which you also get from the meshPanel (CLI-Access).

We will use an application that is provided within the Cloud Foundry sample apps on Github.  It is an app to store music albums. While it has an integrated in-memory database, you can easily connect it to one of the databases in our marketplace to get persistence. We will get there in a moment. Let's  clone the code first:

$ git clone https://github.com/cloudfoundry-samples/spring-music.git

and access the folder.

Once you navigated to the app folder, you can build the app:

$ ./gradlew clean assemble

And push it to the cloud:

$ cf push

And there you are: The app is running.

You should see something like this. Have a look at the manifest.yml file in the app folder. It contains the specifications of name, memory, route, etc. for your app.

You can reach the app's web interface by copying the url to your browser.  Changes in the app will be stored in-memory. However, this is no long-term solution, as your are currently only running a single instance of your app. A restart will lead to a loss of your changes. So what we are going to do next is to bind the app to a persistent database and scale it up to 3 instances.

Step 2: Binding a Data Service to your application

A common microservice architecture consists of multiple apps and services like databases or message queues for communication. You can provision services from the Cloud Foundry Marketplace.

You reach the marketplace by executing:

$ cf marketplace

in your terminal. As a result you get a list of services that are currently offered on the platform. Let's create a MongoDB service to bind to our application.

$ cf create-service MongoDB S musicDB

We are specifying the database, choosing a plan and a name for the database. The database will be created straight away. You will see it in your service list:


$ cf services
Getting services in org meshcloud-demo / space aproject as c9f7d64c-404d-4b29-b719-b2359f6c8157...
OK

name              service              plan              bound apps               last operation
musicDB           MongoDB              S                                           create succeeded

Now we can bind the database to our app with a single command.

$ cf bind-service spring-music musicDB

This will cause changes within the app to be persistent.

Step 3: Scaling your application

As we saw in our manifest.yml file and the CLI, we just started a single instance of the application. If you have high-availability requirements, you should always run a minimum of 2 app instances. You can easily scale your application at any time. We will now scale our app horizontally to 4 instances.

$ cf scale spring-music -i 4

Alternatively, you can also scale vertically, increasing RAM or disk of your application instance.

 

Congratulations! You did it.


New Meshcloud Features

December Release Notes (2017)

New meshcloud Features

We are happy to introduce you to a couple of new features that we have been working on in the past couple of weeks. We hope you'll enjoy them.

OpenStack upgrade

We upgraded our platform from OpenStack Mitaka to Ocata in september. This change has improved platform stability and will enable us to include further services soon. Stay tuned, we will let you know.

Improved Cloud Foundry integration

If you already are a regular Cloud Foundry user, you probably have realized that accessing the Cloud Foundry CLI from our meshPanel has become much easier. Clicking the “Get Passcode”-Link will directly display the Passcode that you need to authenticate against the Cloud Foundry CLI. All intermediate steps have been removed.

Improved resource statistics

To give you a better overview on your resource usage, we extended our stats section in your project dashboard. You now have an overview at first glance on what is running in your project.

Bind volumes to instances via meshPanel

You are now able to create volumes and bind them to your instances via our meshPanel. There is no need to use the OpenStack CLI for this anymore.

Change security groups of running instances

Flexibly add or remove security groups from your running VMs from our meshPanel. It might have happened to you that you created a VM and forgot to make some ports accessible that you need for later use. You can now flexibly edit the security groups related to each of your instances.


The Cloud Foundry-ABC

If you are just about to run your first application in Cloud Foundry, this is the place to start. First of all: Congratulations! Cloud Foundry is a great technology used by developers and it is amazing how it can make your life easier. If you feel like you have been a sys admin, even though you thought of yourself as a developer, I promise, you will love Cloud Foundry. Sys admin time is over, you are finally free to work on your code. Do you think this sounds like Docker or Kubernetes? Wait for it, it can get even easier than this.

In this article, we'll just get you familiar with the most common terms of the Cloud Foundry world. So once we dig deeper, you'll know what we are talking about.

Target

There are multiple public Cloud Foundry installations across the world. meshcloud offers a couple of them within Germany. So once you start working with Cloud Foundry, you will have to define, which of the installations you are communicating to. Each of those installations is called a target. In order to switch locations within the meshcloud Federation, you will also have to switch target.

For example

cf api https://api.cf.eu-de-darz.msh.host

will lead you to our DARZ location in Darmstadt.

CLI

"CLI" stands for command line interface. The Cloud Foundry CLI will help you to interact with Cloud Foundry, to push your applications, scale them, create services and so on. In order to use Cloud Foundry, you will download and install the Cloud Foundry CLI tools first. Once you installed it, you can use your terminal or Powershell to execute functions, which in the background communicate to the Cloud Foundry API via REST calls. Every call you make to a function, simply starts with cf.

Organization

A Cloud Foundry Organization defines a single tenant on the system. So within meshcloud this is one customer account. In order to see the organization that you are currently working with in your terminal just type

cf orgs

and the result will be something like this:

 

Getting orgs as xyz...

name
meshcloud-demo

Space

Within meshcloud, a Cloud Foundry Space represents a meshcloud project. You may have multiple spaces/projects within your organization. All your applications and service instances will be scoped to a specific space/project. In order to see the spaces/projects you have access to within your organization, you can type:cf spaces

Services

We differentiate applications and services within Cloud Foundry. While you bring the application to the platform. As meshcloud, we offer various stateful services for you to use. Services are offered in the so-called Market Place. To see the market place, just type: cf marketplace and you will see a list of services to choose from. They are mainly databases and message queues. Each service is offered in various plans, that may differ in size or performance. For example there are shared database plans (our "S" plans) and dedicated database plans (our "M" and "L" plans) within meshcloud's Cloud Foundry.

 

And that's it. That is the basic vocabulary that you should be familiar with, when starting to use Cloud Foundry.


Hosting your WordPress Website in Cloud Foundry

If you are looking for a way to host your WordPress website and want to enjoy the freedom of the cloud, here is how you do it! This tutorial is based on Cloud Foundry.

Getting started

At first we have to download and unzip WordPress to prepare it for the Cloud Foundry deployment. In our example, we download the English version from the WordPress homepage. If you need another version, you can find it under this link.

$ wget https://wordpress.org/latest.zip
$ tar xzvf latest.zip
$ cd WordPress

If you are using a Mac and don't have wget installed, you can install it via hombrew. brew install wget

Now we have to start with the customisation for the cloud use. Being in the WordPress directory now, we have to create the ".bp-config" folder where we'll create the "options.json" file that contains the PHP extensions we need to run WordPress.

$ mkdir .bp-config
$ nano .bp-config/options.json
$ cat .bp-config/options.json
{
"PHP_EXTENSIONS": ["mysql", "bz2", "zlib", "curl", "mcrypt", "mbstring", "mysqli", "gd", "zip"]
}

Prepare Database

Having done that, we have to prepare our database. The first thing to do when a Database is needed in Cloud Foundry is to start a service. To see which services are available in your CF Infrastructure type:

$ cf marketplace
service plans description
MongoDB S*, M*, L* MongoDB Instances
MySQL S*, L*, M* MySQL Instances
PostgreSQL S*, M*, L* PostgreSQL Instances
RabbitMQ S*, M*, L* RabbitMQ Instances

For WordPress we need a MySQL database. You have to decide which plan you want to choose and give the database a descriptive name. Now you can create the service.

$ cf create-service MySQL S WordPress

After doing so, we have to link the credentials of our newly created database in our wp-config. One of the key advantages of cloud deployment is that you can configure your software completely dynamically, so you can deploy it anywhere anytime. To do so, we have to read the database connection information dynamically out of the Cloud Foundry environment instead of referencing to a concrete database. The "diff" command shows the difference between the files. You don't have to run it yourself it only shows you what you have to change in order to get your site running ("-"-Lines are old +-"Lines" are new).

$ cp wp-config-sample.php wp-config.php
$ nano wp-config.php
$ diff wp-config-sample.php wp-config.php

--- wp-config-sample.php 2015-12-16 10:58:26.000000000 +0100
+++ wp-config.php 2017-10-13 14:34:31.000000000 +0200
@@ -18,18 +18,27 @@
* @package WordPress
*/

+
+
+$services = json_decode($_ENV['VCAP_SERVICES'], true);
+$service = $services['MySQL'][0]['credentials']; // pick the first MySQL service
+
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
-define('DB_NAME', 'database_name_here');
+define('DB_NAME', $service['database']);
+
+

/** MySQL database username */
-define('DB_USER', 'username_here');
+define('DB_USER', $service['username']);
+

/** MySQL database password */
-define('DB_PASSWORD', 'password_here');
+define('DB_PASSWORD', $service['password']);

/** MySQL hostname */
-define('DB_HOST', 'localhost');
+define('DB_HOST', $service['host'] . ':' . $service['port']);
+

/** Database Charset to use in creating database tables. */
define('DB_CHARSET', 'utf8');
@@ -46,14 +55,14 @@
*
* @since 2.6.0
*/
-define('AUTH_KEY', 'put your unique phrase here');
-define('SECURE_AUTH_KEY', 'put your unique phrase here');
-define('LOGGED_IN_KEY', 'put your unique phrase here');
-define('NONCE_KEY', 'put your unique phrase here');
-define('AUTH_SALT', 'put your unique phrase here');
-define('SECURE_AUTH_SALT', 'put your unique phrase here');
-define('LOGGED_IN_SALT', 'put your unique phrase here');
-define('NONCE_SALT', 'put your unique phrase here');
+define('AUTH_KEY', 's1,d-+8?BFD$n`|0r+sk[/O<e7.86={p');
+define('SECURE_AUTH_KEY', '=|DiG2C+Y1FLKFIZv_S#GZUvfz~Z<FkI#qGV=U25r5ofI). iZZ:atO7R6ru@ms]&C/=K5VxImw#du$}PfiO=?Qc&e-1}Jc*yI$;/87r{!}-Qq9');
+define('SECURE_AUTH_SALT', '.qUX{|m?o4j-(Bs2%6|Sf=^wT<y1dJ-+RV&BTfhEqNi`VB,+?i)DPC5r-FcJe9d<');
+define('LOGGED_IN_SALT', '&ah.M&Vij;X;[85Ox,}Z10PT#f ssFp5UjNU<?5LnK+]1ICBq*E{%8H@v(_Y#Jwz');
+define('NONCE_SALT', '2f3kM}yX5gTJ]AD~3P(/P~N#L&y*,A-0ldJ-wTr-h(Jild]IAW{K])^5<0qP `');

We initialised a php variable called "services", got the 'VCAP_SERVICES'-Json out of "$_ENV" and decoded it. Then we grabbed the first MySQL service credentials and saved it to the variable "service". Now we have the credentials in our service variable and can use them to initialise WordPress. Due to security concerns, we removed the salts of our example project. Just follow the description in the config file to create your own.

If you have problems establishing the database connection, you can check the content of the environment variable by using the following command.

cf env $APPNAME

Pushing WordPress to Cloud Foundry

Before we can finally push the app, we have to create the "manifest.yml" file.

---
applications:
- name: wordpressmeshcloud
memory: 256M
services:
- wordpress

Let Cloud Foundry do it's magic now.

cf push

How to Proceed

If you followed the steps, you should now be able to reach your WordPress blog with the browser of your choice. To get the application's URL and it's status you can use the CF CLI again. Simply type:

cf app wordpressmeshcloud

You should be able to see your url now, it's called "routes:" in Cloud Foundry.

For productive use make sure you use a datastore to persist your data. You can do so by using FUSE or a Wordpress-Plugin for Cloud Storage.


Cloud Foundry Intro: How using PaaS can save you a lot of time

Learn why Cloud Foundry is useful for your application deployment and see how easy you can speed up your deployment process:

Read more


Cloud Foundry Intro: Wie man mit PaaS viel Zeit sparen kann

Wann ist der Einsatz von Cloud Foundry sinnvoll und wie beginnt man am besten damit?

Read more