首先需要了解一下,开发应用的四层环境
- 开发环境(Development)
这个环境可以是一个独立开发者使用,也可以是较少的几个人一起使用.这个环境中对
代码的任何改动都不会影响其他人,所以可以随便改. - 集成环境(Integration)
各个开发者开发的不同功能代码都会提交到这个环境进行整合,进行测试,以保证进入预发布环境没有问题.根据实际开发情况,集成环境和开发环境也可以使用同一个环境,具体会在下文的实践中介绍. - 预演环境(Staging)
预发布环境需要尽可能的和生产环境一样.连接测试数据库,这个环境也可作为演示和培训. - 生产环境(Production)
就是正式上线的环境了,项目可能部署在服务器集群上.
我实际使用的环境是:production/staging/testing/integration
- production:上线的正式环境(多服务器部署)
- staging:连接着正式数据库(多服务器部署,因为当时刚开始弄多服务器* 部署/负载/redis等,所以这个也是为了测试)
- testing:连接测试数据库
- integration:日常的开发环境,可以直接上传修改的文件到服务器.其他三个环境需要走部署流程.
如果你也打算像我一下用这四个环境时,记得这几个关键字最好也和我一样,因为我后来使用阿里云的RDC发现定义的几个关键字是这个,分别是日常环境:testing/预发环境:staging/生产环境:production.这在写同一个部署命令到不同环境的时候很有用.
正式开始
在阿里云RDC中创建项目之后,创建应用,分支选择自由模式.
创建应用的时候需要关联分支,会自动在master分支下给你创建好发布配置文件,名字是[应用名].release.如下:
# 请参考 https://help.aliyun.com/document_detail/59293.html 了解更多关于release文件的编写方式
# 构建源码语言类型
code.language=php7.0
# 应用部署脚本
deploy.appctl.path=deploy.sh
deploy.appctl.path=deploy.sh
是你源码中的部署脚本,详见在代码库中存储部署脚本.
我之前用RDC的时候还没这个东西,所以我项目release的配置都是:
# 构建源码语言类型
code.language=scripts
# 要部署到服务器上的文件,我在里面放了deployer脚本
build.output=deploy/
Screen Shot 2017-10-27 at 7.01.11 PM.png
然后配置应用的环境:
Screen Shot 2017-10-27 at 6.47.16 PM.png你需要配置的地方有:资源管理/部署策略/部署配置
资源管理:配置要部署的机器.我是日常环境配置一台.预发和正式配置多台.因为当时刚开始使用多服务器运行项目,我怕出问题,所以需要有一个给我测试多服务运行状态的环境.
部署策略:我都选的是分批发布不暂停
部署配置:
下载路径中的文件就是发布配置文件中设置的
build.output
参数.
这个RDC脚本部署执行起来的流程就是:
- 将源码中的
build.output
设置的文件打包传到服务器的下载路径
上 - 执行stop命令,我用它创建了部署文件的目录..很奇葩,因为当时还没有deploy.sh文件,我需要解压目录保证存在,不然部署会失败(我假设部署的是一台之后基本软件环境的新系统,没有创建该目录).我没写应该有的stop命令,因为我项目目前的情况用不到.
- 解压步骤1中的包到指定目录
如果你现在写配置话,建议把命令放在deploy.appctl.path=deploy.sh
,我没有改我之前的配置,因为RDC想在还经常升级迭代...我不着急弄...
配置流水线
我是develop分支对应一条流水线:对应环境日常环境和预发环境;
master分支对应一条流水线:对应正式环境
我的一个deploy.php,测试环境用的部署文件:
deployer
<?php
namespace Deployer;
require 'recipe/laravel.php';
use Symfony\Component\Console\Input\InputOption;
//dep -vv deploy --first true --branch develop -- test
option('first', null, InputOption::VALUE_OPTIONAL, 'If first deploy.');
// Configuration
set('repository', 'git@code.aliyun.com:mall-to/easy-admin.git');
set('allow_anonymous_stats', false);
set('default_timeout', 600);
localhost()
->stage('test')
->set("branch", "develop")
->set('deploy_path', '/app/back_end/easy_admin/test');
// Tasks
desc('first deploy');
task('deploy:first', function () {
if (input()->hasOption('first')) {
$first = input()->getOption('first');
if ($first) {
run('{{bin/php}} {{release_path}}/artisan tool:install');
run('{{bin/php}} {{release_path}}/artisan admin:install');
run('{{bin/php}} {{release_path}}/artisan user:install');
run('{{bin/php}} {{release_path}}/artisan mall:install');
run('{{bin/php}} {{release_path}}/artisan activity:install');
//生成的key需要各个地方一样
// run('{{bin/php}} {{release_path}}/artisan passport:install');
// run('{{bin/php}} {{release_path}}/artisan passport:keys');
run('{{bin/php}} {{release_path}}/artisan passport:client --personal');
}
}
});
desc('update');
task('deploy:update',function(){
run('yes|{{bin/php}} {{release_path}}/artisan tool:update');
run('yes|{{bin/php}} {{release_path}}/artisan admin:update');
run('yes|{{bin/php}} {{release_path}}/artisan user:update');
run('yes|{{bin/php}} {{release_path}}/artisan mall:update');
run('yes|{{bin/php}} {{release_path}}/artisan activity:update');
});
desc('copy env');
task('deploy:cp_env', 'cp .env.{{stage}} .env');
desc('copy composer');
task('deploy:cp_composer', 'cp composer.json.circle composer.json');
desc('Restart PHP-FPM service');
task('php-fpm:restart', function () {
// The user must have rights for restart service
// /etc/sudoers: username ALL=NOPASSWD:/bin/systemctl restart php-fpm.service
run('sudo systemctl restart php-fpm.service');
});
task("artisan:vendor", '
php artisan queue:restart;
');
after('deploy:symlink', 'php-fpm:restart');
after('deploy:update_code', 'deploy:cp_env');
after('deploy:update_code', 'deploy:cp_composer');
// [Optional] if deploy fails automatically unlock.
after('deploy:failed', 'deploy:unlock');
// first deploy run
after('artisan:vendor', 'deploy:first');
// plugin install
after('artisan:vendor', 'deploy:update');
// publish vendor
before('deploy:symlink', 'artisan:vendor');
// Migrate database before symlink new release.
before('deploy:symlink', 'artisan:migrate');
参考链接
deployer
阿里云RDC/云效
Traditional Development/Integration/Staging/Production Practice for Software Development
Amazon为何能做到持续交付
谈谈持续集成,持续交付,持续部署之间的区别
网友评论