P: 06-79-21-39-53
E: arthurh.halet@gmail.com
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.
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 is a really good Cloud based IDE, it looks like Eclipse in your browser, let's watch a 3min video made by Codenvy:
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.
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.
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.
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
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
cf domains
if no domain
has been found inside manifest file.