云服务 在 DaoCloud 上部署 Rails App

cassiuschen · 2015年07月03日 · 最后由 seaify 回复于 2015年10月17日 · 4644 次阅读

博客原文:http://cassiuschen.me/posts/7-deploy-rails-app-on-daocloud DaoCloud 是一个 Docker 云,用户可以在上面建立 Docker 镜像并运用镜像进行持续集成、容器托管等服务。近期 DaoCloud 还推出了自由主机的 Docker 管理功能,更方便了 Docker 的容器部署。

因为 DaoCloud 提供免费得容器空间,最高可用 256MB 内存和 20G 的硬盘,对于一个小型的 Rails 应用来说基本上够了,故我将我未完成的个人网站挂在了上面。本文记录了使用 DaoCloud 部署的全过程。

Step 1:创建镜像 (Mirror)

镜像是 Docker 容器运行的环境,在这一步,我们需要完成全部环境的配置。

Docker 创建镜像有两种方式:一种是利用交互式命令行直接配置,另一种是通过Dockerfile文件 Docker 自动配置。

DaoCloud 目前没有提供交互式命令行,故只能通过Dockerfile来配置。以下是我的个人网站所用的Dockerfile

FROM ubuntu:14.04
MAINTAINER Cassius Chen "[email protected]"
RUN apt-get update
RUN apt-get -y install gcc g++ make automake autoconf make libc6-dev patch openssl ca-certificates libreadline6 libreadline6-dev curl zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-dev sqlite3 libgdbm-dev libncurses5-dev libtool bison pkg-config libffi-dev imagemagick redis-server zlib1g-dev openssl openssh-server curl libedit-dev wget git-core
WORKDIR /tmp
RUN wget http://cache.ruby-lang.org/pub/ruby/2.2/ruby-2.2.2.tar.gz
RUN tar -zxvf ruby-2.2.2.tar.gz
WORKDIR /tmp/ruby-2.2.2
RUN ["./configure"]
RUN make -j2
RUN make install -j2
RUN ruby -v
RUN mkdir -pv /var/data
WORKDIR /var/data
ADD ./ /var/data/personal_site
WORKDIR /var/data/personal_site
RUN mkdir -pv tmp/{pids,sockets}
RUN gem install --no-rdoc --no-ri bundler
ENV RAILS_ENV docker
RUN bundle install -V
RUN chmod 777 start.sh
ENV DB_HOST ------
ENV DB_USERNAME ------
ENV DB_PASSWORD ------
ENV REDIS_PASSWORD ------
ENV REDIS_PORT ------
ENV REDIS_HOST ------
RUN rake assets:precompile
EXPOSE 80

CMD ["sh", "/var/data/personal_site/start.sh"]

这个配置并不是很优化,有很多东西也是没有必要安装的。但基本能跑。流程大约是:安装基本依赖 -> 下载 Ruby 源码 -> 编译安装 -> 拷贝项目文件至指定目录 -> 进入目录安装依赖

我的个人网站使用了MongoDBRedis,而 DaoCloud 免费提供了MongoDBRedis的服务,不将数据库直接建立在镜像当中,而是使用外网连接使用。

将数据库与应用分离也是 Docker 推荐的配制方法,其核心思想是一个 Docker Mirror 只负责一种 Container 的运维环境,数据库可以完全与应用分离,这样也保证了服务迁移时的稳定性和更优秀的可扩展性。

如果是自己配置 Docker,一般而言会将应用源码放在容器之外,然后以VOLUME的方式挂在进容器,这样只需要在宿主系统层面更新源码便可直接更新容器内的代码,而不用重新构建运行环境。可惜在 DaoCloud 上不存在宿主系统,故只能将源码拷贝到镜像当中,每次更新代码需要重新构建容器。

这里还有个问题,可以注意到我将rake assets:precompile这一步放在了镜像构建的过程中。这原则上是不对的,静态文件打包应该在容器运行时进行。之所以这样做主要是因为 DaoCloud 的容器只能使用 256MB 的内存,在容器运行时打包会导致内存超出范围的问题,而镜像构建过程没有内存使用限制,取个巧,移到这一步做。不过这带来的问题是rake命令在运行时会读取 Rails 的基本配置,故有一部分环境变量需要在这一步export

写好Dockerfile就可以在 DaoCloud 上发布了。首先注册登录,然后点击“代码构建”,选择新建项目进入下面的界面:

新建页面

