halo
goup
Arthur HALET
26 yearsbirth (birthday) - permis
tphone: 06-79-21-39-53

E: arthurh.halet@gmail.com
fr.png uk.png

Run Cloud Foundry with Codenvy


04/05/2015 19:40:40

This article is connected to https://github.com/cloudfoundry-community/codenvy-cfrunner/ which is a codenvy runner I've made for Cloud Foundry To understand what we will do in this post you need to know what is Codenvy and Cloud Foundry.

Cloud Foundry

Pivotal says it better than me so this is their short definition:

Pivotal Cloud Foundry® is a Platform as a Service (PaaS) that supplies developers with a ready-to-use cloud computing environment and application services, all hosted by virtualized servers on your existing public and private infrastructure.

You can have a look at this good overview from their new website: http://cloudfoundry.com/.

Codenvy

Codenvy is a really good Cloud based IDE, it looks like Eclipse in your browser, let's watch a 3min video made by Codenvy:

Eclipse-che run java code

Codenvy's runners

If you watch the previous videos you will see that Codenvy provides a runner that gives you the possibility to run your webapp directly from Codenvy.

These runners are, in fact, docker container which uses LXC, an operating-system-level environment virtualization for running multiple isolated Linux systems (containers) on a single Linux control host.

And use Dockerfile as a recipe to create tomcat server, apache server or to go runner and to start them with your source code.

Although Codenvy acts like a PaaS,it isn't, it is an IDE in your browser. These runners are really good for rapid development but why not to use the Cloud Foundry power to run your app?

Cloud Foundry is really good at auto-detecting your code's language, your dependencies, it can scale your app on runtime, create a good looking url and so on.

So let's create a Cloud Foundry runner for codenvy.

Cloud Foundry runner

The preexisting

On this page Codenvy demonstrates us how to deploy on CloudFoundry: http://docs.codenvy.com/user/paas/#cloud-foundry. Let's see their dockerfile and the reason why is not good enough for our purpose. Dockerfile:

FROM codenvy/jdk7
RUN mkdir /home/user/cf
WORKDIR /home/user/cf
RUN wget -q http://go-cli.s3-website-us-east-1.amazonaws.com/releases/v6.7.0/cf-cli_amd64.deb && \
    sudo dpkg -i cf-cli_amd64.deb

As you can see this Dockerfile just installs the Cloud Foundry command line and Codenvy indicates to use command line inside of container to run cf push or all the other commands directly in command line. But Cloud Foundry can tail logs, can deploy automatically and can use manifest.yml file to deploy a webapp.

Firstly: Deploy an app with our newly runner

Ok, so we want to deploy app automatically and to tail logs when we will run our Cloud Foundry Runner, we will use the original Dockerfile of Codenvy to make our own Dockerfile :

FROM codenvy/jdk7
# We need to define login, cloudfoundry api, organization and space
# For this we will use env var
ENV CF_API [your api]
ENV CF_LOGIN [your login or email]
ENV CF_PASSWORD [your password]
ENV CF_ORG [organization to target]
ENV CF_SPACE [space to target]

# We will create a new folder inside of our current user on docker
RUN mkdir /home/user/cf
WORKDIR /home/user/cf
# Like the other Dockerfile we download the cloudfoundry command line (but a newer)
RUN wget -q http://go-cli.s3-website-us-east-1.amazonaws.com/releases/v6.11.0/cf-cli_amd64.deb && \
    sudo dpkg -i cf-cli_amd64.deb

# We will create another directory and we will put our source code on to send
RUN mkdir /home/user/app
# Workdir can be assimilated to a cd command
WORKDIR /home/user/app
# Now we login to our Cloud Foundry instance
RUN cf login --skip-ssl-validation -a ${CF_API} -u ${CF_LOGIN} -p ${CF_PASSWORD} -o ${CF_ORG} -s ${CF_SPACE}
# We use the directive given by Codenvy to link source code to a docker volume
VOLUME ["/home/user/app"]
ENV CODENVY_APP_BIND_DIR /home/user/app

# We create an name for our app next we run cf push with this appname and finally we tailed our logs.
CMD appName="super-app"; \
cf push ${appName} >&1 && \
cf logs ${appName} >&1

What's happening on Codenvy on this end? You will see your Dockerfile being run and on this end you will have all the logs from your app in your Codenvy console.

Secondly: Use manifest from Cloud Foundry to deploy your app

