如何用Docker部署Rails應(yīng)用

近期在運(yùn)維界有一個(gè)新興技術(shù)docker特別火,在看了相關(guān)的介紹之后果斷決定嘗試一下用docker部署一臺(tái)服務(wù)器。過程中記錄了一下整個(gè)操作的過程及相關(guān)配置文件,分享給各位也愛追求技術(shù)時(shí)尚的程序猿們。

適用環(huán)境

服務(wù)器:阿里云 (雙核 + 2GB 內(nèi)存) Ubuntu 14.04
應(yīng)用的stack: nginx + unicorn + mongodb

在阿里云上安裝dockerengine

基本按照官網(wǎng)上的安裝指南來做的。我剛開始選擇的是ubuntu管理的安裝包,docker.io, 版本是 1.0.1,發(fā)現(xiàn)bug太多,后來重新安裝了最新的版本 1.4.1。官網(wǎng)的安裝包似乎被墻了,用了網(wǎng)頁(yè)最下面的Yandex的鏡像才把docker安裝好。

啟動(dòng)docker的daemon程序

正常的情況下只需要執(zhí)行下面的命令就可以啟動(dòng)docker

$ sudo service docker start

但是在阿里云的ECS上報(bào)出無(wú)閑置IP的錯(cuò)誤,百度了一下才找到解決方案,操作步驟如下:

打開/etc/network/interfaces,注釋掉以下配置

# route del -net 172.16.0.0 netmask 255.240.0.0 dev eth0 

重新啟動(dòng)networking

$ sudo service networking restart

重新啟動(dòng)docker

$ sudo service docker restart

測(cè)試一下docker是否正常運(yùn)行

$ docker info
Containers: 33
Images: 176
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Dirs: 242
Execution Driver: native-0.2
Kernel Version: 3.13.0-32-generic
Operating System: Ubuntu 14.04.1 LTS
CPUs: 2
Total Memory: 3.859 GiB
Name: iZ256yal27dZ
ID: BQ3A:ZJIY:5EOM:JOTY:EROQ:7UI6:SB6P:QVBC:3FM5:DEMB:WBY2:ZDH6
WARNING: No swap limit support

啟動(dòng)nginx的container

在阿里云的機(jī)器上構(gòu)建以下文件夾,并創(chuàng)建相應(yīng)的文件

dockers
└── nginx
    ├── Dockerfile
    └── config
        └── nginx-app.conf

注意:我們暫時(shí)先將與rails app有關(guān)的配置文件注釋了

# Dockerfile for installing and running Nginx

# Select ubuntu as the base image
From registry.mirrors.aliyuncs.com/library/ubuntu:14.04

# Install nginx
RUN apt-get update
RUN apt-get install -y nginx
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
# ADD config/nginx-app.conf /etc/nginx/sites-enabled/default

# Publish port 80
EXPOSE 80

# Start nginx when container starts
ENTRYPOINT /usr/sbin/nginx
# nginx-app.conf

# this can be any application server, not just Unicorn/Rainbows!
upstream rails-app {
  server app:8080 fail_timeout=0;
}

server {
  listen 80 default deferred; # for Linux

  client_max_body_size 4G;
  server_name _;

  keepalive_timeout 5;

  # path for static files
  root /webapps/app/public;

  try_files $uri/index.html $uri.html $uri @unicorn;

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://rails-app;
  }

  # Rails error pages
  error_page 500 502 503 504 /500.html;
  location = /500.html {
    root /webapps/app/public;
  }
}

然后在nginx文件夾下,生成新的docker image,并啟動(dòng)nginx的container

$ docker build -t junhao/nginx .
$ docker run --name web -d -p 80:80 junhao/nginx

運(yùn)行docker ps來檢查一下container的運(yùn)行情況

$ docker ps
CONTAINER ID        IMAGE                  COMMAND                CREATED             STATUS              PORTS                    NAMES
87ae87c89a78        junhao/nginx:latest    "/bin/sh -c /usr/sbi   5 days ago          Up 5 days           0.0.0.0:80->80/tcp       web

打開瀏覽器,輸入你的阿里云VM地址,應(yīng)該就能看到“Welcome to Nginx”的頁(yè)面。階段性成功,yay!

啟動(dòng)unicorn的container

先把rails app上傳到服務(wù)器上,在應(yīng)用根目錄下創(chuàng)建這樣幾個(gè)文件,Dockerfile, .dockerignore, scripts/start-server.sh

