Deployment
Our application will be located at '/var/www/apps/mysite'. We will use capistrano v3 for deploying.
Overview
- Architecture
- Repositories
- Setup capistrano v3
- Shared data
- Deploy init
- Deploy
- Sync shared data
Prerequisites
- Create virtual host / server on Apache/Nginx before deployment.
If you are using Nginx web server and Passenger, read this to setup a server for Rails app.
Architecture
We have - local machine with our app - server where the site will be installed - server where git repository is located
Git server can be the same server we are deploying to or Github can be used.
Local machine: - folder 'site' - stores development/production versions of site in git - folder 'site_production_shared' - stores shared data
Repositories
- Local repository with branches: master, production, production-shared
- Remote repository with branches: production, production-shared
- Git on server for shared data in /var/www/apps/mysite/shared/ with branches: production-shared
Branches in repository:
- branch master - development version
- branch production - deployment will be from this branch
- branch production-shared - shared data that can be syncing with the server
Server:
- /var/www/apps/mysite/ - folder with the app
- /var/www/apps/mysite/public/ - entry point for the site for Nginx
- /var/www/apps/mysite/shared/ - shared folder
- /var/www/logs/ - site logs
Repositories
Local repository
in the main app folder:
Create branch 'production' from 'master':
git checkout -b production
Create empty branch 'production-shared':
git checkout --orphan production-shared
site_production_shared
create folder 'site_production_shared' for storing shared data on local machine .
For this folder:
- init git:
git init
git checkout -b production-shared
Remote repository
Create a repository from which app will be deployed. It can be on Github, your server with git, or it can be placed on the same server where the app is located.
Add remote repository to your local git:
# locally. from the main app
git remote add origin ssh://myserver.com/repos/reponame.git
For the folder site_production_shared
git remote add origin ssh://myserver.com/repos/reponame.git
Capistrano
basic setup
Edit config/deploy.rb:
#
set :deploy_user, 'myrvmuser'
# IP of your server
role :app, %w{123.45.67.99}
role :web, %w{123.45.67.99}
role :db, %w{123.45.67.99}
edit config/deploy/production.rb:
set :application, "mysite" # app in '/var/www/apps/mysite'
set :rails_env, 'production'
set :branch, 'production'
server '11.22.33.44', user: 'myrvmuser', roles: %w{web}, primary: true
set :deploy_to, "/var/www/apps/#{fetch(:application)}"
set :ssh_options, {
forward_agent: true,
user: 'myrvmuser'
}
Find more features for deployment here.
Shared data
Some files and folders should be shared on the server. These are config files (like 'config/database.yml' or 'log/') or files/folders which should not be overwritten by local version of app.
Such files are place in folder '/var/www/apps/mysite/shared' on the server.
If OptimaCMS is used than files in 'app/views' folder can be edited by web site administrator on server.
We should prevent overwriting such files by our local version while deploying. Also we should be able to update that files from the local version of app.
Specify such files and folders in config/deploy.rb:
# Add necessary files and directories which can be changed on server.
my_config_dirs = %W{config config/environments}
my_config_files = %W{config/database.yml config/secrets.yml config/environments/#{fetch(:stage)}.rb }
my_app_dirs = %W{public/system public/uploads public/img app/views}
# do not change below
set :linked_dirs, fetch(:linked_dirs, []).push('bin', 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle')
set :linked_dirs, fetch(:linked_dirs) + my_app_dirs
set :linked_files, fetch(:linked_files, []) + my_config_files
set :config_dirs, my_config_dirs+my_app_dirs
set :config_files, my_config_files
Setup shared folder on local machine
Shared data is stored in production-shared branch.
In our scenario we have a separate folder site_production_shared to store shared data on local machine.
Copy necessary files to local folder site_prudction_shared.
We have my_app_dirs = %W{public/system public/uploads public/img app/views} in deploy.rb.
Copy 'app/views' from the main site to folder 'site_production_shared'.
.gitignore
Modify '.gitignore' in the shared repository to exclude files/folders you don't want to be syncing. For example, if you have photos uploaded by users stored in '/var/www/apps/mysite/shared/public/photos' and you don't want to store them in the remote repository then include '/public/photos' in '.gitignore'. Or if you have images stored 'public/img' and you want to upload them from your local version to the server, then do not include this folder in '.gitignore'.
Edit .gitignore for the shared folder appropriately:
/.bundle
/db/*.sqlite3
# Ignore all logfiles and tempfiles.
/log/*.log
/tmp
/bin
/log
/vendor
/vendor/bundle
.DS_Store
.idea/
.vagrant/
*.swp
.vagrant/machines/default/virtualbox/id
/config/secrets.yml
/config/deploy.rb
/config/deploy/
/config/application.yml
/public/assets
/public/uploads
/public/photos
/public/system/maintenance.html
Find basic example of this file in gitignore_shared.
Setup shared folder on server
run capistrano task:
cap production my_server_setup:init_shared_folder
It will: - create directory 'var/www/apps/mysite/shared' - initialize git repository in the directory
The 'shared' folder will store data in 'production-shared' branch.
Edit '/var/www/apps/mysite/shared/.gitignore' - see .gitignore for shared folder on local machine.
Deploy init
Push to remote repository
First, commit your changes on local machine:
git checkout master
git add -all
git commit -m "my changes"
Merge branch 'production' and push to the remote git server:
git checkout production
git merge master
git push origin production
go back to master branch:
git checkout master
Copy config files
cap production deploy:copy_config_files
This will copy config files to server.
Upload shared data to server
Copy files to shared folder site_production_shared on local machine.
Commit and push to the remote repository:
git checkout production-shared
git add .
git commit -m "my changes"
git push origin production-shared
Update shared folder on the server - run capistrano task from the app folder:
cap production mysync:shared:update_server
Deploy
cap production deploy
Issues
- If you get this error
DEBUG [6692d638] cannot access /var/www/apps/tpl_demo/releases/20150717052152/public/assets/manifest*.*
DEBUG [6692d638] : No such file or directory
to fix this run the commands on server:
cd /var/www/apps/mysite/releases/_release_id/
rake assets:precompile RAILS_ENV=production
run again 'cap production deploy'.
Sync shared data
Upload shared data to server
We want to upload shared data from local machine to the server.
cd site_production_shared
git checkout production-shared
git push origin production-shared
cd ../site
cd ../site
call cap production mysync:shared:update_server
Get shared data from server
Shared data can be updated on the server. For example, OptimaCMS can change files in app/views.
We want to get files from the server to our local machine (stored in folder site_production_shared).
# from main site folder
cd site
cap production mysync:shared:commit_server
# in site_production_shared
cd ../site_production_shared
git checkout production-shared
git pull origin production-shared