Deployer 使用攻略

ThinkQ發表於2024-01-27

   使用 Deployer 有很多年了,網上也有很多的使用教程,不過發現比較難找到一個完整且能跑通的文章,今天寫這的這篇教程是一個小白也能完整走通教程,當然了,難免也有失誤,歡迎同學在使用過程中反饋遇到的問題!

環境

系統:
➜  /etc cat /etc/redhat-release                         
Rocky Linux release 9.3 (Blue Onyx)# CentOS 替換方案,

# Rocky Linux:Rocky Linux: 一個開源、社群擁有和管理、免費的企業Linux發行版,提供強大的生產級平臺。可作為CentOS停止維護(改為滾動更新的Stream版)後,RHEL的下游Linux作業系統替代方案,並繼承了原CentOS的開源免費特點。 
#2020128日,CentOS釋出公告稱CentOS Linux系列將不再更新維護,CentOS 7生命週期將於2024630日終止。2020128日,CentOS釋出公告稱CentOS Linux系列將不再更新維護,CentOS 8生命週期將於20211231日終止。

PHP 版本:
➜  /etc php -v
PHP 8.3.2 (cli) (built: Jan 25 2024 14:58:00) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.3.2, Copyright (c) Zend Technologies

Nginx 版本:
➜  /etc nginx -v 
nginx version: nginx/1.24.0

MySQL 版本:
➜  /etc mysql -V
mysql  Ver 8.3.0 for Linux on x86_64 (MySQL Community Server - GPL)

   首先,我們先了解一下 Deployer 是什麼,Deployer 是一個使用 PHP 開發的基於 SSH 協議的無侵入具有模組化、程式碼回滾、並行任務的輕量級 web 專案部署工具,它不需要在你目標伺服器上裝服務之類的東西即可使用,它只需要在你的開發機發起部署動作的一方安裝即可。它的原理就是透過 SSH 登入到你的目標機器去建立目錄,移動檔案,執行指定的動作、然後執行指令碼中定義好的 Shell 命令、來完成專案的部署。同時 Deployer 內建了一批常見專案、框架的部署指令碼,例如 Laravel、WordPress 等等,當我們需要部署相關專案時,只需要調整一些引數就可以直接使用。

一、Deployer 安裝(在本地或開發機操作)

Deployer 安裝有多種方法:

第一種 透過 Phar 存檔,只需執行一下命令即可:
curl -LO https://deployer.org/deployer.phar
mv deployer.phar /usr/local/bin/dep
chmod +x /usr/local/bin/dep

第二種 透過 composer 安裝:
(1)專案級安裝:
composer require deployer/deployer --dev
使用:
php vendor/bin/dep
(2)全域性安裝(推薦)
composer global require deployer/deployer -vvv

第三種 透過 Github 原始碼安裝:

clone 最新的程式碼:
git clone https://github.com/deployphp/deployer.git
在原始碼目錄下執行:
php ./build
第三種方法會建立 deployer.phar 的 Phar 歸檔,建議使用第一種方法安裝或第二種方法

   無侵入的部署工具,但還是需要做一些基礎配置,出於安全考慮,我們不會開發 root 使用者的 SSH 登入,而是使用其它使用者,比如 Ubuntu 預設的 ubuntu 使用者。
這裡 Deployer 是用來部署 web 應用的,我們專門建立一個 deployer 使用者來執行工作。

# 新建使用者deployer
➜  /etc sudo adduser deployer
➜  /etc sudo passwd deployer
Changing password for user deployer.
New password:
BAD PASSWORD: The password is shorter than 8 characters
Retype new password:
passwd: all authentication tokens updated successfully.

   web 專案一般需要一些上傳檔案、快取寫入等操作,所以 deployer 還需要有許可權對目錄進行修改,比如 Laravel 的 storage 目錄需要可寫許可權,這裡以 nginx 預設的使用者組 nginx 舉例,如果你修改過使用者或者組名請對應修改下面的命令裡的 nginx 使用者組:

sudo usermod -aG nginx deployer
-a表示追加(append),G表示組(group),所以 -aG表示將使用者追加到指定的組。如果不使用 -a選項,使用者將從所有其他組中刪除,只保留在新指定的組。

   我們通常需要將 deployer 使用者許可權分別設定為建立檔案 644 與目錄 755,這樣一來,deployer 使用者可以讀寫,但是組與其它使用者只能讀:

/etc su deployer
[deployer@dyp etc]$ echo "umask 022" >> ~/.bashrc
[deployer@dyp etc]$ exit
exit
➜  /etc 