As you can see we need to provide a name for our app directly in the Dockerfile which is not very flexible and if you want to change memory or instance number you will need to change your Dockerfile again.

Hopefully Cloud Foundry uses the definition file called manifest.yml this file indicates the service you need, the name of your app, the env var you want inside your app... All you need to do is to put a manifest at your root project directory.yml and to change few things inside our Dockerfile (we will get the app name from the manifest.yml to tail logs).

Your new manifest.yml:

---
# My manifest file
applications:
- name: 'super-app'
  memory: 1G
  instances: 1

The new Dockerfile:

FROM codenvy/jdk7
ENV CF_API 
ENV CF_LOGIN 
ENV CF_PASSWORD 
ENV CF_ORG 
ENV CF_SPACE 

RUN mkdir /home/user/cf
WORKDIR /home/user/cf
RUN wget -q http://go-cli.s3-website-us-east-1.amazonaws.com/releases/v6.11.0/cf-cli_amd64.deb && \
    sudo dpkg -i cf-cli_amd64.deb

RUN mkdir /home/user/app
WORKDIR /home/user/app
RUN cf login --skip-ssl-validation -a ${CF_API} -u ${CF_LOGIN} -p ${CF_PASSWORD} -o ${CF_ORG} -s ${CF_SPACE}
VOLUME ["/home/user/app"]
ENV CODENVY_APP_BIND_DIR /home/user/app

# We get the appName from the manifest.yml, we remove the `-` in front of `name` and we take the name with awk.
# By default when you do cf push the cf cli will try to find a manifest file
CMD appName=`cat manifest.yml | grep name | sed 's/-/ /' | awk '{print }'`; \
cf push >&1 && \
cf logs ${appName} >&1

Lastly: Redirect Codenvy url to our app url

Codenvy provides url like this: http://runner22.codenvycorp.com:52639/ when a runner finishes the process of giving you access to your app. As we deploy on Cloud Foundry with our own domain url we want to link this kind of url with our Cloud Foundry url. My solution is to serve something inside my container to redirect the url to my Cloud Foundry app by clicking on the url, provided by codenvy. .

The final docker file:

FROM codenvy/jdk7
ENV CF_API 
ENV CF_LOGIN 
ENV CF_PASSWORD 
ENV CF_ORG 
ENV CF_SPACE 

# Php5 has a command to run a tiny webserver so we will install php5-cli to be able to use it
RUN sudo apt-get update
RUN sudo apt-get -y install php5-cli

RUN mkdir /home/user/cf
WORKDIR /home/user/cf
RUN wget -q http://go-cli.s3-website-us-east-1.amazonaws.com/releases/v6.11.0/cf-cli_amd64.deb && \
    sudo dpkg -i cf-cli_amd64.deb
RUN mkdir /home/user/app
WORKDIR /home/user/app

RUN cf login --skip-ssl-validation -a ${CF_API} -u ${CF_LOGIN} -p ${CF_PASSWORD} -o ${CF_ORG} -s ${CF_SPACE}
VOLUME ["/home/user/app"]
ENV CODENVY_APP_BIND_DIR /home/user/app

# To say to codenvy that we want a provided url we need to expose a port which our php server will listen to
EXPOSE 8080
ENV CODENVY_APP_PORT_8080_HTTP 8080

CMD appName=`cat manifest.yml | grep name | sed 's/-/ /' | awk '{print }'`; \
    # We need to get the domain url, with the cf cli, you can get all the domains available here, we will take the first one
    domain=`cf domains | sed -n '3p' | awk '{print }'`; \
    # We create the url as Cloud Foundry does, we take the appName and append the domain url to create our url
    url=`echo "http://${appName}.${domain}"`; \
    # We put in a php file the redirection
    echo "<meta http-equiv=\"refresh\" c URL=${url}\">" > toserve.php && \
    cf push >&1 && \
    # We serve the previous php file by running in background a php webserver
    (php -S 0.0.0.0:8080 toserve.php&) && \
    # We tail logs
    cf logs ${appName} >&1

To go further

  1. We could do better to get the domain url. For that we could look at first, in the manifest file and fallback to the first domain found with cf domains if no domain has been found inside manifest file.
  2. Each time you modify your code you need to re-run the runner, we could use for example Webdav server to push our modified code inside Cloud Foundry without re-runing our runner
  3. Codenvy on-prems uses puppet recipe to install Codenvy in your infrastructure, we could use bosh-release to link Codenvy and Cloud Foundry together and we can continue doing all your developer work on the cloud