如何搭配 CI 系統使用 Composer

本文使用「署名 4.0 國際 (CC BY 4.0)」許可協議,歡迎轉載、或從新修改使用,但須要註明來源。 署名 4.0 國際 (CC BY 4.0)html

本文做者: 蘇洋前端

建立時間: 2019年08月24日 統計字數: 5361字 閱讀時間: 11分鐘閱讀 本文連接: soulteary.com/2019/08/24/…git


如何搭配 CI 系統使用 Composer

上一篇文章講了如何搭建高性能的 Composer 服務,本篇來聊聊如何搭配 CI 進行使用,讓研發效率有必定的保障。docker

寫在前面

本文以 GitLab Runner 中最簡單通用的 shell模式爲例,其餘 CI 系統相似,酌情修改腳本便可。考慮到持續集成過程當中須要進行資源隔離,咱們使用工具容器做爲持續集成環境。shell

定義階段

在使用 CI 前,咱們須要先拆分階段,通常來講,基於 Composer 的項目存在三個階段:編程

  • 更新代碼:composer install 階段
  • 部署代碼:sync release 階段
  • 重啓服務:reload/restart service 階段

若是寫成 yml 配置,能夠這樣描述:json

stages:
  - update
  - deploy
  - restart
複製代碼

定義完畢階段後,須要詳細描述每階段作的事情。ubuntu

先從 update 階段開始提及。api

更新代碼

爲了方便描述,項目結構簡單定義爲下面這樣。緩存

.
├── composer.lock
└── composer.json
複製代碼

更新代碼最簡單的方案即是進入項目目錄,執行 composer i ,等待項目安裝完畢了。然而這樣會致使兩個問題:

  • CI 構建機須要安裝並維護 composer,構建機器越多,管理成本越高
  • 不一樣項目必須使用同一份配置,構建機的緩存不可以獨立管理

因此若是使用固定配置構建的工具鏡像,搭配「即用即丟」模式來用作構建執行環境,上面的問題就迎刃而解了。

docker run \
	--add-host composer.lab.com:192.168.123.234 \
	--volume $PWD:/app \
	composer /bin/sh -c "composer install && ls -al vendor"
複製代碼

使用上面的方案,搭配 部署令牌 ,除了解決常規依賴的獲取外,也不難解決下面這種類型的軟件包的獲取。

"repositories": [
    {
      "type": "vcs",
      "url": "https://gitlab+deploy-token-2:ZeYhk_F7oqtdxXuKsvvr@gitlab.lab.com/forum/session.git"
    },
    ...
]
複製代碼

一切彷佛很美好,可是若是涉及到下面這類倉庫,上面的方案就失靈了。

"repositories": [
    {
      "type": "vcs",
      "url": "ssh://git@gitlab.lab.com/forum/session.git"
    },
    ...
]
複製代碼

使用 Git 獲取 SSH 協議的倉庫數據,須要配置 SSH KEY。解決的方案也不難,爲上面的 docker 命令加一些額外的參數:

docker run \
	--add-host composer.lab.com:192.168.123.234 \
	--volume $PWD:/app \
	--volume /etc/passwd:/etc/passwd:ro \
	--volume /etc/group:/etc/group:ro \
	--user $(id -u):$(id -g) \
	composer /bin/sh -c "composer install && ls -al vendor"
複製代碼

爲了追求簡單優雅,咱們能夠將上面的代碼進一步優化,改成用 docker-compose ,像是下面這樣。

version: '3.6'

services:

  composer:
    image: composer
    volumes:
      - ./:/app
      - ./known_hosts:/root/.ssh/known_hosts
      - $HOME/.ssh/id_rsa:/root/.ssh/id_rsa
    command: install
複製代碼

你會發現這裏多映射了一個 known_hosts 文件。因爲 SSH 設計上防止中間人攻擊,須要驗證服務端的指紋,因此,咱們須要將服務端指紋保存下來,不然當 composer 容器訪問代碼倉庫服務器的時候,會由於下面的錯誤而停止倉庫 Clone 。

Could not open a connection to your authentication agent.
複製代碼

這裏經過 ssh-keyscan 來生成簽名文件:ssh-keyscan gitlab.lab.com > known_hosts ,文件內容會相似下面:

ssh-keyscan gitlab.lab.com
# gitlab.lab.com:22 SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.8
gitlab.lab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCyC3qB2M68KeK79op1vdoYYbX+Y3G768DVV+nki0ujUSHsedCo77sfkTIU4ZHAojEn4w/oqAjDcz3bDJNEI/CIO3k1NeiM3tZbkzm8VKTGhXkvxbTYkAud3f/UbXij3LAhsskn8ykoxgl7qqQ4dH2y0v9oBARNh2fRNyENaj4Tvu3Ao8MIh4JWD69u3AcNvQwJWtqphkY7xbvFDb2GNzNrTW+X1R2jHsqCxq8Nuq6tCC9m+JNGtUR6IsZusm5B2/CtamxUSk+1YEtNsWxEJ2qikm7Ud+Ikkak9N+8xZ/Ck6lmjoAxlKwgoP7Tq6cDDfZrQt8drwLE1/j1hzrE7TfoR
# gitlab.lab.com:22 SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.8
gitlab.lab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFzJ/O/QQQ0RsEBALP/UeiZa58IDpI+c4RRjS9Vd1nMFY//xFuS1UF6ml8mpRpaYwSjxgQG9lNbXlL9E9AoAslo=
# gitlab.lab.com:22 SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.8
gitlab.lab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGkm3tji72xkD5ySTJo6NIeaE/zqhedlgkw5Y59quy6X
複製代碼

使用 compose 來描述內容,最後的 CI 腳本能夠簡化爲:

更新代碼:
  stage: update
  script:
    - docker-compose up && ls -al
    - chown -R $(id -u):$(id -g) ./vendor
複製代碼

部署代碼

部署代碼能夠作的簡單些,好比直接用 rsync ,能夠開啓 - I 選項保證一致性,或者老老實實 ansible ,若是追求一步到位,把代碼打包鏡像分發也沒有問題。先以 rsync 爲例,ansible 足夠再寫一篇啦。

生成一枚 SSH 密鑰用於部署,而後項目倉庫/代碼主機中配置信任該密鑰,rsync 使用的話,手段就靈活多了:

  • 使用 CI 變量儲存 / 使用配置服務API獲取
  • 預先分配 KEY 到 CI 程序用戶 .ssh 目錄中

和上面同樣一樣考慮將工具打包爲鏡像使用:

FROM alpine:3.9

RUN echo '' > /etc/apk/repositories && \
    echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.9/main"         >> /etc/apk/repositories && \
    echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.9/community"    >> /etc/apk/repositories && \
    echo "Asia/Shanghai" > /etc/timezone

RUN apk update && \
    apk upgrade && \
    apk add --no-cache rsync openssh-client && \
    rm -rf /var/cache/apk/*
複製代碼

上面的 Dockerfile 演示瞭如何構建一個徹底獨立於系統,大小隻有 10MB 的 Rsync 工具包。

使用命令也很簡單,和傳統的 Rsync 別無二致,只是前面加上了 docker run 命令:

docker run \
	--volume $DEPLOY_DIR/ssh.key:/ssh.key \
	--volume $PWD:/app \
	$RSYNC_TOOL rsync -az --list-only --include='vendor' --exclude='.git*' --timeout=3600 -P --partial --delete -e 'ssh -i /ssh.key -p 22 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' /app/ $DEPLOY_TARGET_01:$PROJECT_WORKDIR
複製代碼

一樣的,若是你願意的話,這個命令也能夠重寫爲更優雅一些的 compose 腳本。

此外,若是你想部署多臺服務器,想將上一步的「過程產物」共享,須要定義緩存目錄,本例中能夠這樣配置:

cache:
  paths:
    - vendor
複製代碼

重啓服務

重啓/重載服務其實沒有什麼難的,若是業務須要平滑重啓,能夠將腳本配置成串行任務:

  • 重啓服務第一批
  • 重啓服務第二批

前端不管是 Nginx 仍是負載均衡服務,會根據服務可用狀況幫助你平滑更新線上應用。

此外,若是你的服務部署更新後,須要觸發其餘項目的構建過程,可使用 GitLab API:pipeline trigger,調用手段不少,最簡單的莫過於使用 curl 進行調用,放在當前項目 CI 腳本的合適位置便可:

curl -X POST -F token=$DEP_PROJECT_TOKEN -F ref=$DEP_PROJECT_REF_NAME https://gitlab.lab.com/api/v4/projects/$DEP_PROJECT_ID/trigger/pipeline
複製代碼

上面的變量能夠在 GitLab CI 幫助文檔和項目配置中得到,在此就不贅述了。

最後

這裏給出一套簡單的參考配置,裏面演示瞭如何使用不一樣的命令來進行項目部署:

variables:
  RSYNC_TOOL:           "docker.lab.com/rsync-tool:1.0.0"
  CACHE_DIR:            "/data/caches/$CI_PROJECT_ID"
  SOURCE_DIR:           $CI_PROJECT_DIR
  PROJECT_WORKDIR:      /data/forum/$CI_PROJECT_NAME
  DEPLOY_TARGET_01:     $DEPLOY_HOST_01
  DEP_PROJECT_TOKEN:    cb0550eeaa6c6a696e6ada8b041234
  DEP_PROJECT_REF_NAME: master
  DEP_PROJECT_ID:       11

stages:
  - update
  - deploy
  - restart

cache:
  paths:
    - vendor

下載依賴:
  stage: update
  script:
    - docker-compose up && ls -al
    - chown -R $(id -u):$(id -g) ./vendor

分發依賴01:
  stage: deploy
  before_script:
    - DEPLOY_DIR=$CACHE_DIR && mkdir -p $DEPLOY_DIR && echo "$DEPLOY_KEY" | tr -d '\r' >$DEPLOY_DIR/ssh.key && chmod 600 $DEPLOY_DIR/ssh.key
  script:
    - docker run --volume $DEPLOY_DIR/ssh.key:/ssh.key --volume $PWD:/app $RSYNC_TOOL rsync -azi --list-only --include='vendor' --exclude='.git*' --timeout=3600 -P --partial --delete -e 'ssh -i /ssh.key -p 22 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' /app/ $DEPLOY_TARGET_01:$PROJECT_WORKDIR

重啓服務:
  stage: restart
  script:
    - "curl -X POST -F token=$DEP_PROJECT_TOKEN -F ref=$DEP_PROJECT_REF_NAME https://gitlab.lab.com/api/v4/projects/$DEP_PROJECT_ID/trigger/pipeline"
複製代碼

先寫到這裏吧。

—EOF


我如今有一個小小的折騰羣,裏面彙集了一些喜歡折騰的小夥伴。

在不發廣告的狀況下,咱們在裏面會一塊兒聊聊軟件、HomeLab、編程上的一些問題,也會在羣裏不按期的分享一些技術沙龍的資料。

喜歡折騰的小夥伴歡迎掃碼添加好友。(請註明來源和目的,不然不會經過審覈)

關於折騰羣入羣的那些事

相關文章
相關標籤/搜索