search
尋找貓咪~QQ 地點 桃園市桃園區 Taoyuan , Taoyuan

如何用Docker實現PHP命令行程序的CI/CD

  • 使用Jet設置環境並在本地運行測試

  • 配置Codeship Pro每次新代碼提交時,自動運行測試

  • 上一步的測試通過後,自動將更新部署到伺服器

持續集成

應用程序和測試套件已經在本地運行,下一步要做的是建立一些持續集成系統。雖然可以設置伺服器來執行此操作,但這個過程工作量略大,因此推薦一個像Codeship Pro的服務。

  • 使用Jet進行本地測試

代碼提交到Codeship測試前,建議先安裝其本地版本的持續集成平台:Jet。這會更快地推進工作,下面示例配置文件中,需要根據應用的實際情況,做出相應調整。

安裝Jet后,在項目的根目錄中創建兩個新文件——

1)codeship-services.yml docker-compose.yml文件的變種,適用於Codeship

codeship-services.yml文件與 docker-compose.yml幾乎一樣。內容如下:

version: "2.0"

services:

# PHP Application

app:

build: .

links:

- database

encrypted_env_file: .env.encrypted

command: cron -f

# Database

database:

image: mariadb

# Composer

composer:

image: composer/composer

volumes:

- ./:/app

codeship-steps.yml內容如下,這個文件在例子里很簡單,按順序執行這些的命令(一個接一個地)就好。如果應用程序允許,也可以並列地跑某幾個步驟:

-

為了確保應用程序容器和資料庫容器已啟動,可以看到codeship-steps.yml文件調用了一個尚未創建的shell腳本。若資料庫遷移,說明測試通過。把腳本放在./docker/codeship-run.sh,內容如下:

#!/usr/bin/env bash ## Ensure that the database is up and running mysqladmin -h"$DB_HOST"-u"$DB_USERNAME"-p"$DB_PASSWORD"ping} untildo ((count++)) ## This will check up to 100 times. if[${count}-gt 100] then echo"Services didn't become ready in time" exit1 fi ## And the script waits one second between each try sleep1done ## Create the databasemysql -h"$DB_HOST"-u"$DB_USERNAME"-p"$DB_PASSWORD"-e 'CREATE DATABASE IF NOT EXISTS laravel' ## Run migrations/bin/

首先,該腳本會嘗試連接到資料庫。Codeship軟體會自動啟動應用程序容器和資料庫容器,但MySQL初始化需要幾秒,所以必須重試該test_database功能,直到成功連接資料庫(或嘗試100次)。這在Codeship的Docker文檔中有更詳細的概述。

一旦腳本能連接到資料庫,它將創建默認資料庫(資料庫名為laravel)。然後會運行遷移,通過PHPUnit創建資料庫表和測試套件。

最後,為了測試配置正常運行和且結果通過,用Jet來運行所有步驟:

