有幸拿到 docker beta 的测试资格,在 Mac OSX 下使用 docker 更加方便好玩了。这篇博文介绍如何在生产环境也就是线上利用 docker 实现快速部署以及横向扩展,为大规模负载均衡做准备。这里使用一个 docker 容器来跑 rails 应用,另一个容器来跑异步队列 sidekiq 等服务,数据库和 redis 使用 RDS 和云 redis,直接使用 docker 镜像的数据库也可以。
首先你的 web 应用要足够干净,rails 也好,nodejs 也一样,不依赖于本地的任何东西,应该是一个 docker 镜像 pull 下来,加上一些环境变量等配置就能直接跑起来。
首先讲一些我的工程目录结构,主要就是 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 是使用 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 镜像的部署很简单,直接 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 开发环境可以看之前的博客。
本文原文出处,Embbnux 博客,生产环境使用 docker 部署 rails 应用 puma 和 sidekiq.欢迎转载,转载请注明原文出处,并保留原文链接