私有化輕量級持續整合部署方案--03-部署web服務(上)

莫問今朝乄 發表於 2022-02-17
提示:本系列筆記全部存在於 Github, 可以直接在 Github 檢視全部筆記

這一篇主要講述部署一個 Web 專案,專案是我曾經搞的一個 VUE 模板專案:https://github.com/orca-studio/vue-template/tree/vite-3.X

私有化輕量級持續整合部署方案--03-部署web服務(上)

目前還沒有搭建映象私有倉庫和自動化部署流程。

只能本地打包 Docker 映象,上傳 DockerHub,再伺服器拉取映象,進行啟動。

本地打包 Docker 需要本地具有 Docker 環境。

WindowsMacDocker 環境,可以在網上查詢怎麼安裝。

構建映象

部署 Web 專案 的第一步是構建 映象(Image)

映象(Image) 是執行時所使用的檔案資源。

Docker 提供了製作 映象(Image) 的方式:使用 build 命令執行 Dockerfile 檔案。

構建 映象(Image) 的關鍵 就在於 Dockerfile 檔案。 Dockerfile 配置了構建映象時所有的操作。

執行 build 時,需要提供一個 上下文目錄(Context)(一般上下文目錄為專案根目錄)。

Docker 會將上下文目錄(Context) 與子目錄結構傳送到 Docker 引擎Docker 引擎 根據這個目錄結構去構建 映象 (Image)

Dockerfile 檔案中,是不允許訪問 上下文目錄(Context) 之外的目錄。

這就是有些教程中會說不能在 Dockerfile 使用 ../ 原因。

預設情況下 Docker 會讀取 上下文目錄(Context)Dockerfile 檔案,所以一般都會將 Dockerfile 檔案放在根目錄。

當然也可以放在其它目錄,執行 build 時使用引數指定 Dockerfile 檔案

PS: 注意:在構建 映象 時不允許訪問 上下文目錄(Context) 之外的目錄。

Dockerfile

為了管理方便,將所有的部署相關放在 deploy 目錄。

所以也將 Dockerfile 存放在 deploy 目錄。

私有化輕量級持續整合部署方案--03-部署web服務(上)
FROM nginx:latest

# 將程式碼copy到映象
COPY ../dist /usr/share/nginx/html

# 將 nginx 配置檔案 copy 到容器內配置檔案的目錄下
COPY ../deploy/nginx.conf /etc/nginx

# 容器應用埠
EXPOSE 80

PS:Dockerfile 支援好多指令,在此只介紹使用到的指令,其它指令有興趣的朋友可以自行查詢

  • 第一行 FROM 指令:表示使用的底層映象,製作應用級別映象,都需要依賴執行環境。web 專案的執行環境為 Nginx 伺服器。

    PS: 之前說過, 映象是分層儲存的,構建映象可以簡單的理解為在現有映象上新增一層。

  • 第二行 COPY 指令:表示 複製檔案,將本地的目錄或者檔案 複製到映象指定目錄下。
    ./dist 目錄,也就是專案編譯生成的程式碼目錄複製到 映象中 /usr/share/nginx/html 目錄

    PS:所有相對目錄都是以 上下文目錄(Context) 為基準,所以 dist 目錄訪問是 ./dist,而非 ../dist

  • 第三行 COPY 指令:表示將 nginx.conf 配置檔案 複製到 /etc/nginx

    PS:所有相對目錄都是以 上下文目錄(Context) 為基準,所以 nginx.conf 目錄訪問是 ./deploy/nginx.conf,而非 ./nginx.conf

    web 專案 容器 執行的是 Nginx 伺服器, 自己製作的 web 映象 映象(Image) 只是將生成的靜態檔案掛載到 Nginx 伺服器上。

    nginx.conf 檔案是用來配置 Nginx 掛載路由等資訊。

  • 第四行 EXPOSE 指令:暴露埠號,啟動容器時使用 ports 對映容器內部的埠號就是此命令暴露的。

Nginx 映象中,暴露了 80 埠執行 Nginx 伺服器,Dockerfile 中只暴露 80 埠,在啟動時 80 埠直接啟動的是 Nginx 伺服器。

注意:不允許直接使用 ./nginx.conf 訪問,會被識別成以 上下文目錄(Context) 下的 nginx.conf

私有化輕量級持續整合部署方案--03-部署web服務(上)

但是允許以 上下文(目錄)為相對目錄的基準目錄。

nginx.conf

