這一篇主要講述部署一個 Web 專案,專案是我曾經搞的一個 VUE
模板專案:https://github.com/orca-studio/vue-template/tree/vite-3.X
目前還沒有搭建映象私有倉庫和自動化部署流程。
只能本地打包 Docker
映象,上傳 DockerHub
,再伺服器拉取映象,進行啟動。
本地打包 Docker
需要本地具有 Docker
環境。
Windows
或 Mac
的 Docker
環境,可以在網上查詢怎麼安裝。
構建映象
部署 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 目錄。
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
但是允許以 上下文(目錄)
為相對目錄的基準目錄。
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-server
中 historyApiFallback 屬性
執行構建
執行構建 映象(Image)
使用的命令是 docker build
。
為了執行方便,在 package.json
中新增 deploy 命令執行構建
每次構建 映象(Image)
前,先進行專案編譯。也就是執行 npm run build
命令。當編譯成功後才執行 docker build
。
PS:
npm-run-all
是一個 NPM 包,用於執行多個指令碼
PS:
Docker Hub
沒有賬號的需要先進行註冊:https://hub.docker.com/
docker build
命令中使用了幾個引數
- -t 構建的映象名稱。 其中 yxs970707 是
Docker 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)
的分層其實每一句命令都是一層。
測試映象
成功構建映象後可以先在本地測試
在此將本地 3333 埠號對映到了容器。可以根據情況隨意設定未被使用的埠號,
如果未出意外的話將會啟動一個 容器
,容器狀態為 RUNNING。
如果啟動時出錯的話,可以點選容器檢視錯誤日誌進行分析
按照步驟理論上不會有什麼問題,如有未成功的可以查詢日誌嘗試解決,實在解決不了可以留言。
推送 Docker Hub
映象
推送 Docker Hub
很簡單,只需要在 Docker Desktop
中登入賬號點選 push 即可
PS:之後部署私有倉庫之後可以推送到私有倉庫
push 成功後就可以在 Docker Hub
中搜到此映象
部署容器
最簡部署
容器的最簡部署方案是隻設定埠號
拉取映象可能有些延遲,因為
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
部署完畢後就可以訪問伺服器進行訪問。
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,也就是根本沒有找到該地址
/usr/share/nginx/html 目錄是儲存前端檔案的目錄。
在伺服器檢視會發現掛載目錄並沒有任何檔案,進入容器內部查詢 /usr/share/nginx/html 也沒有任何檔案
也就是說 Docker
在啟動容器時,使用宿主目錄(空目錄)覆蓋了容器內目錄。
docker exec -it web /bin/sh 進入容器
可以在宿主目錄建立一個檔案測試,在此只貼出測試結果。有興趣的可以自行測試。
具名 Volumes
解決資料掛載問題,需要建立具名的 Volumes。
Docker
中 Volume
是一個完整的模組。具有很強大的功能。
甚至可以將資料掛載到其它機器上,在此只使用 Volume
完成目前的需求。
其它功能,有興趣的朋友可以自行查詢穩定。
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。
仔細觀察的情況下, Portainer
視覺化工具中在 Volume
項此時具有一個 web-html 的資料卷
在其詳細資訊中可以看到具體詳情。
其中具有一個 Mount path 屬性,這個屬性值是此資料卷的目錄。
其實在 Docker
掛載資料卷時,會將此目錄與容器內進行掛載。
另外還有一個 device 屬性,這個資料是與資料卷繫結的目錄。Linux 具有一種可以將 Mount path 和 device 繫結為一個目錄方案
當然還可以使用其它繫結方案,將資料卷繫結到其它目錄。甚至可以繫結到其它機器