部屬前碎念
我有一個專案是抓subdomin在判斷群組,就像Logdown一樣依照次級網域來引導到不同使用者的部落格一樣,礙於某些因素將其專案從機器上搬出來,原本打算搬到Heroku,但發現naked domain實在是很難搞定,最後決定是搬到Amazon Ec2上面,因為過程其實做過很多次,常常健忘就把這些記錄下來。
網域申請我本身是使用Godaddy,他裡面的CNAME指向不能在heroku上面玩次級網址,因為heroku沒有Public IP給你使用,所以用EC2的彈性會好很多,畢竟服務不一樣。
Heroku是屬於PaaS 類型(Platform as a Service),支援特定語言或框架,幫你把很多細節處理好,一鍵部屬也不必多作設定。 Amazon EC2則是屬於IaaS 類型(Infrastructure as a Service),可以完整獲取Root權限,並進去機器裡面做設定,像是擁有一台電腦一樣。
實作部分
Amazon EC2如何申請是用這邊不多贅述,本篇只講部屬細節,這邊建議在選機器的時候,Oregon選擇離自家較近的東京機房,速度會好一些,機器的OS我個人建議選ubuntu,因為有被aws的linux稍微雷過XD。
登入VPS
參照ec2上面的connect方式,應該會如下,請用自己的pem跟vps ip進行連線,以下為範例
ssh -i "yourpem.pem" ubuntu@ec2-111-222-333-444.ap-northeast-1.compute.amazonaws.com
進入機器後,先創建部屬用的帳號,這邊盡量不要用root權限去做部屬比較妥當。
sudo adduser deploy
sudo adduser deploy sudo
su deploy
中間有設定密碼的部分請自行設定,有填資料的部分可以直接Enter過去。
然後為了方便我們登入deploy不需輸入密碼,我們先做ssh認證的部分。
ssh-keygen
中間一路enter過去採用default即可
cd
cd .ssh/
vi authorized_keys
然後將你電腦本地的.ssh/id_rsa.pub
裡面的內容複製進去,並且存檔:wq
這樣你在進行登入的時候就不需輸入密碼,可以嘗試重新以deploy
帳號登入aws ec2
ssh deploy@111.222.333.444
如果不用密碼就直接進去表示成功
安裝Ruby
這裡我是裝2.3.1,如果有不同版本再請自行修改
sudo apt-get update
sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev python-software-properties libffi-dev
再來安裝rbenv
cd
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
exec $SHELL
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
exec $SHELL
rbenv install 2.3.1
rbenv global 2.3.1
ruby -v
最後一步是安裝bundle工具,不然你的rails會沒辦法bundle install
gem install bundler
安裝Nginx + Passenger
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7
sudo apt-get install -y apt-transport-https ca-certificates
# Add Passenger APT repository
sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger trusty main > /etc/apt/sources.list.d/passenger.list'
sudo apt-get update
# Install Passenger & Nginx
sudo apt-get install -y nginx-extras passenger
安裝完啟動Nginx
sudo service nginx start
因為我們的EC2需要將http prot打開才能看到網站,所以別忘記去設定 設定位置在SecurityGroup > 你的instance所使用的group > 下方的inbound選擇edit > 加入http並且save
由於我們的nginx已經啟動,也將http prot80打開,這時候我們將ec2給我們的public ip直接輸入網址,如果設定都正確就可以直接看到nginx為我們預設的首頁。
接著我們編輯nginx設定檔
sudo vim /etc/nginx/nginx.conf
在http的block裡面加入
passenger_root /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini;
passenger_ruby /home/deploy/.rbenv/shims/ruby;
並且重新啟動nginx,如果有跳fail就要檢查一下語法是否錯誤。
sudo service nginx restart
創建你的Database
MySQL
sudo apt-get install mysql-server mysql-client libmysqlclient-dev
PostgreSQL
sudo apt-get install postgresql postgresql-contrib libpq-dev
基礎設定
sudo su - postgres
createuser --pwprompt
exit
關閉nginx預設的歡迎頁
sudo vi /etc/nginx/sites-available/default
將以下兩行用#
註解掉
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
建立部屬所需的資料夾
我們預期將專案放在 /var/www/rails
裡面
cd
cd /var/
mkdir www
cd /var/www/
mkdir rails
sudo chown rails/
請將awesome_project
替換成自己的專案名稱
sudo vi /etc/nginx/sites-available/awesome_project
並且輸入以下內容後:wq
存檔離開
server {
listen 80 default_server;
server_name www.mydomain.com;
passenger_enabled on;
passenger_app_env production;
root /var/www/rails/current/public;
}
注意的地方是
server_name 的地方,如果你沒有申請域名(例如www.domain.com),這行可以省略。
root 代表你的code放在哪,記得務必指向你rails資料夾當中的public資料夾。這邊的資料夾結構說明:
/var/www 是server預設的資料夾
/rails 是我們剛才的所設定的資料夾名稱,建議這邊的名稱和前面的資料夾名稱相同
/current 是capistrano佈署時所產生的資料夾,如果你沒打算用capistrano佈署,可以不用管這層的資料夾
/public 是rails當中的public資料夾,nginx這邊的設定必須指向一個public資料夾
將網站設定啟用
sudo ln -s /etc/nginx/sites-available/rails /etc/nginx/sites-enabled/rails
sudo nginx -s reload
本機安裝Capistrano
group :development do
gem 'capistrano'
gem 'capistrano-bundler', '~> 1.1.2'
gem 'capistrano-rails'
gem 'capistrano-passenger'
gem 'capistrano-rbenv', github: "capistrano/rbenv"
end
#使用mysql可以加入這行
gem 'mysql2', '0.3.18'
執行bundle install
之後
安裝capistrtano
cap install
將會產生所需的設定檔。
設定Capistrano
接著進行設定,進入config/deploy.rb,改成你想要的設定:
set :application, "rails"
set :repo_url, "git@bitbucket.org:motionex/rails.git"
使用capistrano會搭配使用git,如果你的專案是private的,建議放到Bitbucket,就不會變成public專案。否則放在github即可。
回到設定檔中,以下是原本註解掉或不存在的設定,請刪除註解或補上:
set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml')
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system')
role :web, %w{deploy@111.222.333.444} #這裡輸入你的EC2 IP
設定好之後我們可以用capistrano來進行檢查
cap production deploy:check
由於capistrano是使用ssh登入vps主機,所以前面如果沒設定錯誤,在這個步驟並不會叫你輸入密碼。
設定database.yml及secrets.yml
因為github上面的專案會有安全性的問題,畢竟沒付費的public專案是誰想看就能看得到的,所以良好的撰寫習慣會將這兩隻檔案加入.gitignore
,也因為這樣在部屬的時候會少這兩隻檔案,所以我們必須在vps裡面先設定好這兩隻檔案,當capistrano上傳專案時,直接用替換方式做覆蓋。
cd /var/www/rails
mkdir shared
mkdir shared/config
touch shared/config/database.yml
touch shared/config/secrets.yml
並且將database以及secrets的設定訊息填入。
參考如下
production:
adapter: mysql2
encoding: utf8
database: your_database_name
pool: 25
host: 127.0.0.1
encoding: utf8
username: your_username
password: your_password
port: 3306
production:
secret_key_base: 一堆亂碼
都設定好就可以執行
cap production deploy
Rails設定
接下來請連線到VPS進行Rails的設定,如果剛剛的mysql還沒有創建Database 請輸入
mysql -u root -p
#然後輸入密碼
CRETAE DATABASE 資料庫名稱;
接下來
cd /var/www/rails/current
RAILS_ENV=production rake db:create
RAILS_ENV=production rake db:migrate
sudo service nginx restart
這時打開瀏覽器,應該可以看到Rails成功部屬了。
備註: 1. 如果部屬空專案會出現404,請自行設定root route讓網頁能正常導向。 2. 如果重開機以後瀏覽器顯示Incomplete response received from application,代表secrets的hash有問題,可用以下步驟解決: * 執行$rake secret * 複製產生的一長串hash * 到/var/www/rails/shared/config/secrets.yml檔案當中,將原本production底下的secretkeybase換成新的hash即可。
參考連結: * 將Rails佈署(Deploy)到VPS上 * Deploy Ruby On Rails on Ubuntu 14.04 Trusty Tahr * Ruby on Rails實戰聖經之網站佈署