DaoCloud 可以读取你的在各处的 git 账户并直接从 master 分支 clone 代码,然后默认根据根目录中的Dockerfile进行初始版本的镜像构建master-init。成功后就可以进入第二步了。

Step 2:创建服务

上文提到,这个网站用到了MongoDBRedis,回到 DaoCloud 主界面,进入服务集成,看到下图:

服务集成

根据流程建立两个服务,这样数据库方面就建立好了。然后在 Rails 中配置:

# In config/mongoid.yml
docker:
  # Configure available database sessions. (required)
  sessions:
    # Defines the default session. (required)
    default:
      # Defines the name of the default database that Mongoid can connect to.
      # (required).
      database: <%= ENV["DB_NAME"] %>
      username: <%= ENV["DB_USERNAME"] %>
      password: <%= ENV["DB_PASSWORD"] %>
      # Provides the hosts the default session can connect to. Must be an array
      # of host:port pairs. (required)
      hosts: 
        - <%= ENV["DB_HOST"] %>

以环境变量的方式处理配置,同理 Redis:

Redis::Objects.redis = Redis.new(:host => ( ENV["REDIS_HOST"] || '127.0.0.1'), :port => ( ENV["REDIS_PORT"] || '6379').to_i, :password => (ENV["REDIS_PASSWORD"] || ''))

然后将config/environments/production.rb另存一份成config/environments/docker.rb,补全config/secrets.rb和其他文件中关于 docker 环境的配置。就基本配置好了,可以进入下一步了。

Step 3:部署应用

在构建完成的镜像后点击“查看镜像”,并点击“部署”进入下述部署界面:

部署应用

这里先以部署到 DaoCloud 为例,在这里可以选择两种配置。

然后进一步配置环境变量和使用的服务,选择上述建立的服务,并根据自己的配置改变环境变量,如:

环境变量

启动时运行命令默认为DockerfileCMD中的命令,我这里是运行start.sh, 贴出文件:

rake db:seed
puma -e docker -C config/docker_puma.rb

然后贴出docker_puma.rb

#!/usr/bin/env puma

environment 'docker'
daemonize false
threads 0, 4
bind 'tcp://0.0.0.0:80'
preload_app!

然后 DaoCloud 就会开始运行啦~然后就大功告成!

当然,还有如何更新代码。

更新代码

当本地 push 代码到远程仓库并带有tag的时候,DaoCloud 会收到回调并自动构建相应 tag 的镜像。

如:

$ git add -A
$ git commit -am 'next version'
$ git tag -a v0.3.1 -m 'v0.3.1 version'
$ git push origin master --tags

DaoCloud 会自动构建新的镜像并自动重新部署容器,于是,push 完代码,去喝杯咖啡,回来就更新部署完了~是不是很方便~?

自有主机

DaoCloud 还推出了针对自有主机的管理方式。按照网站上的流程很容易的可以在自己的服务器上装 DaoCloud 的客户端(可能存在安全隐患?),DaoCloud 就可以非常方便地提供服务器 Docker 状态的监控,服务器资源使用的监控。

而在上文中部署时也可以使用自有主机进行部署,不同的是,在自有主机的环境中不能直接使用 DaoCloud 提供的服务集成,但可以挂在VOLUME,并可以轻松的在自有主机上进行迁移:

迁移

持续集成

(我比较懒,自己的个人网站一行测试都还没写……这里就不做讨论了)

结语

DaoCloud 用可视化且实时的交互方式为我们提供了友好的 Docker 管理和运行环境,可以说非常好了。 但 DaoCloud 因为始终没有交互式命令行所以在修 Bug 和 hotfix 方面完全没有作为。本身在 Docker 1.3 版本之后可以使用docker exec的方式在容器内部运行进程,方便了 hotfix 和查错,希望未来 DaoCloud 可以加入这个功能。

另我本人并非从事运维的专业人士,文中纰漏还望各位批评指正!

DaoCloud 最近在送 T 恤哦,昨天刚收到一件。

#1 楼 @huobazi 要是不是想要 T 恤……我也没打算把网站部署到 daocloud 上…………

256MB 真的够放一个 Rails 应用了么?

#3 楼 @blacktulip 还行,现在跑了几个小时了内存占用保持在 168MB……

哈,看头像眼熟,点进资料一看真是小紫

#4 楼 @cassiuschen

start.sh 中写 rake db:seed,不合适吧。每次部署时,都会被执行一遍,应该是 rake db:migrate 吧

需要 登录 后方可回复, 如果你还没有账号请 注册新账号