生产环境使用docker部署rails应用puma和sidekiq

有幸拿到docker beta的测试资格, 在Mac OSX下使用docker更加方便好玩了。这篇博文介绍如何在生产环境也就是线上利用docker实现快速部署以及横向扩展,为大规模负载均衡做准备。这里使用一个docker容器来跑rails应用,另一个容器来跑异步队列sidekiq等服务, 数据库和redis使用RDS和云redis,直接使用docker镜像的数据库也可以。

个人原创,版权所有,转载请注明原文出处,并保留原文链接:
https://www.embbnux.com/2016/05/22/rails_use_puma_sidekiq_deploy_with_docker_on_production/

一、生产环境使用docker前准备

首先你的web应用要足够干净,rails也好,nodejs也一样,不依赖于本地的任何东西,应该是一个docker镜像pull下来,加上一些环境变量等配置就能直接跑起来。

  • 1、数据库url可配置,可以连接远程数据库,或者连接其他数据库容器
  • 2、redis也应该是远程连接可配置, redis独立出去,异步队列像sidekiq的也可以在单独容器里跑了,因为一个docker容器只支持一直进程跑,所以server和队列是分开的,通过redis通讯。
  • 3、只处理动态流量,静态资源请走CDN, 图片的上传也不是储存在本地磁盘的, 图片的上传可以上传到容器再由容器传到云存储服务器,或者直接由客户端上传到云存储服务器,数据库里存图片的地址就可以。

二、配置生产环境Dockerfile

首先讲一些我的工程目录结构,主要就是rails的结构,这里只列出关键的文件目录结构:

|__ app
|__ config
|__ |__ puma_docker.rb
|__ |__ database.yml
|__ |__ redis.yml
|__ |__ sidekiq.yml
|__ public
|
|__ Dockerfile
|__ Gemfile
|__ Gemfile.lock

Dockerfile原则应该是只添加有需要的:

##########################################
# Dockerfile for rails app with puma and sidekiq postgres
# Author: Embbnux Ji
# HomePage: www.embbnux.com
##########################################

FROM ruby:2.3.1

MAINTAINER Embbnux [email protected]
RUN apt-get update && apt-get install -y build-essential libssl-dev libpq-dev libxml2-dev libxslt1-dev nodejs git imagemagick libbz2-dev libjpeg-dev libevent-dev libmagickcore-dev libffi-dev libglib2.0-dev zlib1g-dev libyaml-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*

ENV APP_HOME /app

RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME

COPY Gemfile $APP_HOME/
COPY Gemfile.lock $APP_HOME/

RUN bundle install

COPY . $APP_HOME

RUN bundle exec rake assets:precompile RAILS_ENV=production

EXPOSE 8080
CMD ["bundle", "exec", "puma", "-C", "config/puma_docker.rb"]

三、配置rails工程

我的rails是使用puma来作为web服务器的,docker自然也一样,所以app容器默认是执行puma启动server的命令,对外输出接口为8080, 使用nginx代理流量到这个服务端口即可。
puma这里需要配置为暴露8080端口:

# puma_docker.rb:

threads 4, 16
workers 1
environment 'production'
bind 'tcp://0.0.0.0:8080'
preload_app!

on_worker_boot do
  ActiveSupport.on_load(:active_record) do
    ActiveRecord::Base.establish_connection
  end
end

数据库配置:

# database.yml:

default: &default
  adapter: postgresql
  encoding: unicode
  pool: 5
  timeout: 5000

production:
  <<: *default
  pool: 10
  database: <%= ENV["DATABASE"] %>
  host: <%= ENV['DATABASE_HOST'] %>
  username: <%= ENV["DATAUSER"] %>
  password: <%= ENV["DATAPASSWD"] %>

redis的配置也一样,redis的地址用环境变量代替: ENV[“REDIS_URL”]

四、使用远程仓库自动构建

我这边采取的远程仓库方案是Github加Docker Hub,实现代码更新自动构建镜像,方法很简单,就是使用docker hub的自动构建功能,关联github仓库即可。需要在工程根目录下有一个Dockerfile.
这样git push代码后过几分钟镜像就会被自动构建完成。
也可以使用docker hub的webhook功能实现构建完成自动部署,这个我暂时没测试。

五、部署docker镜像到生产环境

docker镜像的部署很简单,直接pull下来跑就可以了。这里为了演示, 数据库和redis也用一个单独的docker容器来跑,模拟远程连接,云储存用docker的volume功能实现,具体如下:

# 下载redis镜像
docker pull redis
# 下载postgres镜像
docker pull postgres
# 下载已经自动构建完成的app镜像
docker pull embbnux/app
# 后台运行redis容器
docker run --name app_redis -d redis
# 后台运行postgres容器, 指定用户名密码
docker run --name app_postgres -e POSTGRES_PASSWORD=password -e POSTGRES_USER=user -e POSTGRES_DB=app_db -d postgres
# 后台运行app容器, 环境变量使用.env.docker文件传入, 映射容器的8080端口到本地的8080端口
docker run --env-file ./.env.docker --link app_redis:redis --link app_postgres:postgres -v /var/www/public/uploads:/app/public/public -v /var/log/app:/app/log --name app_web -p 127.0.0.1:8080:8080 -d embbnux/app
# 上传assets文件到cdn
# docker run --env-file ./.env.docker --link app_redis:redis --link app_postgres:postgres --name app_assets --rm embbnux/app rake cdn:upload_assets
# 运行sidekiq容器
docker run --env-file ./.env.docker --link app_redis:redis --link app_postgres:postgres -v /var/www/public/uploads:/app/public/public -v /var/log/app:/app/log --name app_sidekiq -d embbnux/app bundle exec sidekiq -C config/sidekiq.yml

环境变量文件如下:

# .env.docker
RAILS_ENV=production
SECRET_KEY_BASE=1237293729347238719422b4e25fe42a311bc4e5ffb242397934cbad3adabfbcfae4b431a5029ad6486bce777382470327493287402
DATABASE_HOST=app_postgres
DATABASE=app_db
DATAUSER=user
DATAPASSWD=password
REDIS_URL=redis://app_redis:6379

以后升级代码,只需要把app pull下来跑就可以了, 多机器部署建议用capistrano等工具。
在开发环境使用docker快速构建rails开发环境可以看之前的博客。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

Time limit is exhausted. Please reload the CAPTCHA.

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据