說明:
這條命令在Linux或UNIX系統中執行了以下操作:
echo: 這是一個常用的命令,用於在終端中輸出文字或變數的值。
"umask 022": 這是要輸出的文字內容。umask是一個特殊的許可權設定,它決定了新建立的檔案的預設許可權。022是一個八進位制數,對應的許可權是:
0: 特殊許可權(例如setuid、setgid、sticky bit)
2: 使用者可寫(使用者有w許可權)
2: 組可寫(組有w許可權)
0: 其他可寫(其他使用者沒有w許可權)這意味著新建立的檔案的預設許可權是644(rw-r--r--),而新建立的目錄的預設許可權是755(rwxr-xr-x)。
>>: 這是一個重定向運算子,它將命令的輸出附加到指定的檔案中,而不是覆蓋檔案的內容。如果檔案不存在,它會被建立。
~/.bashrc: 這是一個隱藏檔案,位於使用者的家目錄中。.bashrc檔案是bash shell的配置檔案之一,它在每次啟動新的bash例項時執行其中的命令。透過將umask的命令新增到.bashrc檔案中,你可以確保每次啟動新的bash例項時都會使用這個umask設定。
總的來說,這條命令將umask設定為022,並將這個設定新增到使用者的.bashrc檔案中,以確保新建立的檔案和目錄有適當的預設許可權。

我們需要將 depoloyer 使用者加到 sudoers 中:

vim /etc/sudoers
# 在最後加入
deployer ALL=(ALL) NOPASSWD: ALL
# 儲存並退出(x!)

說明:
deployer ALL=(ALL) NOPASSWD: ALL 是一個用於Linux系統的sudoers檔案中的條目,它定義了deployer使用者可以以其他使用者的身份執行命令,並且不需要輸入密碼。讓我們逐一解釋這個條目的各個部分:

deployer: 這是使用者名稱,即有權使用sudo命令的使用者。
ALL=(ALL): 這定義了deployer使用者可以以哪些使用者身份執行命令。在這裡,ALL表示deployer可以以系統上的任何使用者的身份執行命令。第一個ALL表示目標使用者,第二個ALL表示源使用者。
NOPASSWD:: 這表示在執行sudo命令時不需要輸入密碼。
ALL: 這表示deployer使用者可以執行的命令沒有限制。
因此,整個條目的意思是:deployer使用者可以以系統上的任何使用者的身份執行任何命令,而不需要輸入密碼。

這個條目通常出現在sudoers檔案中,該檔案定義了哪些使用者和組可以執行哪些命令,以及這些命令是否需要密碼。編輯sudoers檔案需要謹慎,因為不正確的配置可能會導致安全問題。如果你需要修改sudoers檔案,建議使用visudo命令,這是一個專門用於編輯sudoers檔案的文字編輯器,它可以幫助檢查語法錯誤。

   接下來要對我們的 web 根目錄授權,假設我們的 web 服務的根目錄在 /var/www/ 下,那麼需要將這個目錄的使用者設定為 deployer ,組設定為 nginx 使用者 nginx:

sudo chown deployer:nginx /var/www/ziyou-space # 最後這裡不要加斜線哦

說明:
這條命令 sudo chown deployer:nginx /var/www/ziyou-space 在Linux系統中執行了以下操作:

sudo: 允許普通使用者以超級使用者(通常是root)的許可權執行命令。
chown: 用於改變檔案或目錄的所有者和所屬組。
deployer:nginx: 指定新的所有者和所屬組。這裡,deployer 是使用者名稱,表示該檔案或目錄將屬於這個使用者。nginx 是組名,表示該檔案或目錄將屬於這個組。
/var/www/ziyou-space: 是要改變所有者和所屬組的檔案或目錄的路徑。
綜上所述,這條命令的意思是:“以超級使用者的許可權,將 /var/www/ziyou-space 的所有者更改為 deployer,並將其所屬組更改為 nginx。”這通常用於配置檔案或目錄的所有權,以便特定的使用者或服務可以訪問或修改它。

   OK,Deployer 的使用者操作到此結束,還需要檢查以下配置:
確認 php 的可執行檔案在全域性 PATH 中,或者手動新增到 deployer 使用者目錄的 .bash_profile PATH 中也可,使用命令確認(登入使用者 deployer 後執行):php -v,如果報錯的話,一般建議是將 php 的 bin 檔案軟連結到 /usr/local/bin/(推薦) 或者 /usr/bin/ 下。
同樣檢查你的 Deployer 任務清單所需要用到的其它命令,比如 npm,nginx,composer 都在 deployer 使用者下可以使用,否則在部署的時候會出錯。

