Skip to content

Instantly share code, notes, and snippets.

@donilan
Last active June 27, 2018 08:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save donilan/41ac004e4dc48d66db4c144b867fa4a4 to your computer and use it in GitHub Desktop.
Save donilan/41ac004e4dc48d66db4c144b867fa4a4 to your computer and use it in GitHub Desktop.
Mina deploy.rb with Docker-passenger, Pull this docker at registry.aliyuncs.com/doni/passenger if you are work from China.
require 'mina/git'
# Basic settings:
# domain - The hostname to SSH to.
# deploy_to - Path to deploy into.
# repository - Git repo to clone from. (needed by mina/git)
# branch - Branch name to deploy. (needed by mina/git)
set :app, "example"
set :bundle_path, "bundle"
set :domain, "example.com"
set :deploy_to, "/apps/#{app}"
set :app_path, lambda { "#{deploy_to}/#{current_path}" }
set :repository, 'git@example.com:example.git'
set :branch, ENV['branch'] || 'production'
set :server_port, '80'
# set :branch, 'docker'
set :bundle_options, %{--without development:test --path "#{bundle_path}" --deployment}
# Manually create these paths in shared/ (eg: shared/config/database.yml) in your server.
# They will be linked in the 'deploy:link_shared_paths' step.
set :shared_paths, ['config/database.yml', 'config/local_env.yml', 'log', 'tmp', bundle_path, 'public/assets']
set :forward_agent, true
set :term_mode, :system # this make sure that we get the prompt for yes/no
# Optional settings:
set :user, 'deploy' # Username in the server to SSH to.
# set :port, '10022' # SSH port number.
# Put any custom mkdir's in here for when `mina setup` is ran.
# For Rails apps, we'll make some of the shared paths that are shared between
# all releases.
task :setup => :environment do
queue! %[mkdir -p "#{deploy_to}/shared/tmp"]
queue! %[mkdir -p "#{deploy_to}/shared/public/assets"]
queue! %[mkdir -p "#{deploy_to}/shared/#{bundle_path}"]
queue! %[mkdir -p "#{deploy_to}/shared/log"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/log"]
queue! %[mkdir -p "#{deploy_to}/shared/config"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/config"]
invoke :'setup_db_conf'
invoke :'setup_rails_env_conf'
end
task :destroy do
queue! %[rm -rf "#{deploy_to}"]
end
desc "Deploys the current version to the server."
task :deploy => :environment do
deploy do
# Put things that will set up an empty directory into a fully set-up
# instance of your project.
invoke :'git:clone'
# invoke :'deploy:link_shared_paths'
to :launch do
# invoke :'docker:build'
invoke :'docker:stop' # stop the previous container
invoke :'docker:run' # run new container with released code
invoke :'docker:link_shared_paths'
invoke :'generate_nginx_conf'
invoke :'docker:link_nginx_conf'
invoke :'docker:post_deploy'
invoke :'docker:restart'
end
end
end
task :setup_rails_env_conf do
# Upload you local file as server conf
conf = File.read('./config/local_env.yml.sample').dedent
# use conf below as server conf
# conf = <<-EOF.dedent
# ---
# ENV_SAMPLE: "Hello world"
# EOF
queue! %[echo "#{conf}" > #{deploy_to}/shared/config/local_env.yml]
end
task :cat_rails_env_conf do
queue! %[cat #{deploy_to}/shared/config/local_env.yml]
end
task :cat_db_conf do
queue! %[cat #{deploy_to}/shared/config/database.yml]
end
task :setup_db_conf do
# Upload you local file as server conf
# conf = File.read('./config/database.yml').dedent
# use conf below as server conf
conf = <<-EOF.dedent
production:
adapter: mysql2
database: #{app}
username: #{app}
# password:
# host: localhost
socket: /var/run/mysqld/mysqld.sock
EOF
queue! %[echo "#{conf}" > #{deploy_to}/shared/config/database.yml]
invoke :'mysql_setup'
end
task :mysql_setup do
queue! %[echo "CREATE DATABASE #{app} DEFAULT CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci';" | mysql -uroot]
queue! %[echo "grant all on #{app}.* to #{app};" | mysql -uroot]
end
task :generate_nginx_conf do
nginx_conf = <<-EOF.dedent
server {
listen 80;
server_name #{domain};
server_name www.#{domain};
root /home/app/webapp/public;
passenger_enabled on;
passenger_user app;
passenger_ruby /usr/bin/ruby2.2;
}
EOF
queue! %[echo "#{nginx_conf}" > #{deploy_to}/shared/config/webapp.conf]
end
namespace :docker do
set :image_name, ENV.fetch("IMAGE_NAME", 'registry.aliyuncs.com/doni/passenger')
set :container_name, ENV.fetch("CONTAINER_NAME", "rails-webapp")
set :docker_exec, "docker exec -u app:app #{container_name}"
set :docker_app_path, "/home/app/webapp"
set :docker_shared_path, "/home/app/shared"
# Sharing mysql sockets to communicate Host and Container
# set :mysql_socket_volume, "/var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock"
# Mount configuration and log folders
set :volumes, [
"-v #{deploy_to}/#{current_path}:#{docker_app_path}",
"-v #{deploy_to}/shared:#{docker_shared_path}",
"-v /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock",
].join(' ')
task link_shared_paths: :environment do
shared_paths.each do |path|
src = "#{docker_shared_path}/#{path}"
target = "#{docker_app_path}/#{path}"
queue! %[docker exec -u app:app #{container_name} ln -fs #{src} #{target}]
end
end
task :link_nginx_conf do
queue! %[docker exec #{container_name} ln -fs #{docker_shared_path}/config/webapp.conf /etc/nginx/sites-enabled/webapp.conf]
end
desc "do migrate for rails app"
task post_deploy: :environment do
# queue %[docker exec #{container_name} gem sources --add https://ruby.taobao.org/ --remove https://rubygems.org/]
# queue %[docker exec #{container_name} gem install bundler]
queue %[docker exec -u app:app #{container_name} bundle install #{bundle_options}]
# queue %[docker exec -u app:app #{container_name} bundle exec rake db:create]
queue %[docker exec -u app:app #{container_name} bundle exec rake db:migrate]
queue %[docker exec -u app:app #{container_name} bundle exec rake assets:precompile]
end
# desc "Build docker image"
# task build: :environment do
# queue "cd #{deploy_to}/#{current_path}"
# queue "docker build --no-cache=true -t #{image_name} ."
# end
desc "Start docker container"
task run: :environment do
queue "docker run -d -p #{server_port}:80 #{volumes} --name #{container_name} #{image_name}"
end
desc "Debug docker container"
task debug: :environment do
queue "docker exec -t -i #{container_name} /bin/bash"
end
desc "Stop docker container"
task stop: :environment do
queue "if [ ! -z \"$(docker ps -a | grep '#{container_name}')\" ]; then docker stop #{container_name}; docker rm -f #{container_name}; fi"
end
desc "Remove all stop container"
task clean_containers: :environment do
queue "docker rm $(docker ps -a -q)"
end
task :restart do
queue %[docker exec -u app:app #{container_name} touch tmp/restart.txt]
end
task :logs do
queue %[docker exec #{container_name} tail -f log/production.log]
end
task :nginx_logs do
queue %[docker exec #{container_name} tail -f /var/log/nginx/error.log]
end
task :seed do
queue %[docker exec -u app:app #{container_name} bundle exec rake db:seed]
end
end
# For help in making your deploy script, see the Mina documentation:
#
# - http://nadarei.co/mina
# - http://nadarei.co/mina/tasks
# - http://nadarei.co/mina/settings
# - http://nadarei.co/mina/helpers
#
# See https://github.com/cespare/ruby-dedent/blob/master/lib/dedent.rb
#
class String
def dedent
lines = split "\n"
return self if lines.empty?
indents = lines.map do |line|
line =~ /\S/ ? (line.start_with?(" ") ? line.match(/^ +/).offset(0)[1] : 0) : nil
end
min_indent = indents.compact.min
return self if min_indent.zero?
lines.map { |line| line =~ /\S/ ? line.gsub(/^ {#{min_indent}}/, "") : line }.join "\n"
end
end
FROM phusion/passenger-full
# Set correct environment variables.
ENV HOME /root
# Use baseimage-docker's init process.
CMD ["/sbin/my_init"]
EXPOSE 80
RUN gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/
RUN gem install bundler
RUN apt-get update -y
RUN apt-get install ghostscript -y
RUN rm -f /etc/service/nginx/down
RUN rm /etc/nginx/sites-enabled/default
RUN usermod -u 1000 app
RUN groupmod -g 1000 app
ENV RAILS_ENV=production
WORKDIR /home/app/webapp
# Clean up APT when done.
# RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment