主要參考 Test and deploy Laravel applications with GitLab CI/CD and Envoy ,因為這篇文章的順序跟說明都很容易讓人做到懷疑人生,所以本篇文章會稍微修改一下順序及內容,建議閱讀本文章的同時可以邊參考原文。
CI(Continuous integration)
: 持續整合 => 自動測試CD(Continuous Deployment)
: 持續部署 => 自動部署[TOC]
Laravel 專案建立後應該都會內建一兩個範例測試,可以透過指令查看這些測試結果。
php artisan test
結果:
PASS Tests\Unit\ExampleTest
✓ that true is true
PASS Tests\Feature\ExampleTest
✓ the application returns a successful response
Tests: 2 passed
Time: 0.83s
# 命令中的專案位置記得改成你的專案
cd laravel-sample
git init
git remote add origin git@gitlab.example.com:<USERNAME>/laravel-sample.git
git add .
git commit -m 'Initial Commit'
git push -u origin main
官方範例是使用 ACL 這個套件來管理權限,所以我們也裝一下。
sudo apt install acl
裝好後就建立使用者
# Create user deployer
sudo adduser deployer
# Give the read-write-execute permissions to deployer user for directory /var/www
sudo setfacl -R -m u:deployer:rwx /var/www
要先切換至這個使用者,並用 deployer
的身份建立 SSH Key
# 切換使用者
sudo su deployer
切換後就可以建立 Key 了,建立時⚠️記得不要設置密碼⚠️
ssh-keygen -t rsa -b 2048
之後使用指令將公鑰複製到 /authorized_keys
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
並複製 私鑰 並貼到 Gitlab Repo > Settings > CI/CD > Variables
# 顯示私鑰
cat ~/.ssh/id_rsa
同時也要將 公鑰 複製並貼到 Gitlab Repo > Settings > Repository > Deploy Key。頁面上的 Title 隨便填就好
# 顯示公鑰
cat ~/.ssh/id_rsa.pub
以上步驟完成後可以試著 clone 專案看看權限是否設置正常
# 命令中的專案位置記得改成你的專案
git clone git@gitlab.example.com:<USERNAME>/laravel-sample.
如果有顯示 Are you sure you want to continue connecting (yes/no)?
請輸入 yes
這一步要回來我們自己的電腦上面做。照著原文件的做法,會透過 Docker 來做。中間需要在自己機器上 build
過一次,所以本機也會需要安裝 Docker。
原文的版本比較舊,裡面提到的一些設置位置會跟現在 Gitlab 上看到的不同。包含原文說要先開權限,現在版本則預設就已經開好了。
*要部署的伺服器不需要裝 Docker。
原文件是使用 php 7.4 ,但我們專案為 Laravel 9 & php 8.0。有些舊版本套件在 php 8.0 已經無法使用,因此 Dockerfile 的內容會跟原文不同。
在專案根目錄建立 Dockerfile
檔案
# Set the base image for subsequent instructions
FROM php:8.0
# Update packages
RUN apt-get update
# Install PHP and composer dependencies
RUN apt-get install -qq git curl libmcrypt-dev libjpeg-dev libpng-dev libfreetype6-dev libbz2-dev libzip-dev
# Clear out the local repository of retrieved package files
RUN apt-get clean
# Install needed extensions
# Here you can install any other extension that you need during the test and deployment process
RUN docker-php-ext-install pdo_mysql zip
# Install Composer
RUN curl --silent --show-error "https://getcomposer.org/installer" | php -- --install-dir=/usr/local/bin --filename=composer
# Install Laravel Envoy
RUN composer global require "laravel/envoy" --dev
建立完成後需將 docker 登入至 GitLab registry,輸入完指令會需要輸入你的 Gitlab 帳號密碼。
docker login registry.gitlab.com
之後就能 build
、push
映像檔到 Gitlab 上
# 命令中的專案位置記得改成你的專案
docker build -t registry.gitlab.com/<USERNAME>/laravel-sample .
docker push registry.gitlab.com/<USERNAME>/laravel-sample
完成後可以到 Gitlab Repo > Package and registries > Container Registry 找到剛剛 push 上去的 image
在根目錄建立 .gitlab-ci.yml
,這是讓 gitlab 自動運行 CI/CD 的關鍵檔案。設定好後 gitlab 就會將這個檔案的指令丟給上面步驟做的 Docker 去做執行,一切的測試跟部署的調用都會透過 Docker。
與 php 版本一樣,這邊也因應現今版本做了稍微的修改。
image: registry.gitlab.com/<USERNAME>/laravel-sample:latest
services:
- mysql:latest
variables:
MYSQL_DATABASE: homestead
MYSQL_ROOT_PASSWORD: secret
DB_HOST: mysql
DB_USERNAME: root
stages:
- test
- deploy
unit_test:
stage: test
script:
- cp .env.example .env
- composer install
- php artisan key:generate
- php artisan migrate
- php artisan test
deploy_production:
stage: deploy
script:
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- eval $(ssh-agent -s)
- ssh-add <(echo "$SSH_PRIVATE_KEY")
- mkdir -p ~/.ssh
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
- ~/.composer/vendor/bin/envoy run deploy --commit="$CI_COMMIT_SHA"
environment:
name: production
url: https://example.com
when: manual
only:
- master
下面幾個小節將會把 .gitlab-ci.yml
中的區塊拆出來解說。
這裡的 SQL 變數是給 Docker 設定預設的資料庫名稱、及帳號密碼,所以這部分我們可以不用動它。
# .gitlab-ci.yml
variables:
MYSQL_DATABASE: homestead
MYSQL_ROOT_PASSWORD: secret
DB_HOST: mysql
DB_USERNAME: root
因為測試的指令會執行 cp .env.example .env
將範例的環境變數當成正式的環境變數來用。 所以要改的是我們的 .env.example
中的資料庫設定,只要改成跟上面一樣就可以了。
# .env.example
DB_CONNECTION=mysql
DB_HOST=0.0.0.0
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=root
DB_PASSWORD=secret
unit_test:
script:
# 安裝 composer 的套件
- composer install
# 設置 .env
- cp .env.example .env
# 產生 environment key
- php artisan key:generate
# 執行 migrations
- php artisan migrate
# 執行測試
- php artisan test
這邊的命令會透過 Envoy 去執行部署,關於 Envoy 的設定我寫在第五章。
因此這邊就看一下底下的 environment
、when
、only
分別的作用。
deploy_production:
...
environment:
name: production
url: http://192.168.1.1
when: manual
only:
- main
會顯示在部署完成後 gitlab 上的 Environments 頁面 中的按鈕,分別是按鈕的 名稱(name)
及按鈕的連結(url)
。
設定執行部署的時機, manual(手動)
。
設定是在哪個 branch 的 commit 推上來後才能夠執行。
調整完後就將這個檔案 commit 並 push 到 gitlab 上。
這個步驟先在自己的機器上做,之後再用 git 推到線上就好,之後會在 docker 內去跑這段程式並部署到你的機器上。
composer require laravel/envoy --dev
並在根目錄建立 Envoy.blade.php
:
@servers(['web' => 'deployer@192.168.1.1'])
@setup
$repository = 'git@gitlab.example.com:<USERNAME>/laravel-sample.git';
$releases_dir = '/var/www/app/releases';
$app_dir = '/var/www/app';
$release = date('YmdHis');
$new_release_dir = $releases_dir .'/'. $release;
@endsetup
...
記得修改裡面的內容,將 deployer@192.168.1.1
後面的 192.168.1.1
換成你要部署機器的 IP,因為前面有設定過使用者為 deployer
因此就不用改使用者名稱。
*如果要部署多台機器則將其他機器的資料加在後面就行,例如:
@servers([
'web' => 'deployer@192.168.1.1',
'web2' => 'deployer@192.168.1.2',
])
部署的檔案位置及資料夾可以自行調整即可。
如果沒修改的話,部署完後 /var/www/app
資料夾會有 releases
、storege
、current
三個資料夾,並會將 app/storege
及 app/.env
用 link 的方式連接到最新部署的專案資料夾內,並將最新部署的專案 link 到外面的 current
資料夾中。
注意:一開始沒有 storege
以及裡面的資料夾,需要在第一次自動部署前先手動建立,否則網頁打開找不到資料夾就會報錯。
mkdir storege/app
mkdir storage/framework/cache
mkdir storage/framework/sessions
mkdir storage/framework/views
mkdir storage/logs
@servers(['web' => 'deployer@192.168.1.1'])
@setup
$repository = 'git@gitlab.example.com:<USERNAME>/laravel-sample.git';
$releases_dir = '/var/www/app/releases';
$app_dir = '/var/www/app';
$release = date('YmdHis');
$new_release_dir = $releases_dir .'/'. $release;
@endsetup
@story('deploy')
clone_repository
run_composer
update_symlinks
@endstory
@task('clone_repository')
echo 'Cloning repository'
[ -d {{ $releases_dir }} ] || mkdir {{ $releases_dir }}
git clone --depth 1 {{ $repository }} {{ $new_release_dir }}
cd {{ $new_release_dir }}
git reset --hard {{ $commit }}
@endtask
@task('run_composer')
echo "Starting deployment ({{ $release }})"
cd {{ $new_release_dir }}
composer install --prefer-dist --no-scripts -q -o
@endtask
@task('update_symlinks')
echo "Linking storage directory"
rm -rf {{ $new_release_dir }}/storage
ln -nfs {{ $app_dir }}/storage {{ $new_release_dir }}/storage
echo 'Linking .env file'
ln -nfs {{ $app_dir }}/.env {{ $new_release_dir }}/.env
echo 'Linking current release'
ln -nfs {{ $new_release_dir }} {{ $app_dir }}/current
@endtask
如果有要新增執行的指令也可以自己寫在裡面,像是 npm install
或是 npm build
等等的。
再把 Envoy.blade.php
也 commit 上去後整個流程就完成了。
上面除了第二章建立使用者時會需要登入到你要部署的伺服器
其他都在自己的電腦就能完成。很多配置文件字很多看起來很雜,其實一行一行慢慢看還蠻容易讀懂的。