浏览代码

add qpkg notes

Ray Lee 5 年之前
父节点
当前提交
5a3255cc62
共有 4 个文件被更改,包括 403 次插入0 次删除
  1. 101 0
      qpkg/01_build_qpkg.md
  2. 65 0
      qpkg/02_qpkg_settings.md
  3. 49 0
      qpkg/03_docker_compose.md
  4. 188 0
      qpkg/04_example.md

+ 101 - 0
qpkg/01_build_qpkg.md

@@ -0,0 +1,101 @@
+# How To Build QPKG
+## 簡介
+### QPKG
+* QPKG 是 qnap 提供, 專門放在 qnap 環境使用的檔案格式. 可以把其他軟體包裝成 QPKG 格式, 供其他 user 在 qnap 上使用
+* QPKG 是以 shell script 為基礎進行包裝, 以一份 shell script 檔提供 `start`, `stop` 等指令
+* 可在 QNap NAS 上, 或其他 Linux 環境安裝 QPKG 開發工具進行開發
+
+### QNap QTS
+* QNap 上搭載的 GUI 管理介面
+  * 可以網頁形式開啟 (host_ip:8080)
+* 上面有 APP Center 可以
+  * 可以搜尋 App 並安裝, 管理
+  * 所有安裝好的 QPKG 會出現在 APP Center 上
+* 上面有 Container Station, 是 docker 的 GUI 介面
+  * 可以使用 docker
+    * 包含一般的 container / image 控制
+    * 可以搜尋 docker hub
+  * 支援 docker-compose
+    * container-station > create 分頁 > create application 按鈕可出現視窗, 讓你輸入 docker-compose.yml 的內容
+
+### QDK
+* QDK 全名 QNAP Development Kit.
+  * 是用來開發 QPKG 的工具
+  * QDK 也被包裝成一個 QPKG 以供使用
+
+
+## 建立環境
+### 建立 QDK 環境 ( on QNap NAS )
+* 安裝 QDK
+  * QDK 是 QNap 官方提供用來建立 QNap Nas 專用 App 的工具
+  * 在 QTS 介面中的 App Center 搜尋 `QDK` 並安裝
+  * 有提供 command line 安裝方式, 一般 linux 也可以安裝來開發
+
+* 環境
+  * 指令 ```cd `getcfg QDK Install_Path -f /etc/config/qpkg.conf` ``` 切換到 qnap 的安裝路徑, 其中
+    * `bin/qbuild` 這個檔案應該是 qbuild 指令的本體
+    * `template` folder 中放置新 qpkg 開發環境的 template file
+
+* 其他
+  * QDK 沒有提供 GUI 開發介面, 以 command line 介面下指令進行相關的包裝行為
+  * `getcfg`
+    * 用來取得 某檔案 -> 某個設定集合 -> 某個設定值
+    * 指令格式 : 
+      * `getcfg [config_group] [key_1]       [key_2] ... -f [config_path]`
+      * `getcfg [      QDK   ] [Install_Path]            -f [/etc/config/qpkg.conf]`
+      * 可以開 `/etc/config/qpkg.conf` 這份檔案 看對應的檔案格式
+
+
+### 建立 QPKG 專案
+* `qbuild --create-env` 指令
+  * 用來建立一個新的 QPKG App 專案
+  * 需在 QPKG 安裝路徑下使用
+  * 指令 `qbuild --create-env MyQPKG`, 其中 `MyQPKG` 替換成你的 Project Name
+  * 此時會有一個新的 MyQPKG folder 出現 ( 跟原本的 folder 和在一起 )
+
+* 所有建立新的 QPKG 開發環境指令如下
+  * ```cd `getcfg QDK Install_Path -f /etc/config/qpkg.conf` ```
+  * `qbuild --create-env KdanQPKG`
+  * `cd KdanQPKG`
+
+* 將路徑切到 QPKG 專案中 ( 如上述的 KdanQPKG folder ) 可看到
+  * `qpkg.cfg` file
+    * 主要的 config 檔, 包含多種設定
+  * `package_routines` file
+    * 程式 install 時的一些 callback function
+  * `icons/` folder
+    * 程式 icon, 若 QPKG_NAME Name 為 KdanQPKG, 則需含有
+      * `KdanQPKG.gif`      : App 列表顯示的 icon, 64*64px
+      * `KdanQPKG_80.gif`   : App details 顯示的 icon, 80*80px,
+      * `KdanQPKG_gray.gif` : `KdanQPKG.gif` 的 disable 版本, 64*64px
+    * 若沒有這些圖片, 會用預設圖片
+    * 可在 QDK 路徑下, 找到這三張預設圖片(為隱藏檔案, `.`開頭), 確認尺寸等詳細資訊
+    * [官方文件](https://edhongcy.gitbooks.io/qdk-qpkg-development-kit/content/qdk-variables.html) 有提到詳細尺寸
+  * `build/` folder
+    * 放最後 build 好的 QPKG 檔
+  * `config/` folder
+    * 不知道幹嘛的
+  * `arm_64/`, `arm-x19/`, `arm-x31/`, `arm-x41/`, `x86/`, `x86_64/`, `x86_ce53xx/`
+    * 放你的 code ( 給特定 cpu 架構 ), 用不到可以刪掉
+  * `shared/`
+    * 放你的 code, 不區分 cpu 架構的部分都放這裡 (docker-compose 相關也是). 
+    * 其中會有預設的 sh 檔, 要負責程式 start, stop 等 shell 指令設定
+
+### Build QPKG
+* 建立專案內容
+  * (略, 參考下段 docker-compose 範例)
+
+* Build App 並安裝 (在你的 QPKG 專案 root folder 上)
+  * `qbuild` : (把你的程式 build 成 QPKG 檔)
+  * `cd build` : 結果放在 build 資料夾下
+  * `sh KdanQPKG_0.1.qpkg` : 直接執行 buid 出來的 qkpg 檔, 進行安裝 (或透過他的 QTS 介面, 上傳此檔案)
+
+* 安裝完, 在 QTS App Center 可看到你的 QPKG 出現, 可在此處 stop / remove
+
+reference : 
+* [官方 QPKG Install Guide](https://edhongcy.gitbooks.io/qdk-quick-start-guide/content/build-your-own-qpkg.html)
+* [官方 QPKG Development Tool Kit](https://edhongcy.gitbooks.io/qdk-qpkg-development-kit/content/qpkg-configuration-file.html)
+* [QPKG 包裝範例](http://ilearnblogger.blogspot.com/2014/03/qnap-nas-install-qnap-app-with-qdk.html)
+* [docker-compose 包入 QPKG 範例](https://medium.com/@amosricky95/%E6%96%B0%E6%89%8B%E7%AD%86%E8%A8%98-%E5%AF%A6%E4%BD%9Crestful-api-with-dockerized-qpkg-%E4%BD%BF%E7%94%A8python-restframework-dqpkg-%E9%83%A8%E4%BB%BD-ba755e248498)
+* [官方 docker in QPKG Format](https://github.com/qnap-dev/docker-qdk2)
+* [官方 package_router 範例](https://github.com/qnap-dev/docker-qdk2/blob/master/example/nginx/package_routines)

+ 65 - 0
qpkg/02_qpkg_settings.md

@@ -0,0 +1,65 @@
+# QPKG 設定
+一個新的 qpkg 專案產生後, 會有幾個比較重要的部分要設定
+
+## qpkg.cfg
+* 是一個一堆 key-value 的設定檔
+* 有一堆設定, 可以參考 [官方文件](https://edhongcy.gitbooks.io/qdk-qpkg-development-kit/content/qpkg-configuration-file.html)
+* 重點 : 
+  * `QPKG_SERVICE_PROGRAM` 名稱, 要與下面的 [project_name].sh 相同 ( 包含.sh )
+  * QPKG 預設認定你的 app 介面是一個 web application 介面
+    * `QPKG_WEBUI`    預設的 web application path
+    * `QPKG_WEB_PORT` 預設的 web application port
+    * `QPKG_DESKTOP_APP` 預設認定用一個新的 broswer 分頁開啟你的 web application
+      * 若是把它設定為 1, 則會用她自己 QTS 的 popup 視窗開啟
+      * 但此方式是 iframe, 會有 x-frame-options 問題
+
+## package_routines
+* 用來設定 安裝 / 移除 的 callback-function
+  * 基本上是個 shell script
+* 這份文件內, 可以使用一些 QPKG 提供的變數, 可以參考 [官方文件](https://edhongcy.gitbooks.io/qdk-qpkg-development-kit/content/generic-installation-script.html)
+  * 如 `SYS_QPKG_DIR` 是這個 QPKG 被安裝的路徑
+* 有 `pkg_post_install`, `pkg_install`, `pkg_post_install` 三個安裝時的 callback
+  * 這三個是一般 shell script 的 function, 可自由使用  `SYS_QPKG_DIR` 等變數
+* `PKG_PRE_REMOVE`, `PKG_MAIN_REMOVE`, `PKG_POST_REMOVE` 這三個是移除的時候用的 callback 設定
+  * 他不是一個 shell script function, 而是一個 shell script 變數
+    * 內容是一個 string, 安裝時 QPKG 會把這個 string 拿去產生 shell script function
+    * 但是新產生的 function 在執行時無法使用 `SYS_QPKG_DIR` 等官方提供的變數
+  * 因為是個 string, 所以延伸出很多問題
+    * 基本概念是把你要執行的 shell 指令寫在指令中
+    * shell script 的 string 在宣告時, 會先把 `$` 進行一次替變數替換, 若不想被替換, 要加上跳脫字元 `\$`
+  * 基本上 : 
+    * 官方變數 及 自訂的 help 變數會直接帶入, 使用 `$`
+    * function 運行中儲存資料的變數, 使用 `\$`
+  * 範例
+
+```sh
+DOCKER=$(/sbin/getcfg container-station Install_Path -f ${QPKG_CONF})/bin/system-docker
+
+PKG_PRE_REMOVE="{
+    IMAGE_ID=\$(/bin/cat $SYS_QPKG_DIR/loaded_docker_images)
+    $DOCKER image rm \$IMAGE_ID
+}"
+```
+
+  * 在[官方文件](https://edhongcy.gitbooks.io/qdk-qpkg-development-kit/content/package-specific-installation-functions.html)(最下方)有提到這件事, 但其內容應該有一些 render 上的錯誤
+
+* 其他
+  * 網路上看到的很多範例 (QPKG 包 docker-compose), 其 package_routines 內容都與此份 [官方 nginx 範例](https://github.com/qnap-dev/docker-qdk2/blob/master/example/nginx/package_routines) 一模一樣, 但還不了解其用意為何, 先備註起來
+
+## shared/[project_name].sh
+* 是個 shell script
+* 根據檔案預設的提示, 將 start / stop 的 shell 指令加在適當的位置即可
+* 這個檔案吃不到 `SYS_QPKG_DIR` 等系統變數, 所以有些參數要用 getcfg 自己拿
+
+## shared folder
+* 你的程式主體放在這, 包含用來啟動的 [project_name].sh
+* 若有 `X86` 等專用的檔案, 要放在對應的資料夾, 而不是 shared
+
+## icons
+* 程式 icon, 若 QPKG_NAME Name 為 KdanQPKG, 則需含有
+  * `KdanQPKG.gif`      : App 列表顯示的 icon, 64*64px
+  * `KdanQPKG_80.gif`   : App details 顯示的 icon, 80*80px,
+  * `KdanQPKG_gray.gif` : `KdanQPKG.gif` 的 disable 版本, 64*64px
+* 若沒有這些圖片, 會用預設圖片
+* 可在 QDK 路徑下, 找到這三張預設圖片(為隱藏檔案, `.`開頭), 確認尺寸等詳細資訊
+* [官方文件](https://edhongcy.gitbooks.io/qdk-qpkg-development-kit/content/qdk-variables.html) 有提到詳細尺寸

+ 49 - 0
qpkg/03_docker_compose.md

@@ -0,0 +1,49 @@
+# Docker Compose Relese
+
+* 準備好要用的 docker-compose
+  * 確定你的 docker-compose 跑得起來
+
+## 重新整理 Docker Compose
+* Release 出去的 Docker Image tag 會被看到, 所以建議好好重新命名 (auth/image_name:version)
+  * ecr 之類的名稱資訊建議拿掉
+  * nginx 之類直接加上一些 config 拿來用的, 可以用 Dockerfile 重包
+  * DottedSign 之類已經完整的, 可以 re-tag
+    * `docker tag 58...68.dkr.ecr.us-east-1.amazonaws.com/dottedsign:preparing kdanmobile/qnap_dotted_sign_web:1.0`
+
+* 開一個新的 project folder
+  * 建立一個新的 docker-compose.yml
+    * 讓他使用新的 image tag
+    * 讓他只需要 docker-compose.yml 跟 image, 不需其他檔案 (比較方便一點)
+  * 確定可以正常 run
+
+## 壓縮 Docker Image
+  
+* 把 docker image 壓成 tar.gz 檔
+  * 可以不用再從 docker hub 抓 (避免 ecr 登入)
+  * 指令 : `docker save kdanmobile/qnap_dotted_sign_web:1.0 | gzip -c > dotted_sign_web.tar.gz`
+    * 一個 image 可能有很多個 tag, 但 tar 只會紀錄指令中的那個 (kdanmobile/qnap_dotted_sign_web:1.0)
+    * 若是指令中使用 image id (sha256), 則 tar 中不會有 tag 資訊 (只剩 id)
+
+* 把這些新的 Image 壓縮檔丟到新的 project folder
+  * 這個 folder 只包含 docker-compose.yml 及 image 壓縮檔
+  * 只需要這個 folder, 就能重新 run 整個 docker compose
+
+## 還原 Docker Image
+* 在其他電腦拿到這個 folder 後
+  * 切到 folder 裡
+  * 還原 docker-image : `docker load < dotted_sign_web.tar.gz`
+  * 檢查 `docker ps -a` 應該可以看到你的 docker image
+  * `docker-compopse up -d` 應該可以正常執行
+
+## 其他資訊
+### QNap 上的 system-docker 指令
+* 一般 docker 指令
+  * QNap 內建一般 docker
+  * QNap QTS 有提供 Container Station, 可以直接 run docker
+
+* QNap 另外提供了 `system-docker-compose`
+  * 所有 docker, docker-compose 相關的指令, 都有對應的 `system-docker`, `system-docker-compose` 版本
+    * 範例 : `system-docker ps -a`, `system-docker-compose up -d`
+  * 他就是一般 docker, 只是把所有的 image, container, volume 等, 跟原本 docker 區隔開
+    * QNap 工程師建議若要把 docker-compose 包裝成 QPKG, 可使用 system-docker-compose
+    * 一般的 docker 指令, QTS 的 container station 不會看到 system-docker 的相關資訊, 不會造成使用者誤刪 or 其他麻煩

+ 188 - 0
qpkg/04_example.md

@@ -0,0 +1,188 @@
+# 範例 : 將 Docker-Compose 包裝成 QPKG
+## 前置作業
+* 安裝 QPKG
+* 假設專案名稱為 `DottedSign`
+
+## 準備好 Docker Compose
+* 確定你的 docker-compose 跑得起來
+* 重新整理 docker image
+  * DottedSign : `docker tag 58...68.dkr.ecr.us-east-1.amazonaws.com/dottedsign:preparing kdanmobile/qnap_dotted_sign_web:1.0` 
+  * Nginx : 把 nginx:1.17.0 跟 DottedSign 的 conf 設定重新包成新的 image `kdanmobile/qnap_dotted_sign_nginx:1.0`
+
+* 建立新的 docker-compose project
+  * 開新 project folder : `mkdir new_dotted_sign`
+  * 修改 docker-compose.yml 使用新的 image tag
+  * 把 docker image 壓成 tar.gz 檔
+    * `docker save kdanmobile/qnap_dotted_sign_web:1.0 | gzip -c > dotted_sign_web.tar.gz`
+    * `docker save kdanmobile/qnap_dotted_sign_nginx:1.0 | gzip -c > dotted_sign_nginx.tar.gz`
+  * 確認 folder 中只有 docker-compose.yml && 所有的 image 壓縮檔
+
+## 建立 QPKG 專案
+* ```cd `getcfg QDK Install_Path -f /etc/config/qpkg.conf` ```
+* `qbuild --create-env DottedSign`
+* 將產生出來的 `DottedSign` folder, 移到你想移動的位置
+
+## 修改專案內容
+* 先進入專案資料夾
+  * `cd [DottedSign_path]`
+### 移除無用檔案
+* 把用不到的 folder 砍掉
+  * `rm -r arm_64/  arm-x19/  arm-x31/  arm-x41/ x86/  x86_64/  x86_ce53xx/`
+### 放置你的 docker-compose
+* `cd shared`
+* `cp -r [new_dotted_sign path] docker_folder` 名稱隨意, 後面會用到
+* 確保 `docker-compose up` 能夠順利執行
+  * 切到 docker_folder 中
+  * 還原 docker image
+  * 確認 `docker-compose up -d` 正常執行
+  * `docker-compose down`
+  * 砍掉 docker image
+
+### 放置 icon
+* `cd [DottedSign_path]/icons`
+* 裡面放三張圖片
+  * `DottedSign.gif`      : App Center  顯示的 icon, 64*64px
+  * `DottedSign_gray.gif` : disable 版本 icon, 64*64px
+  * `DottedSign_80.gif`   : icon, 80*80px
+
+* **重點** 
+  * 注意檔名, `DottedSign` 應該是對應到 `QPKG_NAME`
+  
+
+### [DottedSign_path]/qpkg.cfg 修改如下
+
+```conf
+QPKG_NAME="dotted_sign"
+QPKG_DISPLAY_NAME="DettedSign"
+QPKG_VER="1.0"
+QPKG_AUTHOR="Kdan Mobile"
+
+# 啟動你的 qpkg 後, 要用哪個 port 及哪個 default path 連到你的服務
+QPKG_WEBUI="/"
+QPKG_WEB_PORT=4040
+
+# # 以下兩個為預設值不用動
+QPKG_RC_NUM="101"
+QPKG_SERVICE_PROGRAM="dotted_sign.sh"
+
+# # 可能會需要加註 license (GPL, MIT .. .)
+# QPKG_LICENSE=""
+
+# # 實測過, 但不知道會顯示在哪
+# QPKG_SUMMARY="The Best E-Signature Solution for Your Business"
+
+# # 當值為 1 ( default 非 1 ), 會以 popup 的方式顯示你的網頁, 而非另開分頁, 但有 iframe x-frame-options 問題
+# QPKG_DESKTOP_APP=1
+
+# 以下有一堆其他設定, 但都是註解掉的狀態
+```
+
+* **重點** : 此檔案內容
+  * `QPKG_NAME` 會被其他檔案參照, 需要注意是否正確
+  * `QPKG_SERVICE_PROGRAM` 需要確認與 `shared/` 下的檔名一致(預設應該ok)
+  * `QPKG_WEBUI`, `QPKG_WEB_PORT` 要看你 web application, nginx 的設定
+
+
+### [DottedSign_path]/package_routines 修改如下
+
+```sh
+QPKG_CONF=/etc/config/qpkg.conf
+DOCKER=$(/sbin/getcfg container-station Install_Path -f ${QPKG_CONF})/bin/system-docker
+
+image_id_from_docker_load() {
+  # docker load will return one of:
+  # 1. "Loaded image: nginx:1.17.0"
+  # 2. "Loaded image ID: sha256:719cd2e...cb50105"
+
+  IMAGE_ID=$(echo "$1" | sed 's/Loaded image: //g' | sed 's/Loaded image ID: sha256://g')
+  echo $IMAGE_ID
+}
+
+load_docker_image() {
+  LOAD_RESULT=$($DOCKER load < "$SYS_QPKG_DIR/docker_folder/$1")
+  IMAGE_ID=$(image_id_from_docker_load "$LOAD_RESULT")
+  echo $IMAGE_ID
+}
+
+# callback-function
+pkg_post_install(){
+    IMAGES_ID_1=$(load_docker_image "dotted_sign_nginx.tar.gz")
+    IMAGES_ID_2=$(load_docker_image "dotted_sign_web.tar.gz")
+    echo "$IMAGES_ID_1 $IMAGES_ID_2" > $SYS_QPKG_DIR/loaded_docker_images
+}
+
+# callback-pseudo-functions
+PKG_PRE_REMOVE="{
+    IMAGE_ID=\$(/bin/cat $SYS_QPKG_DIR/loaded_docker_images)
+    $DOCKER image rm \$IMAGE_ID
+}"
+```
+* 此檔案內容全都被註解掉, 因此直接加入即可
+* **重點** :
+  * `pkg_post_install`
+    * 要注意到底 load 了哪些 image 壓縮檔
+  * `PKG_PRE_REMOVE` 是個字串
+    * 要留意哪些地方要跳脫, 哪些不用
+
+
+### [DottedSign_path]/shared/dotted_sign.sh 修改如下
+
+```sh
+#!/bin/sh
+CONF=/etc/config/qpkg.conf
+QPKG_NAME="dotted_sign"
+
+DOCKER_COMPOSE=$(/sbin/getcfg container-station Install_Path -f ${CONF})/bin/system-docker-compose
+SYS_QPKG_DIR=$(/sbin/getcfg $QPKG_NAME Install_Path -f ${CONF})
+DOCKER_COMPOSE_FILE="$SYS_QPKG_DIR/docker_folder/docker-compose.yml"
+
+# # 不知道用途, 實測砍掉沒差 先保留
+# export QNAP_QPKG=$QPKG_NAME
+
+case "$1" in
+  start)
+    ENABLED=$(/sbin/getcfg $QPKG_NAME Enable -u -d FALSE -f $CONF)
+    if [ "$ENABLED" != "TRUE" ]; then
+        echo "$QPKG_NAME is disabled."
+        exit 1
+    fi
+    : ADD START ACTIONS HERE
+    $DOCKER_COMPOSE -f $DOCKER_COMPOSE_FILE -p $QPKG_NAME up -d
+    ;;
+
+  stop)
+    : ADD STOP ACTIONS HERE
+    $DOCKER_COMPOSE -f $DOCKER_COMPOSE_FILE -p $QPKG_NAME down
+    ;;
+
+  restart)
+    $0 stop
+    $0 start
+    ;;
+
+  *)
+    echo "Usage: $0 {start|stop|restart}"
+    exit 1
+esac
+
+exit 0
+```
+
+* 對此檔案的變更, 主要是刪除一些無用的變數設定, 加入 start / stop 的 docker-compose 指令
+* **重點** : 凡是 docker-compose 的 QPKG, 此檔案內容應該幾乎一樣
+  * 只有 `QPKG_NAME` 會變動, 要參考你的 `qpkg.cfg`
+  * 其餘部分完全一樣, 可以複製貼上
+
+## Build 專案
+* `cd [DottedSign_path]`
+* `qbuild`
+
+## 安裝 QPKG
+* 方法一 : 利用 App Center 上傳你的檔案進行安裝
+* 方法二 : 若安裝檔已經在 QNap Nas 上, 可用 command line 安裝
+  * `cd [DottedSign_path]/build`
+  * `chmod 755 dotted_sign_0.2.qpkg`
+  * `./dotted_sign_0.2.qpkg`
+<!--stackedit_data:
+eyJoaXN0b3J5IjpbLTk2MDQxNDg3XX0=
+-->