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 加入我们的 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 虽然默认没有带包管理工具,但是安装了 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 migrate
和migrate finshed
就说明镜像已经成功运行 migrate 了
这样一来基本的 rails 运行环境就搭建完成了