iT邦幫忙

2023 iThome 鐵人賽

DAY 4
2

今天在開始之前,要先說到了開發上最容易遇到的問題,就是你的 git 的遊戲規則是  git flowgithub flow 還是 gitlab flow

我覺得這個問題不難,就是越簡單越好,因為 YAGNI (You aren't gonna need it)

因為連 gitlab 也開始拋棄了固定的 gitlab flow 策略,轉向更通用且彈性的策略上。

所以在這個專案中,借鑑於 GitOps 的一些概念,在這邊所採取的策略是:

  • 分支會有: maindevelopPR 產生的分支
    • develop: 使用上如一般的 Staging 環境一樣,是比照 production 的測試區
    • main: production 的分支
    • 開發中的內容都會在 PR 的分支內,合併至 develop 的 PR 都
  • 假如有需要 Hotfix 的情況時,不另外特別處理,直接快速將 PR 推出與合併至 main

git flowchart

所以從上面的規劃來看,我們會需要有兩個線上環境,跟一個本地開發環境。
為了簡化有可能遇到的非預期的環境問題,所以採用的是盡量全部環境容器化,把環境的因素都統一。

製作 Dockerfile

Dockerfile.base:這邊會把 container image 分為兩個部分,base 是預先將環境的依賴先安裝好,再來針對不同環境的去調整。

FROM php:8.2-cli-buster

ENV COMPOSER_ALLOW_SUPERUSER=1

#
#-----------------------------------------------
# Basic Dependency
#-----------------------------------------------
#
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        libz-dev \
        libpq-dev \
        libjpeg-dev \
        libpng-dev \
        libfreetype6-dev \
        libssl-dev \
        libmcrypt-dev \
        libmagickwand-dev \
        libxml2-dev \
        libzip-dev \
        unzip \
        && rm -r /var/lib/apt/lists/*

#
#-----------------------------------------------
# PHP Extension
#-----------------------------------------------
#
RUN docker-php-ext-install soap exif pcntl zip pdo_pgsql bcmath sockets

RUN MAKEFLAGS="-j $(nproc)" pecl install  -o -f grpc && docker-php-ext-enable grpc

RUN usermod -u 1000 www-data && groupmod -g 1000 www-data

Dockerfile.api: 這邊僅有留下 deployment 所需的步驟

FROM asia.gcr.io/readcast-2023/api-base-image:latest

#
#-----------------------------------------------
# Final Touch
#-----------------------------------------------
#
ADD .deploy/php/app.ini /usr/local/etc/php/conf.d

RUN usermod -u 1000 www-data && groupmod -g 1000 www-data

COPY . /var/www/
WORKDIR /var/www

RUN ./vendor/bin/rr get-binary

#
#-----------------------------------------------
# Optimize for production
#-----------------------------------------------
#
RUN php artisan route:cache && php artisan config:cache

VOLUME ["/var/www"]

CMD /bin/bash -c 'php artisan octane:start --server=roadrunner --host=0.0.0.0 --port=8080 --rr-config=.rr.yaml --workers=4'

製作 Cloud Build yaml

cloudbuild-baseimage.yaml:這個主要是針對 Dockerfile.base 的 pipeline 設定

steps:
  # build image
  - name: 'gcr.io/cloud-builders/docker'
    args:
      - 'build'
      - '-t'
      - '${_IMG_REPO}/$PROJECT_ID/${_APP_NAME}:$BUILD_ID'
      - '-t'
      - '${_IMG_REPO}/$PROJECT_ID/${_APP_NAME}:latest'
      - '-f'
      - "${_DOCKERFILE}"
      - '.'

  # push image
  - name: 'gcr.io/cloud-builders/docker'
    args: ["push", "${_IMG_REPO}/$PROJECT_ID/${_APP_NAME}:$BUILD_ID"]

  # push image for latest
  - name: 'gcr.io/cloud-builders/docker'
    args: ["push", "${_IMG_REPO}/$PROJECT_ID/${_APP_NAME}:latest"]

timeout: 3600s
options:
  machineType: 'E2_HIGHCPU_8'

images:
  - ${_IMG_REPO}/$PROJECT_ID/${_APP_NAME}:latest
  - ${_IMG_REPO}/$PROJECT_ID/${_APP_NAME}:$BUILD_ID

substitutions:
  _IMG_REPO: 'asia.gcr.io'
  _APP_NAME: 'api-base-image'
  _DOCKERFILE: '.deploy/Dockerfile.api'

cloudbuild-baseimage.yaml:這個主要是針對 Dockerfile.api 的 pipeline 設定,會 deploy 至 cloud run

steps:
  # get env from secret manager
  - name: 'gcr.io/cloud-builders/gcloud'
    entrypoint: 'bash'
    args:
      - '-c'
      - |
        gcloud beta secrets versions access latest --secret="${_PHP_DOT_ENV}" > ./${_ENV_FILE}

  - name: 'composer:2'
    entrypoint: 'bash'
    args:
      - '-c'
      - |
        composer install --optimize-autoloader --ignore-platform-reqs --no-scripts --no-dev
        composer dump-autoload

  # build container image
  - name: 'gcr.io/cloud-builders/docker'
    args:
      - 'build'
      - '-t'
      - '${_IMG_REPO}/$PROJECT_ID/${_APP_NAME}:$BUILD_ID'
      - '-t'
      - '${_IMG_REPO}/$PROJECT_ID/${_APP_NAME}:latest'
      - '-f'
      - "${_DOCKERFILE}"
      - '.'

  # push container image
  - name: 'gcr.io/cloud-builders/docker'
    args: ["push", "${_IMG_REPO}/$PROJECT_ID/${_APP_NAME}:$BUILD_ID"]

  # push container image
  - name: 'gcr.io/cloud-builders/docker'
    args: ["push", "${_IMG_REPO}/$PROJECT_ID/${_APP_NAME}:latest"]

  # deploy on cloud run
  - name: 'gcr.io/cloud-builders/gcloud'
    args:
      - beta
      - run
      - deploy
      - ${_APP_NAME}
      - --image
      - ${_IMG_REPO}/$PROJECT_ID/${_APP_NAME}
      - --region
      - ${_CLOUDSDK_COMPUTE_ZONE}
      - --platform
      - managed
      - --quiet
      - --cpu=${_CPU}
      - --memory=${_MEMORY}
      - --port=8080
      - --allow-unauthenticated
      - --timeout=${_TIMEOUT_LIMIT}
      - --project=${PROJECT_ID}
      - --max-instances=${_MAX_INSTANCES}
      - --min-instances=${_MIN_INSTANCES}
      - --concurrency=${_CONCURRENCY}
      - --execution-environment=gen1

images:
  - ${_IMG_REPO}/$PROJECT_ID/${_APP_NAME}:latest
  - ${_IMG_REPO}/$PROJECT_ID/${_APP_NAME}:$BUILD_ID

substitutions:
  _IMG_REPO: 'asia.gcr.io'
  _APP_NAME: 'api-production'
  _DOCKERFILE: 'Dockerfile.api'
  _ENV_FILE: '.env'
  _PHP_DOT_ENV: 'api-production-env'
  _CLOUDSDK_COMPUTE_ZONE: 'asia-east1'
  _MIN_INSTANCES: '0'
  _MAX_INSTANCES: '2'
  _CPU: '1'
  _MEMORY: '512M'
  _CONCURRENCY: '120'
  _TIMEOUT_LIMIT: '30'

明天我們會進一步回到了本地環境的建立,會使用 dockerdocker-compose 來建立人人都可以使用的開發環境。就算是在深山中網路不穩時,也可以愉快開發的模式與工作 style。

讓容器化的環境減少不必要的 debug 時間,重新掌握開發的步調!

Reference


上一篇
#2 萬事俱備 只欠開始! 專案與雲服務初始化
下一篇
#4 API Service 的第二步: 本地與 Laravel 初始化
系列文
Laravel 擴展宇宙:從 1 到 100 十倍速打造產品獨角獸30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
mikehsu0618
iT邦新手 1 級 ‧ 2023-09-19 10:50:27

看到 git 頭就痛啊啊

Bill iT邦新手 4 級 ‧ 2023-09-19 16:29:42 檢舉

越是重要才是越頭痛的地方R

0
xie
iT邦新手 4 級 ‧ 2023-09-22 12:57:09

YAGNI !!

我要留言

立即登入留言