在OpenShift运行Yesod应用

April 5, 2013

OpenShift是RedHat的云计算平台,亮点之一是DIY,可以运行任意的语言、框架、数据库…

本来想在上面弄个代理的,太难了,所以先弄个简单的,熟悉一下。

新建

rhc新建一个DIY应用:

rhc app create hello diy-0.1

当前目录就会有一个hello目录,里面是个Git仓库,赠送例子。

代码

首先,写一个简单的Yesod应用:

{-# LANGUAGE TypeFamilies, MultiParamTypeClasses #-}
{-# LANGUAGE QuasiQuotes, TemplateHaskell #-}

import Yesod
import Network.Wai.Handler.Warp
import System.Environment (getEnv)
import Control.Applicative ((<$>))

data Hello = Hello

mkYesod "Hello" [parseRoutes|
/ HomeR GET
|]

instance Yesod Hello

getHomeR :: Handler RepHtml
getHomeR = defaultLayout [whamlet| Hello, world |]

main :: IO ()
main = runOpenShift Hello

runOpenShift master = do
    ip   <- getEnv "OPENSHIFT_INTERNAL_IP"
    port <- read <$> getEnv "OPENSHIFT_INTERNAL_PORT"

    app  <- toWaiApp master
    let settings = defaultSettings { settingsPort = port
                                   , settingsHost = Host ip}
    runSettings settings app

我们runOpenShift运行一个应用。OpenShift的DIY应用要绑定在一个内部的IP和端口,OpenShift会把HTTP请求代理过去。runOpenShift从环境变量OPENSHIFT_INTERNAL_IPOPENSHIFT_INTERNAL_PORT获得IP的端口,然后运行。

编译

OpenShift用的是RHEL 6.2 x64版,跟我系统不同,有些库的版本不对,所以编译的时候要静态连接。

ghc -optl-static -optl-pthread -threaded Hello.hs

编译的时候会有一些这样的警告:

Linker.c:(.text+0x1213): warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

我遇到一共5个,只要不用到那几个函数应该不用有问题的。

编译之后得到一个Hello程序啦,记得strip一下,减少体积。

Action Hooks

OpenShift根据.openshift/action_hooks里的钩子来管理应用。例如start用来启动,stop用来停止,我们只修改这两个。

#!/bin/bash

cd $OPENSHIFT_REPO_DIR
nohup ./Hello >${OPENSHIFT_DIY_LOG_DIR}/log 2>&1 &
#!/bin/bash

kill `ps -ef | grep Hello | grep -v grep | awk '{ print $2 }'`
exit 0

OpenShift有很多环境变量,例如上面用到OPENSHIFT_REPO_DIR,表示仓库的目录,OPENSHIFT_DIY_LOG_DIR表示日志目录。

上传

在本机测试完之后就可以上传了,我们把仓库push上去就可以了。

git add .
git commit -m "A simple Yesod application"
git push

上传比Appfog快很多。

运行

重启:

rhc app restart hello

浏览器,打开应用地址看看。

其他

OpenShift可以用SSH shell登陆,我第一次SSH登陆别人的机器(github不算,它没有shell),不过延时比较明显,如果速度快点的话,调试会很方便。

试过Heroku、Appfog、CloudFoundry还有OpenShift,他们的命令行工具居然都是用ruby写的。

蠢事

我运行发现一直没结果,又写printf调试,又上ssh都没发现问题。最后我把协议改成https, 居然可以了,WTF。 原来OpenShift网站一只都在用HTTPS,但是给出的应用地址链接却是HTTP的,没留意到啊。

参考

Use Your Own Languages and Data Stores on OpenShift 一个C语言的例子