deploy/nginx.conf 檔案中編寫 Nginx 配置。 構建映象(Image)時會將此檔案複製到映象

PS: 也可以使用類似上一篇中的將 nginx.conf 掛載到宿主環境中。

events {
    worker_connections  1024;
}

http {
    include mime.types;
    default_type text/html;
    sendfile on;
    keepalive_timeout 65;
    charset utf-8;
    error_log  /var/log/nginx/error.log;
    access_log  /var/log/nginx/access.log;
    server {
        listen       80;

        location / {
            root    /usr/share/nginx/html;
            index  index.html index.htm;
            try_files $uri $uri/ /index.html;
        }
    }
}
  • root: 此屬性設定根目錄,當前根目錄設定為 /usr/share/nginx/html,靜態檔案都儲存在此目錄。
  • index: 此屬性指定網站初始頁面。 也就是 /usr/share/nginx/html/index.html
  • try_files: 此屬性將所有的訪問都轉為 index.html 。單頁面程式的路由都是請求同一個 HTML,由 JS 內部判斷的路由頁面,
    類似 webpack-dev-serverhistoryApiFallback 屬性

執行構建

執行構建 映象(Image) 使用的命令是 docker build

為了執行方便,在 package.json 中新增 deploy 命令執行構建

每次構建 映象(Image) 前,先進行專案編譯。也就是執行 npm run build 命令。當編譯成功後才執行 docker build

私有化輕量級持續整合部署方案--03-部署web服務(上)

PS: npm-run-all 是一個 NPM 包,用於執行多個指令碼

PS: Docker Hub 沒有賬號的需要先進行註冊:https://hub.docker.com/

docker build 命令中使用了幾個引數

  • -t 構建的映象名稱。 其中 yxs970707Docker Hub 中的使用者名稱稱。
    當前沒有構建私庫,先推送到 Docker Hub。將 yxs970707 改為自己使用者名稱稱或組織。
    : 後的為當前映象的 標籤(tag),一般情況下會設定版本號。
    也可以使用多個 -t 設定多個版本號
  • -f Dockerfile 檔案地址,Dockerfile 檔案存在了 deploy 目錄,所以需要指定檔案地址。
  • 最後一個點 . 表示設定當前目錄為 上下文目錄(Context)

PS:標籤(tag) 可以隨意設定,標籤(tag) 可以根據實際情況使用版本號

PS: 構建映象時可以設定多 標籤(tag),新增多個 -t

此時,執行 npm run deploy 便可以構建映象(Image)。構建映象(Image)時,每一句命令都具有清晰的資訊。構建成功後就可以在本地 Docker 中看到此映象

PS:第一次構建可能會慢一些,因為本地沒有 Nginx 映象,需要 pull。

PS:映象(Image) 的分層其實每一句命令都是一層。

私有化輕量級持續整合部署方案--03-部署web服務(上) 私有化輕量級持續整合部署方案--03-部署web服務(上)

測試映象

成功構建映象後可以先在本地測試

私有化輕量級持續整合部署方案--03-部署web服務(上)

在此將本地 3333 埠號對映到了容器。可以根據情況隨意設定未被使用的埠號,

如果未出意外的話將會啟動一個 容器,容器狀態為 RUNNING

私有化輕量級持續整合部署方案--03-部署web服務(上) 私有化輕量級持續整合部署方案--03-部署web服務(上)

如果啟動時出錯的話,可以點選容器檢視錯誤日誌進行分析

私有化輕量級持續整合部署方案--03-部署web服務(上)

按照步驟理論上不會有什麼問題,如有未成功的可以查詢日誌嘗試解決,實在解決不了可以留言。

推送 Docker Hub

映象推送 Docker Hub 很簡單,只需要在 Docker Desktop 中登入賬號點選 push 即可

PS:之後部署私有倉庫之後可以推送到私有倉庫

push 成功後就可以在 Docker Hub 中搜到此映象

私有化輕量級持續整合部署方案--03-部署web服務(上) 私有化輕量級持續整合部署方案--03-部署web服務(上) 私有化輕量級持續整合部署方案--03-部署web服務(上)

部署容器

最簡部署

容器的最簡部署方案是隻設定埠號

拉取映象可能有些延遲,因為 Docker 配置了國內源,需要時間來同步

version: '3.9'
services:
  nginx:
    image: yxs970707/deploy-web-demo:1.0.0
    container_name: web
    restart: always
    ports:
      - 7777:80

