├── .dockerignore ├── .gitignore ├── Capfile ├── Dockerfile ├── Gemfile ├── Gemfile.lock ├── README.md ├── Rakefile ├── Vagrantfile ├── app ├── assets │ ├── images │ │ └── .keep │ ├── javascripts │ │ ├── application.js │ │ └── posts.coffee │ └── stylesheets │ │ ├── application.css │ │ ├── posts.scss │ │ └── scaffolds.scss ├── controllers │ ├── application_controller.rb │ ├── concerns │ │ └── .keep │ └── posts_controller.rb ├── helpers │ ├── application_helper.rb │ └── posts_helper.rb ├── jobs │ └── file_creator.rb ├── mailers │ └── .keep ├── models │ ├── .keep │ ├── concerns │ │ └── .keep │ └── post.rb └── views │ ├── layouts │ └── application.html.erb │ └── posts │ ├── _form.html.erb │ ├── edit.html.erb │ ├── index.html.erb │ ├── index.json.jbuilder │ ├── new.html.erb │ ├── show.html.erb │ └── show.json.jbuilder ├── bin ├── bundle ├── rails ├── rake ├── setup └── spring ├── config.rb ├── config.ru ├── config ├── application.rb ├── boot.rb ├── database.yml ├── deploy.rb ├── deploy │ ├── local.rb │ └── staging.rb ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── assets.rb │ ├── backtrace_silencers.rb │ ├── cookies_serializer.rb │ ├── filter_parameter_logging.rb │ ├── inflections.rb │ ├── mime_types.rb │ ├── rails_config.rb │ ├── resque.rb │ ├── session_store.rb │ └── wrap_parameters.rb ├── locales │ └── en.yml ├── resque.yml ├── routes.rb ├── secrets.yml ├── settings.yml └── settings │ ├── development.yml │ ├── production.yml │ └── test.yml ├── db ├── migrate │ └── 20150305170140_create_posts.rb ├── schema.rb └── seeds.rb ├── docker-compose-development.yml ├── docker-compose.yml ├── docker ├── rails │ ├── conf │ │ └── nginx.conf │ └── start.sh └── resque │ └── Dockerfile ├── lib ├── assets │ └── .keep ├── capistrano │ └── tasks │ │ └── docker.rake └── tasks │ ├── .keep │ └── resque.rake ├── log └── .keep ├── public ├── 404.html ├── 422.html ├── 500.html ├── favicon.ico └── robots.txt ├── railways.cache ├── test ├── controllers │ ├── .keep │ └── posts_controller_test.rb ├── fixtures │ ├── .keep │ └── posts.yml ├── helpers │ └── .keep ├── integration │ └── .keep ├── mailers │ └── .keep ├── models │ ├── .keep │ └── post_test.rb └── test_helper.rb ├── user-data └── vendor └── assets ├── javascripts └── .keep └── stylesheets └── .keep /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | 3 | db/*.sqlite3 4 | log/* 5 | tmp 6 | vendor 7 | Vagrantfile 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Ignore the default SQLite database. 11 | /db/*.sqlite3 12 | /db/*.sqlite3-journal 13 | 14 | # Ignore all logfiles and tempfiles. 15 | /log/* 16 | !/log/.keep 17 | /tmp 18 | 19 | /vendor/bundle 20 | 21 | config/settings.local.yml 22 | config/settings/*.local.yml 23 | config/environments/*.local.yml 24 | -------------------------------------------------------------------------------- /Capfile: -------------------------------------------------------------------------------- 1 | # Load DSL and set up stages 2 | require 'capistrano/setup' 3 | 4 | # Include default deployment tasks 5 | require 'capistrano/deploy' 6 | 7 | # Include tasks from other gems included in your Gemfile 8 | # 9 | # For documentation on these, see for example: 10 | # 11 | # https://github.com/capistrano/rvm 12 | # https://github.com/capistrano/rbenv 13 | # https://github.com/capistrano/chruby 14 | # https://github.com/capistrano/bundler 15 | # https://github.com/capistrano/rails 16 | # https://github.com/capistrano/passenger 17 | # 18 | # require 'capistrano/rvm' 19 | # require 'capistrano/rbenv' 20 | # require 'capistrano/chruby' 21 | # require 'capistrano/bundler' 22 | # require 'capistrano/rails/assets' 23 | # require 'capistrano/rails/migrations' 24 | # require 'capistrano/passenger' 25 | 26 | # Load custom tasks from `lib/capistrano/tasks` if you have any defined 27 | Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r } 28 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ruby:2.2.1 2 | MAINTAINER Mook 3 | 4 | # Install nginx with passenger 5 | RUN gem install passenger -v 5.0.4 && \ 6 | apt-get update && \ 7 | apt-get install -y libcurl4-openssl-dev && \ 8 | passenger-install-nginx-module --auto 9 | 10 | ADD docker/rails/conf/nginx.conf /opt/nginx/conf/nginx.conf 11 | 12 | # Add configuration to set daemon mode off 13 | RUN echo "daemon off;" >> /opt/nginx/conf/nginx.conf 14 | 15 | # Install Rails dependencies 16 | RUN apt-get update && apt-get install -y nodejs --no-install-recommends && rm -rf /var/lib/apt/lists/* 17 | RUN apt-get update && apt-get install -y mysql-client postgresql-client sqlite3 --no-install-recommends && rm -rf /var/lib/apt/lists/* 18 | 19 | # throw errors if Gemfile has been modified since Gemfile.lock 20 | RUN bundle config --global frozen 1 21 | 22 | RUN mkdir -p /usr/src/app 23 | WORKDIR /usr/src/app 24 | 25 | ADD Gemfile /usr/src/app/ 26 | ADD Gemfile.lock /usr/src/app/ 27 | RUN bundle install --system 28 | 29 | ADD . /usr/src/app 30 | 31 | # Initialize log 32 | RUN cat /dev/null > /usr/src/app/log/production.log 33 | RUN chmod -R a+w /usr/src/app/log 34 | 35 | EXPOSE 80 36 | 37 | ENV RAILS_ENV=production 38 | 39 | ADD docker/rails/start.sh /usr/src/app/ 40 | RUN chmod +x /usr/src/app/start.sh 41 | WORKDIR /usr/src/app/ 42 | CMD ["./start.sh"] 43 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | 4 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 5 | gem 'rails', '4.2.0' 6 | # Use sqlite3 as the database for Active Record 7 | gem 'sqlite3' 8 | # Use SCSS for stylesheets 9 | gem 'sass-rails', '~> 5.0' 10 | # Use Uglifier as compressor for JavaScript assets 11 | gem 'uglifier', '>= 1.3.0' 12 | # Use CoffeeScript for .coffee assets and views 13 | gem 'coffee-rails', '~> 4.1.0' 14 | # See https://github.com/sstephenson/execjs#readme for more supported runtimes 15 | # gem 'therubyracer', platforms: :ruby 16 | 17 | # Use jquery as the JavaScript library 18 | gem 'jquery-rails' 19 | # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks 20 | gem 'turbolinks' 21 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder 22 | gem 'jbuilder', '~> 2.0' 23 | # bundle exec rake doc:rails generates the API under doc/api. 24 | gem 'sdoc', '~> 0.4.0', group: :doc 25 | 26 | # Use ActiveModel has_secure_password 27 | # gem 'bcrypt', '~> 3.1.7' 28 | 29 | # Use Unicorn as the app server 30 | # gem 'unicorn' 31 | 32 | # Use Capistrano for deployment 33 | gem 'capistrano', '~> 3.1' 34 | gem 'capistrano-rails', '~> 1.1' 35 | 36 | # For queing 37 | gem 'resque', '~> 1.25.2', github: 'resque/resque', tag: 'v1.25.2' 38 | 39 | gem 'rails_config', '~> 0.4.2' 40 | 41 | group :development, :test do 42 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console 43 | gem 'byebug' 44 | 45 | # Access an IRB console on exception pages or by using <%= console %> in views 46 | gem 'web-console', '~> 2.0' 47 | 48 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring 49 | gem 'spring' 50 | 51 | gem 'pry-rails' 52 | gem 'pry-doc' 53 | end 54 | 55 | group :production do 56 | # postgre is needed for production 57 | gem 'pg' 58 | end 59 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GIT 2 | remote: git://github.com/resque/resque.git 3 | revision: 5379faa08db53233d7a1bbc4f1e01104be7d7851 4 | tag: v1.25.2 5 | specs: 6 | resque (1.25.2) 7 | mono_logger (~> 1.0) 8 | multi_json (~> 1.0) 9 | redis-namespace (~> 1.3) 10 | sinatra (>= 0.9.2) 11 | vegas (~> 0.1.2) 12 | 13 | GEM 14 | remote: https://rubygems.org/ 15 | specs: 16 | actionmailer (4.2.0) 17 | actionpack (= 4.2.0) 18 | actionview (= 4.2.0) 19 | activejob (= 4.2.0) 20 | mail (~> 2.5, >= 2.5.4) 21 | rails-dom-testing (~> 1.0, >= 1.0.5) 22 | actionpack (4.2.0) 23 | actionview (= 4.2.0) 24 | activesupport (= 4.2.0) 25 | rack (~> 1.6.0) 26 | rack-test (~> 0.6.2) 27 | rails-dom-testing (~> 1.0, >= 1.0.5) 28 | rails-html-sanitizer (~> 1.0, >= 1.0.1) 29 | actionview (4.2.0) 30 | activesupport (= 4.2.0) 31 | builder (~> 3.1) 32 | erubis (~> 2.7.0) 33 | rails-dom-testing (~> 1.0, >= 1.0.5) 34 | rails-html-sanitizer (~> 1.0, >= 1.0.1) 35 | activejob (4.2.0) 36 | activesupport (= 4.2.0) 37 | globalid (>= 0.3.0) 38 | activemodel (4.2.0) 39 | activesupport (= 4.2.0) 40 | builder (~> 3.1) 41 | activerecord (4.2.0) 42 | activemodel (= 4.2.0) 43 | activesupport (= 4.2.0) 44 | arel (~> 6.0) 45 | activesupport (4.2.0) 46 | i18n (~> 0.7) 47 | json (~> 1.7, >= 1.7.7) 48 | minitest (~> 5.1) 49 | thread_safe (~> 0.3, >= 0.3.4) 50 | tzinfo (~> 1.1) 51 | arel (6.0.0) 52 | binding_of_caller (0.7.2) 53 | debug_inspector (>= 0.0.1) 54 | builder (3.2.2) 55 | byebug (3.5.1) 56 | columnize (~> 0.8) 57 | debugger-linecache (~> 1.2) 58 | slop (~> 3.6) 59 | capistrano (3.4.0) 60 | i18n 61 | rake (>= 10.0.0) 62 | sshkit (~> 1.3) 63 | capistrano-bundler (1.1.4) 64 | capistrano (~> 3.1) 65 | sshkit (~> 1.2) 66 | capistrano-rails (1.1.2) 67 | capistrano (~> 3.1) 68 | capistrano-bundler (~> 1.1) 69 | coderay (1.1.0) 70 | coffee-rails (4.1.0) 71 | coffee-script (>= 2.2.0) 72 | railties (>= 4.0.0, < 5.0) 73 | coffee-script (2.3.0) 74 | coffee-script-source 75 | execjs 76 | coffee-script-source (1.9.1) 77 | colorize (0.7.5) 78 | columnize (0.9.0) 79 | debug_inspector (0.0.2) 80 | debugger-linecache (1.2.0) 81 | erubis (2.7.0) 82 | execjs (2.3.0) 83 | globalid (0.3.3) 84 | activesupport (>= 4.1.0) 85 | hike (1.2.3) 86 | i18n (0.7.0) 87 | jbuilder (2.2.9) 88 | activesupport (>= 3.0.0, < 5) 89 | multi_json (~> 1.2) 90 | jquery-rails (4.0.3) 91 | rails-dom-testing (~> 1.0) 92 | railties (>= 4.2.0) 93 | thor (>= 0.14, < 2.0) 94 | json (1.8.2) 95 | loofah (2.0.1) 96 | nokogiri (>= 1.5.9) 97 | mail (2.6.3) 98 | mime-types (>= 1.16, < 3) 99 | method_source (0.8.2) 100 | mime-types (2.4.3) 101 | mini_portile (0.6.2) 102 | minitest (5.5.1) 103 | mono_logger (1.1.0) 104 | multi_json (1.11.0) 105 | net-scp (1.2.1) 106 | net-ssh (>= 2.6.5) 107 | net-ssh (2.9.2) 108 | nokogiri (1.6.6.2) 109 | mini_portile (~> 0.6.0) 110 | pg (0.18.1) 111 | pry (0.10.1) 112 | coderay (~> 1.1.0) 113 | method_source (~> 0.8.1) 114 | slop (~> 3.4) 115 | pry-doc (0.6.0) 116 | pry (~> 0.9) 117 | yard (~> 0.8) 118 | pry-rails (0.3.3) 119 | pry (>= 0.9.10) 120 | rack (1.6.0) 121 | rack-protection (1.5.3) 122 | rack 123 | rack-test (0.6.3) 124 | rack (>= 1.0) 125 | rails (4.2.0) 126 | actionmailer (= 4.2.0) 127 | actionpack (= 4.2.0) 128 | actionview (= 4.2.0) 129 | activejob (= 4.2.0) 130 | activemodel (= 4.2.0) 131 | activerecord (= 4.2.0) 132 | activesupport (= 4.2.0) 133 | bundler (>= 1.3.0, < 2.0) 134 | railties (= 4.2.0) 135 | sprockets-rails 136 | rails-deprecated_sanitizer (1.0.3) 137 | activesupport (>= 4.2.0.alpha) 138 | rails-dom-testing (1.0.5) 139 | activesupport (>= 4.2.0.beta, < 5.0) 140 | nokogiri (~> 1.6.0) 141 | rails-deprecated_sanitizer (>= 1.0.1) 142 | rails-html-sanitizer (1.0.1) 143 | loofah (~> 2.0) 144 | rails_config (0.4.2) 145 | activesupport (>= 3.0) 146 | railties (4.2.0) 147 | actionpack (= 4.2.0) 148 | activesupport (= 4.2.0) 149 | rake (>= 0.8.7) 150 | thor (>= 0.18.1, < 2.0) 151 | rake (10.4.2) 152 | rdoc (4.2.0) 153 | json (~> 1.4) 154 | redis (3.2.1) 155 | redis-namespace (1.5.1) 156 | redis (~> 3.0, >= 3.0.4) 157 | sass (3.4.13) 158 | sass-rails (5.0.1) 159 | railties (>= 4.0.0, < 5.0) 160 | sass (~> 3.1) 161 | sprockets (>= 2.8, < 4.0) 162 | sprockets-rails (>= 2.0, < 4.0) 163 | tilt (~> 1.1) 164 | sdoc (0.4.1) 165 | json (~> 1.7, >= 1.7.7) 166 | rdoc (~> 4.0) 167 | sinatra (1.4.5) 168 | rack (~> 1.4) 169 | rack-protection (~> 1.4) 170 | tilt (~> 1.3, >= 1.3.4) 171 | slop (3.6.0) 172 | spring (1.3.3) 173 | sprockets (2.12.3) 174 | hike (~> 1.2) 175 | multi_json (~> 1.0) 176 | rack (~> 1.0) 177 | tilt (~> 1.1, != 1.3.0) 178 | sprockets-rails (2.2.4) 179 | actionpack (>= 3.0) 180 | activesupport (>= 3.0) 181 | sprockets (>= 2.8, < 4.0) 182 | sqlite3 (1.3.10) 183 | sshkit (1.7.1) 184 | colorize (>= 0.7.0) 185 | net-scp (>= 1.1.2) 186 | net-ssh (>= 2.8.0) 187 | thor (0.19.1) 188 | thread_safe (0.3.4) 189 | tilt (1.4.1) 190 | turbolinks (2.5.3) 191 | coffee-rails 192 | tzinfo (1.2.2) 193 | thread_safe (~> 0.1) 194 | uglifier (2.7.1) 195 | execjs (>= 0.3.0) 196 | json (>= 1.8.0) 197 | vegas (0.1.11) 198 | rack (>= 1.0.0) 199 | web-console (2.1.1) 200 | activemodel (>= 4.0) 201 | binding_of_caller (>= 0.7.2) 202 | railties (>= 4.0) 203 | sprockets-rails (>= 2.0, < 4.0) 204 | yard (0.8.7.6) 205 | 206 | PLATFORMS 207 | ruby 208 | 209 | DEPENDENCIES 210 | byebug 211 | capistrano (~> 3.1) 212 | capistrano-rails (~> 1.1) 213 | coffee-rails (~> 4.1.0) 214 | jbuilder (~> 2.0) 215 | jquery-rails 216 | pg 217 | pry-doc 218 | pry-rails 219 | rails (= 4.2.0) 220 | rails_config (~> 0.4.2) 221 | resque (~> 1.25.2)! 222 | sass-rails (~> 5.0) 223 | sdoc (~> 0.4.0) 224 | spring 225 | sqlite3 226 | turbolinks 227 | uglifier (>= 1.3.0) 228 | web-console (~> 2.0) 229 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | rails-docker-example 2 | ================================================================================ 3 | 4 | 5 | 6 | ## Contents 7 | 8 | - [Summary](#summary) 9 | - [How to run containers](#how-to-run-containers) 10 | - [Requirements](#requirements) 11 | - [Run containers](#run-containers) 12 | - [For development environment](#for-development-environment) 13 | - [Deployment](#deployment) 14 | - [Set up for DigitalOcean droplet](#set-up-for-digitalocean-droplet) 15 | - [Install Docker and Docker Compose](#install-docker-and-docker-compose) 16 | - [Set up deploy user](#set-up-deploy-user) 17 | - [Add deploy keys to repo on Github](#add-deploy-keys-to-repo-on-github) 18 | - [capistrano](#capistrano) 19 | - [* If you met `exit status 4` while building Docker image](#-if-you-met-exit-status-4-while-building-docker-image) 20 | - [Deploy with CircleCI](#deploy-with-circleci) 21 | - [circle.yml](#circleyml) 22 | - [Manage persistent data](#manage-persistent-data) 23 | - [Backup and restore data](#backup-and-restore-data) 24 | - [Static files in `/tmp` directory](#static-files-in-tmp-directory) 25 | - [DB data](#db-data) 26 | - [TIPS: Zero time deployment with CoreOS and vulcand](#tips-zero-time-deployment-with-coreos-and-vulcand) 27 | - [Setup environment as Vagrant](#setup-environment-as-vagrant) 28 | 29 | 30 | 31 | ## Summary 32 | 33 | This repository is a example project by Rails with Resque worker. 34 | The structure of the project is following; quite simple: 35 | 36 | ``` 37 | ███████████████████ ███████████████████ 38 | ███████████████████ ███████████████████ 39 | ███████Redis███████ ██████Postgre██████ 40 | ███████████████████ ███████████████████ 41 | ███████████████████ ███████████████████ 42 | ┼ ▲ ▲ 43 | │ │ │ 44 | Load ┌─────────┘ │ │ 45 | information │ │ ┌─────────────────────┐ 46 | for job │ │ │ Rails │ 47 | ╱│╲ │ │ Web application │ 48 | ┌─────────────────┐ │ │ │ 49 | │ │ │ │ ┌──────────────┐ │ 50 | │ Rescue worker │ │ Register jobs │ │ │ │ 51 | │ │ └────────────────┼───│ Resque Task │ │ 52 | │ │ │ │ │ │ 53 | └─────────────────┘ │ └──────────────┘ │ 54 | └─────────────────────┘ 55 | ``` 56 | 57 | * Rails 58 | * Resque 59 | * It can be used by Rails and also worker is run independently 60 | * It is expected to be run as several workers 61 | * Postgre 62 | * DB for models of Rails 63 | * Redis 64 | * For Resque 65 | * Data container 66 | * data-only-container for persistent data like temporary file and data for DB 67 | * This is mounted to containers 68 | 69 | ## How to run containers 70 | 71 | ### Requirements 72 | 73 | These are required to run it as Docker containers. 74 | 75 | * docker 76 | * docker-compose 77 | 78 | ### Run containers 79 | 80 | All you have to do is bellow: 81 | 82 | ```sh 83 | docker-compose up 84 | ``` 85 | 86 | ## For development environment 87 | 88 | For development environment, you can use `docker-compose-development.yml` on your local machine. 89 | 90 | It is basically same as `docker-compose.yml` for staging or production environment but it shares your local Rails project with web container with using same image as staging/production. 91 | When you update code, you can see changes for it as you run `rails server` on your local too. 92 | 93 | This is `docker-compose-development.yml`: 94 | 95 | ```yml 96 | web: 97 | build: . 98 | links: 99 | - postgres 100 | - redis 101 | ports: 102 | - "80:80" 103 | # Following is development configuration 104 | command: /bin/bash -c "rake db:migrate && rails server -b 0.0.0.0 -p 80" 105 | environment: 106 | RAILS_ENV: development 107 | volumes_from: 108 | - data 109 | # ... 110 | # omitted some lines... 111 | # ... 112 | data: 113 | image: busybox 114 | volumes: 115 | - /tmp 116 | # For postgres 117 | - /var/lib/postgresql/data 118 | - .:/usr/src/app 119 | ``` 120 | 121 | ## Deployment 122 | 123 | **Currently, this example does not support hot-deployment. This example has deployment task by capistrano but it needs to restart all containers when you want to update application.** 124 | 125 | This is example to deploy these containers to a Ubuntu 14.04 droplet on 126 | [DigitalOcean](https://www.digitalocean.com/). 127 | 128 | ### Set up for DigitalOcean droplet 129 | 130 | #### Install Docker and Docker Compose 131 | 132 | Install the latest Docker by following documentation: [Ubuntu - Docker 133 | Documentation](https://docs.docker.com/installation/ubuntulinux/#docker-maintained-package-installation) 134 | 135 | ```sh 136 | apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9 137 | sudo sh -c "echo deb https://get.docker.com/ubuntu docker main \ 138 | apt/sources.list.d/docker.list" 139 | sudo apt-get update && \ 140 | apt-get install -y lxc-docker 141 | ``` 142 | 143 | Install Docker Compose 144 | 145 | ```sh 146 | curl -L https://github.com/docker/compose/releases/download/1.1.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose 147 | chmod a+x /usr/local/bin/docker-compose 148 | ``` 149 | 150 | #### Set up deploy user 151 | 152 | It needs that `deploy` user to deploy source code to this droplet. 153 | 154 | ```sh 155 | sudo adduser deploy 156 | sudo passwd -l deploy # Do this to make password string which is not able to input 157 | ``` 158 | 159 | Add deploy user to `docker` group to be able to execute `docker` command. 160 | 161 | ```sh 162 | sudo gpasswd -a deploy docker 163 | ``` 164 | 165 | And create key for deploy user. 166 | 167 | ```sh 168 | su deploy 169 | ssh-keygen -t rsa -C "deploy" 170 | ``` 171 | 172 | #### Add deploy keys to repo on Github 173 | 174 | Create deploy key of your repository with key of deploy user: [Managing deploy keys | GitHub API](https://developer.github.com/guides/managing-deploy-keys/#setup-2) 175 | 176 | After set up deploy key of your repository, you can clone your repository via git command like this: 177 | 178 | ```sh 179 | git clone git@github.com:your-username/your-repo.git 180 | ``` 181 | 182 | ### capistrano 183 | 184 | To deploy the application to droplet, it has capistrano file. Execute deployment manually by executing this command: 185 | 186 | ```sh 187 | DEPLOY_TARGET_HOST=your.host.name bundle exec cap staging docker:deploy 188 | ``` 189 | 190 | `docker.rake` has 3 tasks. 191 | 192 | 1. update 193 | * Update git repository of Rails project 194 | 2. build 195 | * Build Docker images 196 | 3. deploy 197 | * Run Docker containers 198 | * This task executes 3 commands of `docker-compose`: stop, rm and up. You don't have to care of containers running as it stops all of running containers. 199 | 200 | Building images and running containers works by execute `docker-compose`. 201 | See [docker-compose.yml](https://github.com/mookjp/rails-docker-example/blob/master/docker-compose.yml) 202 | 203 | #### * If you met `exit status 4` while building Docker image 204 | 205 | You may meet this error while you build your Docker image: 206 | 207 | ``` 208 | Your compiler failed with the exit status 4. This probably means that it ran out of memory. To solve this problem, try increasing your swap space: https://www.digitalocean.com/community/articles/how-to-add-swap-on-ubuntu-12-04 209 | ``` 210 | 211 | You can upgrade space to add swap space following this procedure: 212 | [How To Add Swap on Ubuntu 14.04 | DigitalOcean](https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-14-04) 213 | 214 | I confirmed that swap 4GB works for this project. 215 | 216 | ### Deploy with CircleCI 217 | 218 | #### circle.yml 219 | 220 | This project has a sample `circle.yml` to deploy it to DO's droplet. 221 | 222 | 223 | ## Manage persistent data 224 | 225 | This project uses data-only-container for portability of persistent data, for example, temporary file which is needed by the application, DB data and etc. 226 | It follows the instruction in Documentation of Docker: [Managing data in containers - Docker Documentation](https://docs.docker.com/userguide/dockervolumes/) and There's nothing new to the documentation. 227 | 228 | This project has Resque job, `FileCreator`. This is just to create file when the new post was created. And file is saved in `/tmp` in production; this is sample so it is meaningless!. See `config/settings/production.yml` and `app/jobs/file_creator.rb`. 229 | 230 | Following is the way to backup files which was saved in `/tmp` and restore them. 231 | 232 | ### Backup and restore data 233 | 234 | #### Static files in `/tmp` directory 235 | 236 | In this case, it just needs to create backup file from container directory and extract it to container. 237 | 238 | ```sh 239 | # Create backup as a tar file 240 | docker run --volumes-from railsdockerexample_data_1 -v $(pwd)/backup:/backup busybox tar cvf /backup/backup.tar /tmp 241 | # Restore it 242 | docker run --volumes-from railsdockerexample_data_1 -v $(pwd)/backup:/backup busybox tar xvf /backup/backup.tar 243 | ``` 244 | 245 | #### DB data 246 | 247 | If you need to backup and restore postgres DB data, you can do it by following: 248 | 249 | ```sh 250 | # Create backup as a tar file 251 | docker run --volumes-from railsdockerexample_data_1 -v $(pwd)/backup:/backup busybox tar cvf /backup/backup.tar /var/lib/postgresql/data 252 | # Restore it 253 | docker run --volumes-from railsdockerexample_data_1 -v $(pwd)/backup:/backup busybox tar xvf /backup/backup.tar 254 | # Restart containers; As restarted container may have new ip address and Rails knows it only to read ENV --- it was set --link option and it will not update automatically 255 | docker-compose restart 256 | ``` 257 | 258 | ## TIPS: Zero time deployment with CoreOS and vulcand 259 | 260 | We can do zero time deployment by using CoreOS and [mailgun/vulcand](https://github.com/mailgun/vulcand). This project has `Vagrantfile` to up the environment for it. 261 | 262 | Ref: [Vulcand を使って Docker コンテナをブルーグリーンデプロイする - Qiita](http://qiita.com/spesnova/items/34d787f6b46761f775a4#upstream-example-v1-%E3%81%AE%E8%A8%AD%E5%AE%9A) 263 | 264 | Quite simple to do that. vulcand has the very simple system to handle some endpoints; `Frontend`, `Backend` and `Servers`. In this case, the container is `Server`. 265 | 266 | We can build and start container with versioned source code with commit-id then switch endpoint like this: 267 | 268 | ```sh 269 | # Create new Backend linked to new version 270 | etcdctl set /vulcand/backends/8c5a86/backend '{"Type": "http"}' 271 | 272 | # Create new Server linked to the Backend 273 | etcdctl set /vulcand/backends/8c5a86/servers/srv1 '{"URL": "http://localhost:5000"}' 274 | 275 | # Update Frontend with new Backend Id 276 | etcdctl set /vulcand/frontends/f1/frontend '{"Type": "http", "BackendId": "8c5a86", "Route": "PathRegexp(`/.*`)"}' 277 | ``` 278 | 279 | ``` 280 | ┌───────────────────────────────────────────────────────────────────┐ 281 | │ FrontEnd │ 282 | │ {"Type": "http", "BackendId": "a43bd2", │ 283 | │ "Route": "PathRegexp(`/.*`)"} │ 284 | │ │ 285 | └───────────────────────────────────────────────────────────────────┘ 286 | │ 287 | Frontend forwards request to │ * Switch the target "Server" by set 288 | the container which was linked │ backend Id of commit id via etcd 289 | to backend │ API after the new container was 290 | ┌─────────────────┘ built and ready. 291 | │ 292 | │ 293 | │ 294 | │ 295 | ▼ 296 | ┌───────────────────────────────┐ ┌───────────────────────────────┐ 297 | │ Backend │ │ Backend │ 298 | │ /vulcand/backends/a43bd2 │ │ /vulcand/backends/8c5a86 │ 299 | │ {"Type": "http"} │ │ {"Type": "http"} │ 300 | │ │ │ │ 301 | └───────────────────────────────┘ └───────────────────────────────┘ 302 | ┼ ┼ 303 | │ │ 304 | ┼ ┼ 305 | ┌───────────────────────────────┐ ┌───────────────────────────────┐ 306 | │ Server │ │ Server │ 307 | │/vulcand/backends/a43bd2/server│ │/vulcand/backends/8c5a86/server│ 308 | │ s/srv1 │ │ s/srv1 │ 309 | │{"URL": "http://0.0.0.0:8080"} │ │{"URL": "http://0.0.0.0:8081"} │ 310 | └───────────────────────────────┘ └───────────────────────────────┘ 311 | ┼ ┼ 312 | │ │ 313 | ┼ ┼ 314 | ┌───────────────────────────────┐ ┌───────────────────────────────┐ 315 | │ Docker container │ │ Docker container │ 316 | │ (built as a43bd2) │ │ (built as 8c5a86) │ 317 | │ 0.0.0.0:8080 │ │ 0.0.0.0:8081 │ 318 | │ │ │ │ 319 | └───────────────────────────────┘ └───────────────────────────────┘ 320 | ``` 321 | 322 | **NOTICE: This wouldn't fit production environment as it builds Docker image inside the only host. It may affects performance while users send request to the only host. For production, it needs to change to use Docker registry and run containers by pulling image from there.** 323 | 324 | ### Setup environment as Vagrant 325 | 326 | Install vagrant dns plugin for local dns. Then run `vagrant up` to up your local environment. 327 | 328 | **This plugin supports MacOS only** 329 | 330 | ```sh 331 | vagrant plugin install vagrant-dns 332 | vagrant dns --install 333 | vagrant ssh-config >> ~/.ssh/config 334 | vagrant up 335 | ``` 336 | 337 | ### See how it works to deploy it to Vagrant 338 | 339 | All needed tasks are already included in [rails-docker-example/docker.rake at master · mookjp/rails-docker-example](https://github.com/mookjp/rails-docker-example/blob/master/lib%2Fcapistrano%2Ftasks%2Fdocker.rake). 340 | You can deploy new containers with zero time deployment with Vagrant: 341 | 342 | ```sh 343 | vagrant up 344 | bundle exec cap local docker:deploy # `local` environment is for vagrant 345 | ``` 346 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path('../config/application', __FILE__) 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # # vi: set ft=ruby : 3 | 4 | SYNCED_DIR_PATH = '/home/core/rails-docker-example' 5 | 6 | # provisioning script 7 | # TODO: split it as .sh file 8 | $script = <