Rails 在 CoreOS 上用 Docker 部署 Rails 应用

gamefu · 2015年08月05日 · 最后由 helloyokoy 回复于 2015年11月03日 · 3546 次阅读

coreos 上的配置

coreos 没有包管理工具,也不鼓励使用包管理工具来解决依赖关系,他提倡使用 docker 等容易来解决管理以来,要想搭建一个 rails 的环境,我们需要创建一个能满足我们需求的镜像。docker 原则上是一个服务就需要一个镜像,不同的服务之间通讯需要使用 docker 自己提供的通讯方式,这个演示实例里,我们只依赖于一个数据库服务。首先我们需要创建我们整个 rails 运行环境所需要的所有服务镜像

postgres 数据库的官方镜像


docker pull postgres

然后我们还需要运行 rails 的 web 服务器镜像,我选择的是 passenger 的官方镜像


docker pull phusion/passenger-ruby22

rails 运行需要 postgres 数据库,因此,我们需要创建一个 postgres 容器,同时给我们创建的容器一个名称


docker run --name gamePostgres -d postgres

这样一来我们在 coreos 上的配置就配置好了

Dockerfile

将这个 Dockerfile 加入我们的 rails 项目下


# 以phusion/passenger-ruby22镜像为基础
FROM phusion/passenger-ruby22

# 设置时区
RUN echo "Asia/Shanghai" > /etc/timezone
RUN dpkg-reconfigure -f noninteractive tzdata

#设置当前环境变量
ENV HOME /root
#设置rails环境为生产环境
ENV RAILS_ENV production

CMD ["/sbin/my_init"]

# 缓存gem,如果Gemfil没有改变将不会从源直接下载
WORKDIR /tmp
ADD ./Gemfile Gemfile
ADD ./Gemfile.lock Gemfile.lock
RUN bundle install

#启动nginx
RUN rm -f /etc/service/nginx/down
#配置nginx
RUN rm /etc/nginx/sites-enabled/default
ADD nginx.conf /etc/nginx/sites-enabled/webapp.conf

#添加环境文件
ADD nginx-env.conf /etc/nginx/main.d/nginx-env.conf

#增加初始化运行脚本
RUN mkdir -p /etc/my_init.d
#Migrate
ADD migrate.sh /etc/my_init.d/migrate.sh
RUN chmod +x /etc/my_init.d/migrate.sh

# 创建项目目录
RUN mkdir /home/app/webapp
# 将项目文件加入项目目录
ADD . /home/app/webapp

WORKDIR /home/app/webapp
# 编译静态文件
RUN rake assets:precompile

# 清楚产生的缓存文件
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# 开放80端口
EXPOSE 80


由于 passenger 镜像是建立在 nginx 的基础上地,所以我们需要配置 nginx.同时在跟目录创建 nginx.conf.


server {
    listen 80;
    #指定项目根目录
    root /home/app/webapp/public;

    # 开启passenger
    passenger_enabled on;
    passenger_user app;
    client_max_body_size 20M;
    passenger_max_request_queue_size 0;
}

在 docker 中服务通讯必须在容器之间暴露端口,因此我们需要添加 env 文件来暴露各容器之间的端口,在项目根目录下创建 nginx-env.conf 文件


# 暴露服务端口 这个示例中只有postgres服务,因此我们只需要暴露这个端口即可
env POSTGRES_PORT_5432_TCP_ADDR;
env POSTGRES_PORT_5432_TCP_PORT;

最后,我们配置一下.gitignore,在.gitignore 文件里加上,因为服务器的数据库配置和本地数据库配置不一样

/config/database.yml

同时 copy 一份 database.yml,将其改名为 database.yml.sample

在 coreos 上部署

coreos 虽然默认没有带包管理工具,但是安装了 git 之类的常用工具,因此,我们可以使用 git 部署我们的项目,将我们的项目上传到 github,然后在 coreos 的某个目录将整个项目拉下来。我选择的是/root/apps 目录

拉取项目后,我们首先需要更改的是数据库配置文件 database.yml


default: &default
  adapter: postgresql
  encoding: unicode
  pool: 5
  timeout: 5000
  username: postgres
  password:
  # 通过暴露出来的地址和端口配置数据库
  host: <%= ENV['POSTGRES_PORT_5432_TCP_ADDR'] %>
  port: <%= ENV['POSTGRES_PORT_5432_TCP_PORT'] %>
development:
  <<: *default
  database: sample_dev

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: sample_test

production:
  <<: *default
  database: sample_production


然后进入项目根目录,通过 Dockfile 构建一个镜像,并且给自己创建的镜像一个名称


docker build -t game/ruby_sample .

以后的每一次更改项目内容都需要重新构建一个新的镜像,如果你是第一次生成容器可以不用运行下面这条命令,如果你之前已经创建过同名的容易就需要将其删除,如我之前这个容器名为 gameRuby_sample,那么我就需要将这个容器删除后重新创建


docker rm -f gameRuby_sample

创建新的容器,并且建立容器之间的通讯,监听服务器的 80 端口


docker run --name gameRuby_sample --link gamePostgres:postgres -d -p 80:80 game/ruby_sample

进行到这里,一个完整的 rails 容器已经基本建立完成了。然而整个容器还缺乏一个很关键的部分没解决,就是运行 rails 程序的 migrate,由于,migrate 必须在整个容器建立完成之后才能运行,因此无法直接将其写在Dockerfile内,只有当运行容器时运行,才能有效果。 passenger 是根据 ubuntu 镜像的基础上搭建的,也就是说,这个系统的启动流程跟 ubuntu 启动的流程是一样的,当 ubuntu 系统完成引导后,操作系统会去检查/etc/my_init.d/目录下的脚本,并且会运行,这样一来,只需把 migrate 的执行脚本放到这个目录下面,那么就会在镜像启动的时候运行 Migrate。

#增加初始化运行脚本
RUN mkdir -p /etc/my_init.d
#Migrate
ADD migrate.sh /etc/my_init.d/migrate.sh
RUN chmod +x /etc/my_init.d/migrate.sh

下面是 migrate 运行脚本


#!/bin/sh
echo "start migrate"
bash -c 'cd /home/app/webapp; bundle exec rake db:migrate';
echo "migrate finshed"

只要运行 docker run 后,运行docker logs -f 镜像名,能看到start migratemigrate finshed就说明镜像已经成功运行 migrate 了

这样一来基本的 rails 运行环境就搭建完成了

刚好最近在 研究 docker 部署 rails ~

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