# Dockerfile for a Rails application using Nginx and Unicorn

# Select ubuntu as the base image
From registry.mirrors.aliyuncs.com/library/ubuntu:14.04

RUN apt-get update -q
RUN apt-get install -qy curl

# Install rvm, ruby, bundler
RUN curl -sSL https://get.rvm.io | bash -s stable
RUN /bin/bash -l -c "rvm requirements"
RUN /bin/bash -l -c "rvm install 2.1.5"
RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc"

# Copy the Gemfile and Gemfile.lock into the image. 
# Temporarily set the working directory to where they are. 
WORKDIR /tmp 
ADD ./Gemfile Gemfile
ADD ./Gemfile.lock Gemfile.lock
RUN /bin/bash -l -c "bundle install"

# Add rails project to project directory
ADD ./ /webapps/app

# set WORKDIR
WORKDIR /webapps/app

# bundle install
# RUN /bin/bash -l -c "bundle install"

# Add configuration files in repository to filesystem
ADD scripts/start-server.sh /usr/bin/start-server
RUN chmod +x /usr/bin/start-server

# Publish port 80
EXPOSE 8080

# Startup commands
ENTRYPOINT /usr/bin/start-server
# .dockerignore

# Ignore bundler config.
/.bundle

# Ignore the default SQLite database.
/db

# Ignore all logfiles and tempfiles.
/log
/tmp

# Gemfile.lock

# Redis
dump.rdb

注意:我有一個(gè)unicorn的配置文件在config文件夾下,沒有用配置文件的需要修改start-server.sh的最后一行命令

#!/bin/bash

cd /webapps/app
source /etc/profile.d/rvm.sh
mkdir -p /webapps/shared/pids
mkdir -p /webapps/shared/log
cat /webapps/shared/pids/unicorn.pid
kill -QUIT `cat /webapps/shared/pids/unicorn.pid`
bundle exec unicorn -c config/unicorn.rb -E production -p 8080

然后創(chuàng)建unicorn的docker image,并啟動(dòng)container

$ cd /webapps/app
$ docker build -t junhao/app .
$ docker run --name app -d -p 8080:8080 junhao/app

接著,我們要對(duì)nginx的container做一些改動(dòng):把和rails app相關(guān)的配置添加回來,并重新創(chuàng)建、啟動(dòng)nginx的container。

打開dockers/nginx/conf/nginx-app.conf,把下面這行設(shè)置添加回來

# ADD config/nginx-app.conf /etc/nginx/sites-enabled/default

然后停止現(xiàn)在的container,并重建container。

$ cd dockers/nginx
$ docker stop web
$ docker build -t junhao/web .

下一步就是重啟,在重啟的時(shí)候我們要用到一個(gè)叫container linking的技術(shù)手法。仔細(xì)看一下nginx-app.conf,里面有這樣一段代碼:

upstream rails-app {
  server app:8080 fail_timeout=0;
}

這里的app:8080中的app指的是我們創(chuàng)建的unicorn container。那么在nginx的container中,app代表的其實(shí)是unicorn container在本機(jī)的地址映射。這個(gè)是需要我們?cè)趩?dòng)nginx container的時(shí)候做特殊處理的,不然nginx container無(wú)法獲得相關(guān)信息。--link app:app就是把a(bǔ)pp container的信息傳遞給了web container。

$ docker run --name web --link app:app -d -p 80:80 junhao/nginx

現(xiàn)在打開瀏覽器,試試打開一個(gè)不需要訪問數(shù)據(jù)庫(kù)的頁(yè)面。

配置MongodDB

我用了MongoDB官方的部署服務(wù)MMS來管理MongoDB,所以沒有用docker。大家也可以嘗試不同的方法。在本機(jī)安裝完MongoDB之后,在config/mongoid.yml中修改hosts的地址:- dockerhost:27000。這里的dockerhost指的是container運(yùn)行的VM的地址。
這個(gè)地址我們可以在container啟動(dòng)時(shí)定義,由于之前運(yùn)行時(shí)沒有定義這個(gè)值,我們需要重啟app container。

$ docker stop app
$ docker build -t junhao/app .
$ docker run --name app --add-host=dockerhost:<enter your host address here> -d -p 8080:8080 junhao/app

然后重啟一下web container

$ docker stop web
$ docker run --name web --link app:app -d -p 80:80 junhao/nginx

這樣就大功告成啦!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容