博客原文:http://cassiuschen.me/posts/7-deploy-rails-app-on-daocloud DaoCloud 是一个 Docker 云,用户可以在上面建立 Docker 镜像并运用镜像进行持续集成、容器托管等服务。近期 DaoCloud 还推出了自由主机的 Docker 管理功能,更方便了 Docker 的容器部署。
因为 DaoCloud 提供免费得容器空间,最高可用 256MB 内存和 20G 的硬盘,对于一个小型的 Rails 应用来说基本上够了,故我将我未完成的个人网站挂在了上面。本文记录了使用 DaoCloud 部署的全过程。
镜像是 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 源码 -> 编译安装 -> 拷贝项目文件至指定目录 -> 进入目录安装依赖
我的个人网站使用了MongoDB
和Redis
,而 DaoCloud 免费提供了MongoDB
和Redis
的服务,不将数据库直接建立在镜像当中,而是使用外网连接使用。
将数据库与应用分离也是 Docker 推荐的配制方法,其核心思想是一个 Docker Mirror 只负责一种 Container 的运维环境,数据库可以完全与应用分离,这样也保证了服务迁移时的稳定性和更优秀的可扩展性。
如果是自己配置 Docker,一般而言会将应用源码放在容器之外,然后以VOLUME
的方式挂在进容器,这样只需要在宿主系统层面更新源码便可直接更新容器内的代码,而不用重新构建运行环境。可惜在 DaoCloud 上不存在宿主系统,故只能将源码拷贝到镜像当中,每次更新代码需要重新构建容器。
这里还有个问题,可以注意到我将rake assets:precompile
这一步放在了镜像构建的过程中。这原则上是不对的,静态文件打包应该在容器运行时进行。之所以这样做主要是因为 DaoCloud 的容器只能使用 256MB 的内存,在容器运行时打包会导致内存超出范围的问题,而镜像构建过程没有内存使用限制,取个巧,移到这一步做。不过这带来的问题是rake
命令在运行时会读取 Rails 的基本配置,故有一部分环境变量需要在这一步export
写好Dockerfile
就可以在 DaoCloud 上发布了。首先注册登录,然后点击“代码构建”,选择新建项目进入下面的界面:
DaoCloud 可以读取你的在各处的 git 账户并直接从 master 分支 clone 代码,然后默认根据根目录中的Dockerfile
进行初始版本的镜像构建master-init
。成功后就可以进入第二步了。
上文提到,这个网站用到了MongoDB
和Redis
,回到 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 环境的配置。就基本配置好了,可以进入下一步了。
在构建完成的镜像后点击“查看镜像”,并点击“部署”进入下述部署界面:
这里先以部署到 DaoCloud 为例,在这里可以选择两种配置。
然后进一步配置环境变量和使用的服务,选择上述建立的服务,并根据自己的配置改变环境变量,如:
启动时运行命令默认为Dockerfile
中CMD
中的命令,我这里是运行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 可以加入这个功能。
另我本人并非从事运维的专业人士,文中纰漏还望各位批评指正!