/etc su deployer
[deployer@dyp etc]$ php -v
PHP 8.3.2 (cli) (built: Jan 25 2024 14:58:00) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.3.2, Copyright (c) Zend Technologies
[deployer@dyp etc]$ nginx -v
nginx version: nginx/1.24.0
[deployer@dyp etc]$ mysql -V
mysql  Ver 8.3.0 for Linux on x86_64 (MySQL Community Server - GPL)
[deployer@dyp etc]$ 

   我們 deployer 的執行機制是從 git 或者其它你指定的程式碼庫 clone 程式碼到目標伺服器,所以如果你的程式碼不是公開的倉庫,我們通常需要新增 SSH 公鑰才可以從程式碼庫 clone 程式碼,所以接著來建立公鑰:
先切換當前登入使用者到 deployer

su - deployer
sudo git config --global user.name 'ThinkCsly'
git config --global user.email 'thinkcsly@163.com'

$ ssh-keygen -t rsa -b 4096 -C "thinkcsly@163.com" 
# 這裡的 -C 是指定備註
# 一路回車下去即可

說明:
這條命令是在Linux或類Unix系統中使用ssh-keygen工具來生成一個新的SSH金鑰對。下面是對這條命令的詳細解釋:

ssh-keygen: 這是用於生成、管理和轉換認證金鑰的工具。SSH金鑰對通常用於無密碼登入到遠端伺服器。
-t rsa: 這指定了要生成的金鑰型別為RSARSA是最常見的SSH金鑰型別。
-b 4096: 這指定了金鑰的長度為4096位。較長的金鑰長度提供了更好的安全性,但也會增加加密和解密操作的計算成本。
-C "thinkcsly@163.com": 這指定了一個註釋或描述,通常是使用者的名字或與其相關的其他資訊。在這裡,註釋是"thinkcsly@163.com"。這個描述不是用於加密目的,而是為了幫助使用者記住或識別金鑰。
執行這條命令後,系統會要求你為私鑰設定一個密碼短語(passphrase)。私鑰用於解密公鑰,因此為了安全起見,最好為私鑰設定一個密碼短語。

執行完這條命令後,會在當前目錄下生成兩個檔案:id_rsa(私鑰)和id_rsa.pub(公鑰)。私鑰應該妥善保管,而公鑰可以安全地分享給任何你想要無密碼登入到的遠端伺服器。

[deployer@dyp etc]$ cat ~/.ssh/id_rsa.pub # 顯示公鑰

