Введение
Данное руководство в первую очередь предназначено для новичков, которые хотят научиться азам деплоя и ознакомиться в общих чертах с алгоритмом работы над удаленной unix системой локально, в качестве удаленного сервера мы будем использовать образ Ubuntu запущенный в Docker.
Итак, что же такое Mina? Это инструмент для деплоя и автоматизации выполнения операций на удаленном сервере.Преимущество этого решения, в первую очередь, заключается в быстроте выполнения. Mina работает очень быстро, поскольку деплоит bash скрипт, который генерируется на удаленном сервере из вашего deploy.rb файла и в последствии выполняется.
Capistrano, к примеру, выполняет каждую команду отдельно, в своей ssh сессии, и поэтому уступает по скорости в разы, mina выполняет все в одном bash скрипте, который требует только одну сессию.
Требования
В этом руководстве, предполагается, что вы используете Ubuntu и у вас уже установлено следующее программное обеспечение:
Подготовка Rails приложения
Я не буду рассматривать подробно шаги создания Rails приложения, поскольку самым лучшим вариантом будет наличие у вас своего приложения, которое вы хотели бы задеплоить. Либо вы можете воспользоваться тестовым примером github.com/rails-guides/mina-deploy-example
Установка SSH / Rbenv / Ruby & Rails
Итак, у вас установлен Docker и имеется образ Ubuntu. Если все сделано верно, то при вызове команды docker images вы должны увидеть следующую информацию:
root@root:~$ docker images | grep ubuntu
ubuntu latest 0ef2e08ed3fa 6 weeks ago 130MB
Запускаем данную последовательность операций в консоли:
docker run -d -it -p 2222:22 ubuntu:16.04
docker ps //Скопируйте container_id
docker attach container_id
Первая команда запустит образ Ubuntu в фоновом режиме и открытым портом для ssh подключения. Далее мы подключаемся к системе через attach с использованием уникального идентификатора контейнера.
После того, как вы вошли в систему под пользователем root, вам необходимо получить последние обновления, установить ssh-сервер и запустить его.
apt-get update
apt-get install openssh-server
service ssh start
Добавляем в систему пользователя deployer, мы будем использовать его при настройке mina.
adduser deployer
Система попросит заполнить вас некоторые данные (first_name и т.д), эти шаги можно пропустить. В качестве пароля используйте 123. Далее подключаемся по ssh чтобы удостовериться, что все сделано правильно.
ssh -p 2222 deployer@0.0.0.0
! Если у вас появится предупреждение `WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED`
Выполните удаление ключей из файла known_host с указанным сокетом (0.0.0.0:2222).
ssh-keygen -f "/home/USER/.ssh/known_hosts" -R [0.0.0.0]:2222
После этого переподключитесь еще раз и вы увидите следующее:
deployer@e2cad98fb69d:~$
SSH работает, отлично! Вернемся к нашему пользователю root, нам все еще необходимо установить rbenv / ruby / rails. В первую очередь нам потребуется git для установки rbenv.
apt-get install git
Проследуйте шагам описанным в официальной документации для установки.
github.com/rbenv/rbenv#installation
Для работы с ruby нам нужно предустановить следующие библиотеки:
apt-get install bzip2
apt-get install -y libssl-dev libreadline-dev zlib1g-dev
apt-get install build-essential
Мне понадобится ruby версии 2.3.1 и RoR 4.2.7.1. Не забудьте определить вашу Ruby версию глобально.
rbenv install -v 2.3.1
rbenv global 2.3.1
gem install rails -v 4.2.7.1
Установка Postgres / Nginx
apt-get install postgresql postgresql-contrib
service postgresql start
Определим пароль для пользователя postgres (все тот же 123)
su - postgres
psql
\password
create database mina_deploy_example; //заранее создадим базу данных
Nginx?—?веб-сервер и почтовый прокси-сервер, работающий на Unix-подобных операционных системах.
apt-get install nginx
После установки измените конфигурационный файл на нижеследующий.
nano /etc/nginx/sites-available/default
upstream mysite {
server unix:///home/deployer/mina-deploy-example/shared/tmp/sockets/puma.sock fail_timeout=0;
}
server {
listen 80;
listen [::]:80;
root /home/deployer/mina-deploy-example/current/public;
location ~ ^/assets/ {
expires max;
gzip_static on;
gzip_vary on;
add_header Cache-Control public;
break;
}
location ~ ^/system/ {
expires max;
gzip_static on;
gzip_vary on;
add_header Cache-Control public;
break;
}
location / {
proxy_pass http://mysite; # match the name of upstream directive which is defined above
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ~ ^/(500|404|422).html {
root /home/deployer/mina-deploy-example/current/public;
}
error_page 500 502 503 504 /500.html;
error_page 404 /404.html;
error_page 422 /422.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
Настройка git репозитория
Для деплоя через mina вам необходимо создать репозиторий на github, настроить git пользователя, сгенерировать ssh ключ и добавить его в ваш репозиторий. Для примера я буду использовать github
ssh -p 2222 deployer@0.0.0.0
git config --global user.name "Some User"
git config --global user.email "someuser@example.com"
ssh-keygen -t rsa -b 4096 -C "someuser@example.com"
ssh -T git@github.com
Скопируйте публичный ключ
cat ~/.ssh/id_rsa.pub
Переходим на github > ваш репозиторий > settings > слева выбираем Deploy keys > жмем Add deploy key и вставляем скопированное значение.
Deploy при помощи mina
Переходим в директорию проекта, добавляем в Gemfile
gem 'mina'
gem 'mina-puma', require: false
gem 'mina-nginx', require: false
В папке config создайте файл deploy.rb, он будет использоваться mina при деплое приложения. Файл конфигурации состоит из нескольких основных частей.
require 'mina/bundler'
require 'mina/rails'
require 'mina/git'
require 'mina/rbenv'
require 'mina/nginx'
require 'mina/puma'
set :application_name, 'mina-deploy-example'
set :domain, '127.0.0.1'
set :port, '2222'
set :user, 'deployer'
set :shared_dirs, fetch(:shared_dirs, []).push('tmp', 'log', 'public/uploads', 'public/system')
set :shared_files, fetch(:shared_files, []).push('config/puma.rb', 'config/database.yml', 'config/secrets.yml')
set :deploy_to, '/home/deployer/mina-deploy-example'
set :repository, 'git@github.com:rails-guides/mina-deploy-example.git'
set :branch, 'master'
set :rails_env, 'production'
В верхней части мы подключаем зависимости, устанавливаем домен приложения, порт и пользователя через которого будет создаваться bash скрипт и идти выполнение команд. На файлы и директории объвленные в shared_dirs и shared_files будет создана символическая ссылка.
Данная часть определяет команды, которые будут выполненны при вызове mina setup.
task :environment do
invoke :'rbenv:load'
end
task setup: :environment do
command %{mkdir -p "#{fetch(:shared_path)}/log"}
command %{chmod g+rx,u+rwx "#{fetch(:shared_path)}/log"}
command %{mkdir -p "#{fetch(:shared_path)}/config"}
command %{chmod g+rx,u+rwx "#{fetch(:shared_path)}/config"}
command %{touch "#{fetch(:shared_path)}/config/puma.rb"}
command %{touch "#{fetch(:shared_path)}/config/database.yml"}
command %{touch "#{fetch(:shared_path)}/config/secrets.yml"}
command %{mkdir -p "#{fetch(:shared_path)}/tmp/sockets"}
command %{chmod g+rx,u+rwx "#{fetch(:shared_path)}/tmp/sockets"}
command %{mkdir -p "#{fetch(:shared_path)}/tmp/pids"}
command %{chmod g+rx,u+rwx "#{fetch(:shared_path)}/tmp/pids"}
end
И основная часть, то, что будет выполняться каждый раз при деплое приложения.
task deploy: :environment do
deploy do
invoke :'git:clone'
invoke :'deploy:link_shared_paths'
on :build do
invoke :'bundle:install'
invoke :'rails:db_migrate'
invoke :'rails:assets_precompile'
invoke :'deploy:cleanup'
end
on :launch do
invoke :'puma:restart'
end
end
end
В директории проекта, в папке config, вам необходимо создать файл puma.rb.
directory '/home/deployer/mina-deploy-example/current'
rackup '/home/deployer/mina-deploy-example/current/config.ru'
environment 'production'
daemonize true
pidfile '/home/deployer/mina-deploy-example/shared/tmp/pids/puma.pid'
state_path '/home/deployer/mina-deploy-example/shared/tmp/sockets/puma.state'
bind 'unix:///home/deployer/mina-deploy-example/shared/tmp/sockets/puma.sock'
activate_control_app 'unix:///home/deployer/mina-deployexample/shared/tmp/sockets/pumactl.sock'
Данный конфиг позволяет запустить сервер в фоновом режим и production окружении привязывая сервер к unix сокету. Хорошее объяснение команд для настройки puma вы можете найти в этом репозитории и официальной документации github.com/puma/puma/blob/master/examples/config.rb.
Создайте database.yml и secrets.yml в папке /home/deployer/mina-deploy-example/shared/config
production:
host: localhost
database: mina_deploy_example
adapter: postgresql
encoding: unicode
username: postgres
password: 123
production:
secret_key_base: SECRET_KEY_BASE
Для того, чтобы не смотреть на то, как ваш bundler постоянно ругается на то, что у вас отсутствуют определенные зависимости, установите следующие гемы и библиотеки:
gem install bundler
apt-get install ruby-dev
gem install json -v '1.8.6'
gem install pg -v '0.20.0'
apt-get install postgresql postgresql-contrib libpq-dev
gem install uglifier
apt-get install nodejs
apt-get install imagemagick
Далее деплоим приложение и запускаем puma
mina deploy
mina puma:start
Прокидываем ssh тонель на порт nginx’a
sudo ssh -f -N -L 80:localhost:80 deployer@0.0.0.0 -p 2222
При переходе по адресу http://localhost:80 вы увидите надпись New article. Если все шаги выполнены верно, то при создании новых статей и добавлении изображений все будет корректно отображаться.
Поделиться с друзьями
Комментарии (6)
mtungusov
15.05.2017 20:21+1В моем понимании делать как написано в статье нельзя, так как не понятно зачем здесь докер.
По феншую нужно 3 контейнера:
- с нужной версией руби
- с нужной версией постгреса
- с нужной версией nginx-а
На основе контейнера с руби делается новый простым копированием исходников и приложение стартует через ENTRYPOINT.
Все 3 контейнера вместе запускаются через docker-compose на девелоперской машине.
Elfet
Вообще то cap использует пулл коннектов и не переподключается каждый раз, а использует уже доступный.
Какой смысл деплоить в контейнер? Лучше построить image. Похоже вы не разобрались с docker.
Рекомендую либо выбросить докер и остаться на мине/капистране. Либо выкинуть мину и разобраться в докере.
dmitriy-strukov
Спасибо за ваш отзыв, а вы точно правильно поняли суть руководства? Я использовал docker для имитации production окружения локально. Image кстати есть, https://hub.docker.com/r/dmitriystrukov2011/mina-deploy-tutorial/, если правильно понял вас.
staticlab
@Elfet имеет в виду, что деплоить в докер-контейнер с целью получения image нерационально. Гораздо лучше подготовить к деплою все файлы, а затем единомоментно скопировать их при помощи Dockerfile.
neumeika
внимание, у админов статья вызывает нервный смех и тик, в особенности, если используется какой-нибудь passenger и есть ассеты. Хотя хз, мож у кого прод без оного на пуме какой-нить, оно же с каждым годом всё асинхроннее_быстрее_выше_сильнее :)
Дмитрий, docker, как бы принято считать stateless, зачем вы так жестоко стереотипы ломаете? Отдельным слоем «принято» код добавлять, и чтобы версия image менялась ;)
llait
neumeika
Я думаю, что Дмитрий пытался с помощью докера симитировать удаленный сервер. Docker в статье заканчивается ровно там, где открывается ssh-порт. Со следующего шага этот Docker container уже ведет себя как «обыкновенный» сервер, в который Дмитрий, собственно, деплоит приложение.
В статье не идет речь о настройке Docker архитектуры для разворачивания Rails приложения.@dmitry-strukov думаю Вам стоит указать на это в начале вашей статьи.