PS:映象(Image)標籤(tag) 設定的為 1.0.0,拉取映象時需要指定

使用 Portainer 部署完畢後就可以訪問伺服器進行訪問。

私有化輕量級持續整合部署方案--03-部署web服務(上) 私有化輕量級持續整合部署方案--03-部署web服務(上)

volumes 掛載

在上面將所有檔案都存放映象中,並沒有使用 volumes/usr/share/nginx/html 目錄掛載到宿主機中。
接下來就實現這一操作,將資料掛載到宿主機中。

將資料掛載到宿主機中可以實現不更新映象和容器直接更新前端專案。

但是真實情況下並不推薦這樣做。這裡只是介紹下可以這樣做,在後續自動化部署時還是根據映象版本更新。

非具名 volumes 覆蓋問題

之前都是使用宿主目錄直接掛載容器內目錄。

直接使用宿主目錄掛載,在容器啟動時會使用宿主目錄覆蓋容器目錄。

version: '3.9'

services:
  nginx:
    image: yxs970707/deploy-web-demo:1.0.0
    container_name: web
    restart: always
    ports:
      - 7777:80
    volumes:
      - /volumes/web/html:/usr/share/nginx/html

更新 YMAL 檔案,新增掛載 /usr/share/nginx/html 目錄。

使用此檔案重新部署,訪問時 Nginx 會提示 403,也就是根本沒有找到該地址

私有化輕量級持續整合部署方案--03-部署web服務(上)

/usr/share/nginx/html 目錄是儲存前端檔案的目錄。

在伺服器檢視會發現掛載目錄並沒有任何檔案,進入容器內部查詢 /usr/share/nginx/html 也沒有任何檔案
也就是說 Docker 在啟動容器時,使用宿主目錄(空目錄)覆蓋了容器內目錄。

私有化輕量級持續整合部署方案--03-部署web服務(上) 私有化輕量級持續整合部署方案--03-部署web服務(上)

docker exec -it web /bin/sh 進入容器

可以在宿主目錄建立一個檔案測試,在此只貼出測試結果。有興趣的可以自行測試。

私有化輕量級持續整合部署方案--03-部署web服務(上)

具名 Volumes

解決資料掛載問題,需要建立具名的 Volumes。

DockerVolume 是一個完整的模組。具有很強大的功能。

甚至可以將資料掛載到其它機器上,在此只使用 Volume 完成目前的需求。

其它功能,有興趣的朋友可以自行查詢穩定。

私有化輕量級持續整合部署方案--03-部署web服務(上)

Volume 可以使用命令先進行建立,然後在掛載時使用。當然可以在 Docker Compose 建立。

version: '3.9'

volumes:
  web-html:
    name: web-html
    driver: local
    driver_opts:
      o: bind
      type: none
      device: /volumes/web/html

services:
  nginx:
    image: yxs970707/deploy-web-demo:1.0.0
    container_name: web
    restart: always
    ports:
      - 7777:80
    volumes:
      - web-html:/usr/share/nginx/html

YAML 檔案中 volumes 就是建立具名的資料卷。

這個資料卷使用了本地資料卷,將資料卷繫結本地 /volumes/web/html 目錄

PS: 資料卷還具有其它繫結方式,比如使用 IP 繫結其它機器。

然後使用 資料卷名稱(web-html) 掛載容器 /usr/share/nginx/html

注意,使用資料卷名稱掛載時, /volumes/web/html 目錄必須存在,目錄下不允許有檔案。

使用此 yml 部署便可以將資料掛載到 /volumes/web/html

私有化輕量級持續整合部署方案--03-部署web服務(上) 私有化輕量級持續整合部署方案--03-部署web服務(上)

仔細觀察的情況下, Portainer 視覺化工具中在 Volume 項此時具有一個 web-html 的資料卷

私有化輕量級持續整合部署方案--03-部署web服務(上)

在其詳細資訊中可以看到具體詳情。

其中具有一個 Mount path 屬性,這個屬性值是此資料卷的目錄。

其實在 Docker 掛載資料卷時,會將此目錄與容器內進行掛載。

另外還有一個 device 屬性,這個資料是與資料卷繫結的目錄。Linux 具有一種可以將 Mount pathdevice 繫結為一個目錄方案

當然還可以使用其它繫結方案,將資料卷繫結到其它目錄。甚至可以繫結到其它機器

私有化輕量級持續整合部署方案--03-部署web服務(上)