然後我們將生成的公鑰完整複製出來配置到程式碼倉庫,我這裡是碼雲(https://gitee.com):

可以自己驗證一下是否成功:

ssh -T git@gitee.com

注意:檢視OpenSSH版本:

[deployer@dyp www]$ ssh -V
OpenSSH_8.7p1, OpenSSL 3.0.7 1 Nov 2022
我這裡OpenSSH 版本是8.7;由於從OpenSSH 8.2 版本開始,客戶端預設禁用了ssh-rsa,OpenSSH 8.2 釋出,禁用 ssh-rsa 演算法。
為了解決這個問題,我們可以在本地開啟ssh-rsa的支援:
(1)手動在 .ssh/config 檔案里加上如下內容:
Host gitee.com
        PubKeyAcceptedKeyTypes=+ssh-rsa
(2)或者使用其他加密演算法, eg.ed25519
ssh-keygen -t ed25519 -C "thinkcsly@163.com"

如果 OpenSSH 是8.2+,不開啟ssh-rsa的支援的話會報下面錯誤:
[deployer@dyp www]$ sudo git clone git@gitee.com:ThinkCsly/ziyou-space.git
Cloning into 'ziyou-space'...
git@gitee.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

clone 程式碼測試:

Are you sure you want to continue connecting (yes/no/[fingerprint])?
說明:
在嘗試建立連線或訪問某個系統時。它詢問使用者是否確定要繼續進行連線,並提供了三種響應選項:

yes:表示使用者確定要繼續連線。
no:表示使用者不想繼續連線。
[fingerprint]:這可能意味著使用者可以透過提供某種指紋資訊(可能是數字指紋或其他身份驗證方法)來確認他們想要繼續連線。不過,這裡的[fingerprint]更像是一個佔位符,實際使用時可能會被具體的指紋資訊或操作所替代。
在實際應用中,這樣的提示通常用於確保使用者明確知道他們正在嘗試連線的系統或裝置,並作為一種安全措施來防止未經授權的訪問。如果使用者不確定連線的合法性或安全性,他們應該選擇no或尋求更多的資訊,而不是盲目地繼續連線。

此處,我們選擇yes即可。

   OK, 現在你的伺服器就可以從程式碼庫 clone 程式碼了,你可以在伺服器上 git clone 一下你的程式碼庫測試,如果不成功,請檢查你的公鑰是否正確完全的複製與貼上正確,不正確的話再次重複複製貼上即可,檢查OpenSSH 版本問題。

在本地(或者開發機)執行部署任務時我們不想每次輸入密碼,所以我們需要將 deployer 使用者設定 SSH 免密碼登入:

方式一:在本機生成 deployer 專用金鑰,然後複製公鑰:

ssh-keygen -t rsa -b 4096 -f  ~/.ssh/deployerkey

這個命令是用來生成一個新的SSH金鑰對。SSH金鑰對通常用於安全地訪問遠端伺服器,而不需要每次都輸入密碼。這裡詳細解釋一下命令的各個部分:
ssh-keygen: 這是用於生成、管理和轉換認證金鑰的工具。
-t rsa: 這指定了要生成的金鑰型別為RSARSA是最常見的SSH金鑰型別。
-b 4096: 這指定了金鑰的長度為4096位。較長的金鑰長度提供了更好的安全性,但也會增加加密和解密操作的計算成本。
-f ~/.ssh/deployerkey: 這指定了私鑰的儲存路徑和名稱。在這個例子中,私鑰將被儲存在使用者主目錄下的.ssh資料夾中,並命名為deployerkey。公鑰的預設名稱是deployerkey.pub,並且它也會被儲存在同一個目錄中。
執行這個命令後,系統會要求你為新生成的金鑰對設定一個密碼短語(passphrase)。這個密碼短語用於保護私鑰,防止未授權的訪問。當你使用私鑰進行SSH連線時,系統會要求你輸入這個密碼短語。

生成的公鑰可以用於配置遠端伺服器的SSH訪問,而私鑰則儲存在本地,用於建立安全的SSH連線。

然後將公鑰儲存到目標伺服器(注意,這一步還是在本機操作):

/SoftWare ssh-copy-id -i  ~/.ssh/deployerkey.pub deployer@47.95.xx.x  # 請填寫伺服器 IP
# 應該會讓你確認連線,然後再讓你輸入 deployer 在伺服器上的登入密碼,輸入後回車即可

然後你應該就可以直接以 deployer 使用者免密碼登入到伺服器了,測試方式:

/SoftWare ssh deployer@47.95.xxx.xx -i ~/.ssh/deployerkey
# 應該就能直接進到伺服器上了,然後 exit 退出

   OK,這一步搞定了 deployer 免密碼登入,接下來我們聊專案的部署。

方式二:在本機生成 deployer 專用金鑰,然後複製公鑰:

ssh-keygen -t rsa -b 4096 -f ~/.ssh/aliyun-47.95 -C "thinkcsly@163.com"
說明:其中,-t rsa表示選擇RSA演算法,-b 4096表示設定金鑰長度為4096位,-C後面的引數是註釋資訊,-f 表示生成的檔案路徑(通常位於~/.ssh/目錄下)與檔名稱,可根據自己的喜好修改。

配置 config:

vim ~/.ssh/config

說明:
Host <主機名>   # 將<主機名>替換為目標伺服器的IP地址或域名(根據情況命名)
    HostName <主機名>   # 同樣替換成目標伺服器的IP地址或域名
    User <使用者名稱>       # 替換成目標伺服器的使用者名稱
    IdentityFile ~/.ssh/id_rsa     # 指定私鑰檔案路徑,預設情況下為~/.ssh/id_rsa

將公鑰複製到目標伺服器的authorized_keys檔案中:

$ cat ~/.ssh/aliyun-47.95.pub | ssh deployer@47.95.xx.xx 'cat >> ~/.ssh/authorized_keys'

這裡的user是目標伺服器的使用者名稱,host是目標伺服器的IP地址或域名。

目標服務deployer使用者的authorized_keys在新增公鑰前後對比:

現在就可以直接使用ssh <主機名>命令來進行無需輸入密碼的SSH遠端連線了:

/SoftWare ssh aliyun_4795

Welcome to Alibaba Cloud Elastic Compute Service !

Last login: Sat Jan 27 14:07:47 2024
[deployer@dyp ~]$ exit
logout
Connection to 47.95.xxx.x closed./SoftWare 

五、Deployer 的使用(在本地操作)

假設我們的專案在本地 /var/www/ziyou-space 下,那麼我們切換到該目錄:

cd /var/www/ziyou-space
然後執行 Deployer 的初始化命令:

免密登入(一)

   在專案根目錄下會生成 deploy.php 檔案,這個檔案就是部署清單,說明 Deployer 怎樣去部署你的專案,這部分不需要過多的介紹,大家參考 Deployer 官網的詳細說明操作即可。
需要關心的幾個配置是:

 // 指定你的程式碼所在的伺服器 SSH 地址,請不要使用 https 方式哦。
set('repository', 'git@gitee.com:ThinkCsly/ziyou-space.git');
// 部署的分支
set('branch', 'master');
// 目標伺服器保留的版本數
set('keep_releases', 3);
// 目標伺服器的 IP 或者域名
host('your_server_ip') 
    ->user('deployer') // 這裡填寫 deployer 
      // 並指定公鑰的位置
    ->identityFile('~/.ssh/aliyun-47.95')
    // 指定專案部署到伺服器上的目錄
    ->set('deploy_path', '/var/www/zi-space'); 
    desc('Upload .env file');
task('env:upload', function() {
    // 將本地的 .env.staging 檔案上傳到程式碼目錄的 .env
    upload('.env.staging', '/var/www/ziyou-space/shared/.env');
});
// 定義一個後置鉤子,在 deploy:shared 之後執行 env:upload 任務
after('deploy:shared', 'env:upload');

免密登入(二)

在專案根目錄下會生成 deploy.php 檔案,配置如下:

<?php
namespace Deployer;

// 引入官方的 Laravel 部署指令碼
require 'recipe/laravel.php';

// 設定一個名為 application 的環境變數,值為 ziyou-space
set('application', 'ziyou-space');
// Config
// 設定一個名為 repository,值為初始化指令碼時輸入的 github 倉庫地址,初始為空,就手動新增即可,指定你的程式碼所在的伺服器 SSH 地址,請不要使用 https 方式
set('repository', 'git@gitee.com:ThinkCsly/ziyou-space.git');
set('branch', 'master');
set('keep_releases', 3);
// shared_files / shared_dirs 這兩個環境變數是陣列格式,add 函式可以往陣列裡新增值
add('shared_files', []);
add('shared_dirs', []);
// Deployer 會把這個變數下的目錄加上寫許可權
add('writable_dirs', []);

// 這裡填寫目標伺服器的 IP 或者域名(這裡填寫 .ssh/config 配置的 Host 名稱即可),可以同時部署到多個機器上,配置多個host即可。
host('aliyun_4795')
    ->set('deploy_path', '/var/www/ziyou-space');// 指定部署目
// Hosts

after('deploy:failed', 'deploy:unlock');
before('deploy:symlink', 'artisan:migrate');


// 定義一個上傳 .env 檔案的任務
desc('Upload .env file');
task('env:upload', function() {
    // 將本地的 .env 檔案上傳到程式碼目錄的 .env
    upload('.env.staging', '{{release_path}}/.env');
});

// 定義一個後置鉤子,在 deploy:shared 之後執行 env:upload 任務
after('deploy:shared', 'env:upload');

伺服器上刪除剛才 git 測試 clone 的程式碼:

[deployer@dyp www]$ cd /var/www/
[deployer@dyp www]$ rm -rf ziyou-space

在本地部署:

到伺服器檢視部署的程式碼:


我門上傳的.env.staging 檔案也 OK。

    .dep 為 Deployer 的一些版本資訊,不用去研究:

current - 它是指向一個具體的版本的軟連結,nginx 配置中 root 指向它,比如 zi-space 專案的, root 就指向:/var/www/zi-space/current/public
releases - 部署的歷史版本資料夾,裡面保留最近部署的版本,版本數在deplo.php中的keep_releases設定,保留多少個版本根據自己情況設定,建議 5 個。保留版本可以讓我們在上線出問題時使用 dep rollback 快速回滾專案到上一個版本。
shared - 共享資料夾,它的作用就是儲存我們專案中版本間共享的檔案,比如 Laravel 專案的 .env 檔案,storage 目錄,比如我們上傳的.env.staging檔案,它會以軟連結的形式連結到當前版本中。
到此為止基本完成了 Deployer部署; 過程中需要注意使用細節了,大部分的問題都出在許可權問題上。在建立使用者時,一定要仔細操作。

   個人用它已經五多年了, Deployer 非常好用,輕量方便,一條命令完成部署,回滾等操作,如果有碰到問題,可以去 GitHub 官方倉庫提 issue 或者搜尋相關問題解決方案。多看文件,很多時候遇到的問題其實都是沒仔細看使用文件造成的結果,同時歡迎大家隨時交流。

部分參考文章:部落格:又一篇 Deployer 的使用攻略

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章