Mina - RoR快速的自动化部署工具

Contents
  1. 建立一个project
  2. 关于deploy.rb
  3. 命令队列(the command queue)
  4. 子任务(Subtasks)
  5. 部署(Deploying)
  6. Deploying是怎么工作的?

Mina是一个让你通过ssh来运行脚本,管理你的app部署的自动化工具。

Mina之所以高效,是因为它是Bash脚本部署generator,它生成一个完整的Bash程序,并且在远程服务器运行。


建立一个project


1、创建config/deploy.rb文件

1
2
$ mina init
Created config/deploy.rb.

你可以看一下什么是 deploy.rb, 按照下面的方法简单配置一下你的服务器:

1
2
3
4
5
# config/deploy.rb
set :user, 'username'
set :domain, 'your.server.com'
set :deploy_to, '/var/www/flipstack.com'
...

2、设置你的服务器

在服务器上创建目录 /var/www/flipstack.com

1
2
3
4
5
# Once in your server, create the deploy folder:
[email protected]$ mkdir /var/www/flipstack.com
[email protected]$ chown -R username /var/www/flipstack.com

3、运行 mina setup

Mina会自动通过ssh连接服务器并创建目录。关于folder structure

1
2
$ mina setup
-----> Creating folders... done.

4、部署服务器

运行 mina deploy,来部署在config/deploy.rb 中定义的task。

1
2
3
4
5
6
$ mina deploy
-----> Deploying to 2012-06-12-040248
...
Lots of things happening...
...
-----> Done.

关于deploy.rb


deploy.rb文件是一个简单的被Rake调用的Rakefile,事实上,mina就是通过Rake加载deploy.rb的一个alias。

1
2
3
4
5
6
# Sample config/deploy.rb
set :domain, 'your.server.com'
task :restart do
queue 'sudo service restart apache'
end

在这里你可以定义你想通过mina调用的tasks,在上面的例子中,我们定义了mina restart这个命令。

而mina的魅力就在于你自己定义的一系列新命令。

queue命令排列了你想在远端服务器上运行的Bash command,如果你运行了mina restart,它就会调用上面定义的task,并通过ssh在远端的服务器上执行队列中的command。

关于command queue

命令队列(the command queue)


作为核心,Mina仅仅是在Rake上方加上了命令队列,并且在最后执行这个队列。我们来看一个deploy.rb 的配置:

1
2
3
4
5
6
7
8
# config/deploy.rb
set :user, 'john'
set :domain, 'flipstack.com'
task :logs do
queue 'echo "Contents of the log file are as follows:"'
queue "tail -f /var/log/apache.log"
end

一旦在终端下运行mina logs,就会通过ssh [email protected]在远程服务器上执行队列中的命令了。

1
2
3
4
5
6
$ mina logs --simulate
# Execute the following commands via
#
echo "Contents of the log file are as follows:"
tail -f /var/log/apache.log

子任务(Subtasks)


Mina提供了invoke的帮助方法,可以让你在一个task中调用其他的tasks。

1
2
3
4
5
6
7
8
9
10
11
12
13
# config/deploy.rb
task :down do
invoke :maintenance_on
invoke :restart
end
task :maintenance_on
queue 'touch maintenance.txt'
end
task :restart
queue 'sudo service restart apache'
end

在上面的例子中,如果你运行了mina down,将会调用其他子任务中的队列命令,这些命令将会被最后执行。

部署(Deploying)


Mina提供了deploy这个命令来调用一段部署脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# config/deploy.rb
set :domain, 'flipstack.com'
set :user, 'flipstack'
set :deploy_to, '/var/www/flipstack.com'
set :repository, 'http://github.com/flipstack/flipstack.git'
task :deploy do
deploy do
# Put things that prepare the empty release folder here.
# Commands queued here will be run on a new release directory.
invoke :'git:clone'
invoke :'bundle:install'
# These are instructions to start the app after it's been prepared.
to :launch do
queue 'touch tmp/restart.txt'
end
# This optional block defines how a broken release should be cleaned up.
to :clean do
queue 'log "failed deployment"'
end
end
end

工作原理:通过捕获deploy块内的queue命令。

Deploying是怎么工作的?

下面是一个deploy的示例:

Step 1: Build it

Deploy进程会通过你提供的参数新建一个临时的文件夹。在这个例子中,会运行git:clonebundle:install

1
2
3
4
5
6
7
8
9
10
11
12
$ mina deploy --verbose
-----> Creating the build path
$ mkdir tmp/build-128293482394
-----> Cloning the Git repository
$ git clone https://github.com/flipstack/flipstack.git . -n --recursive
Cloning... done.
-----> Installing gem dependencies using Bundler
$ bundle install --without development:test
Using i18n (0.6.0)
Using multi_json (1.0.4)
...
Your bundle is complete! It was installed to ./vendor/bundle

Step 2: Move it to releases

一旦project被创建,它会被移动到releases/,并且将会创建一个名为current/来指向活动的release。

1
2
3
4
5
$
-----> Moving to releases/4
$ mv "./tmp/build-128293482394" "releases/4"
-----> Symlinking to current
$ ln -nfs releases/4 current

Step 3: Launch it

调用在to :launch块中的命令,这些命令通常用来重启webserver的进程。一旦这个步骤完成,部署就成功了!

1
2
3
4
5
$
-----> Launching
$ cd releases/4
$ sudo service nginx restart
-----> Done. Deployed v4

失败了怎么办?

如果在任意一个步骤失败了,release的路径就会被删除。在to :clean代码块中定义的命令就会被执行,看起来什么都没有发生过。我们来看一下部署失败会发生什么事。

1
2
3
4
5
6
7
8
9
10
11
$
-----> Launching
$ cd releases/4
$ sudo service nginx restart
Starting nginx... error: can't start service
-----> ERROR: Deploy failed.
-----> Cleaning up build
$ rm -rf tmp/build-128293482394
-----> Unlinking current
$ ln -nfs releases/3 current
OK