{ContainerRunStdout=step_name:"serial_bash_docker/codeship-run.sh" PHPUnit 5.7.19 by Sebastian Bergmann and contributors.{=step_name:"app"}:.1/1(100%) Time:1.09 seconds Memory:12.00MB OK (1test,1 assertion{StepFinished=step_name:"serial_bash_docker/codeship-run.sh"type:STEP_FINISHED_TYPE_SUCCESS}$
  • 將倉庫連接到Codeship

如果尚未提交本地代碼到GitHub或Bitbucket上。每次提交代碼更改時,Codeship都自動會從私有或公共倉庫中拉取代碼,所以只需要設置Codeship去監視那個倉庫。

在Codeship中創建一個新項目,並將其連接到倉庫:

跳出提示框時,選擇Codeship Pro做為項目類型。

現在項目已經鏈接到Codeship。下次提交代碼時,Codeship將會編譯且使用與本地相同的codeship-steps.yml來運行。此時唯一的問題是使用本地的 .env文件,此文件不會提交到代碼倉庫,不過有個簡單方法來設置環境變數且又不會影響安全性。

  • 加密環境變數

因為最好的做法是不要將.env文件推送到持續集成伺服器,所以需要提出一種安全地將變數傳遞給Codeship方法——加密.env文件

首先,在Codeship找到AES密鑰(通常位於項目設置的常規頁面中),並將其放在一個名為codeship.aes的本地根目錄文件中。不要忘記將此文件添加到.gitignore,因為它是不應共享的密鑰:

下一步,更新codeship-services.yml文件,讓其使用加密的.env文件,而非明文.env文件

# PHP Application . cron -f - .//app

使用Jet將.env文件加密成.env.encrypted,將加密后的.env.encrypted文件提交到軟體倉庫,然後將其推送到遠程倉庫:

.env.env.$ git add -A &&git commit -am "Adding codeship config"$ git

Codeship正在編譯代碼:

也可以點擊進去,查看編譯詳細過程和每個步驟:

如果上述都無誤地執行,最後會看到一個成功的編譯結果:

自動部署

雖然持續集成服務會讓人知道編譯和測試是否通過,但使用Codeship更大的價值在於自動化部署過程,為了做到這一點,需要做幾件事情:

  • 在伺服器上手動配置和部署代碼庫

  • 伺服器上有一個SSH密鑰,允許從代碼庫拉取代碼

  • 伺服器上有一個腳本,用來更新代碼並重新啟動容器

準備齊全后,就可以構建一個部署者容器,其工作就是在編譯過程結束后,登陸到SSH伺服器中,運行更新腳本。

這只是利用容器來部署代碼的一種方法,也許並不是最佳的方法。另一個選擇是使用Docker Hub等容器倉庫來編譯,然後直接從Docker Hub那裡更新容器。Docker在生產中的最佳做法仍在探索中,這種方法更適用也相對簡單。

  • 首次手動部署代碼

此步驟根據主機服務提供商而有所不同,但只要伺服器滿足安裝了Git,Docker和Docker Compose就可以。SSH登陸伺服器:

  • 創建一個新的SSH密鑰

  • 賦予SSH密鑰可以從代碼庫讀取訪問

  • 克隆代碼庫

  • 設置.env文件,使用一個新的APP_KEY和資料庫密碼

  • 使用docker-compose up -d –build 命令來製作鏡像,並且運行容器

現在可以運行docker ps查看,當第一次在本地配置好這個項目時,可以看到同樣的兩個容器在運行。

  • 添加腳本更新伺服器代碼

現在在本地版本的代碼中,添加一個shell腳本,該腳本將從倉庫中獲取更新的代碼,並重啟容器:

git pull origin master ## Rebuild the containerscompose up -d --build docker exec dockerphpcliexample_app_1 php artisan migrate --force

此時,要確保文件位於伺服器上,因此提交代碼到代碼庫,又將其從伺服器中拉出。通過在伺服器上運行命令: $ bash docker/deploy.sh ,並確保容器仍然工作。

  • 創建一個部署者容器

綜上所述,在編譯和測試結束后,現在需要一個容器在Codeship的CI伺服器遠程運行此部署腳本。在倉庫中創建一個名為deployer/ 的新目錄,裡面包含 Dockerfile文件,.env文件和execute.sh文件。

Dockerfile:

latest # Install opensshRUN apk update && apk add openssh # Prep for the ssh keyRUN mkdir-p "$HOME/.ssh"RUN touch$HOME/.ssh/id_rsaRUN chmod600$HOME/.ssh/id_rsa # Add the shell scriptCOPY executesh execute.sh CMD sh execute.shPRIVATE_SSH_KEY=<SSH_KEY (with linebreaks replaced with `\n`)>echo-e $PRIVATE_SSH_KEY>>$HOME/.ssh/ssh--oStrictHostKeyChecking=no $USER@$HOST"cd docker-php-cli-example && sh docker/deploy.sh"

這個容器將使用.env文件中的環境變數,SSH登陸到伺服器運行部署腳本。

  • 讓Codeship Pro運行部署者容器

為了讓Codeship知道部署者容器,把它添加到codeship-services.yml文件中:

$ jet encrypt deployer/.env deployer/.env.

最後,把更新的代碼推到github倉庫,確保Codeship成功地編譯和部署了代碼:

原文地址:

本文轉載自數人云ID:dmesos

高端私有雲項目交流群,歡迎加入!

加入最活躍的kubernetes技術討論QQ群502207183,並註明城市、行業、技術方向。



熱門推薦

本文由 yidianzixun 提供 原文連結

寵物協尋 相信 終究能找到回家的路
寫了7763篇文章,獲得2次喜歡
留言回覆
回覆
精彩推薦