# [雲端教學] Vue 3 專案部署 Cloud Run 全攻略 - 從本機到 GCP:前端專案一鍵上雲的完整流程指南  平常做前端專案講到部署,大家應該都會想到 Vercel、Netlify 或 GitHub Pages 吧?這一次因為工作上的需要,嘗試了不同的做法,把網站部署在 Google 的 Cloud Run 上。 這篇文章就是想分享我自己實作部署的過程,希望可以幫助跟我一樣的前端夥伴,試試看不一樣的部署方式,也多了解一點雲端的世界。 ## Cloud Run Cloud Run 是 Google Cloud 提供的一個 serverless 容器平台,簡單來說,它可以把「裝在容器裡的應用程式」自動部署上網,不需要自己架伺服器,也不需要擔心流量太多會爆掉。 它有幾個很吸引人的優點: * 自動擴展:流量多就自動開多一點,流量少就省下資源費用。 * 按量計費:真的只有在有請求時才會付錢,用多少算多少。 * 支援容器:只要把程式包成容器,不管是前端還是後端,都可以跑在 Cloud Run 上。 * 公開存取:預設會生成一個可以對外訪問的 HTTPS 網址。 所以即使只是單純想部署一個 Vue 前端專案,只要學會打包成 Docker image,也能用 Cloud Run 來輕鬆上線! **Cloud Run 為什麼可以選擇 Artifact Registry / Docker Hub、GitHub、Function?** 當要部署一個應用到 Cloud Run,其實就是讓 Cloud Run「幫我們執行一個容器(Container)」。那這個容器從哪裡來呢?就得從我們指定的來源「拉取(pull)」image 來執行。  * GitHub 如果專案放在 GitHub,可以搭配 CI/CD 自動部署。 GitHub Actions 可以在 build 完 image 後直接推送到 Cloud Run。 * Function 這個其實不是「拉 image」的來源,而是另一種部署方式。如果選擇的是 Function,其實是把應用部署成 Cloud Function(無容器的 serverless 執行環境),適合純後端 API。 接下來的範例我們會是使用 Google Cloud 自家的倉庫 Artifact Registry 來做說明。 --- 上述段落有提到 image 跟 container,如果對這兩個詞感到陌生,可以想像成在做甜點 🍰: * Image(映像檔)就像是一個蛋糕的食譜,它定義了怎麼做蛋糕,但本身不能吃。 * Container(容器)是根據那個食譜烤出來的實際蛋糕,是可以吃的、活生生的實體。 我們可以從同一份食譜烤出很多個一模一樣的蛋糕,也可以改一點配方再烤出不同版本的蛋糕。 ## 前置作業 在把專案部署到 Cloud Run 之前,我們需要先完成以下幾個步驟: ### 建立 GCP 專案、開啟 Cloud Run API 因為 Cloud Run 是 GCP 提供的服務,所以我們要先建立一個 GCP 專案,才能使用其資源。 另外在使用 Cloud Run 之前,也必須確保有啟用它的 API。我們可以到 GCP Console 網頁上手動啟用,或是執行以下指令來啟用 Cloud Run API: ```bash! gcloud services enable run.googleapis.com ``` ### 安裝好 Google Cloud CLI(`gcloud`) Google Cloud CLI 是我們接下來要用來執行部署指令的工具,像是 `gcloud run deploy`、`gcloud builds submit` 等。 可參考官方的安裝文件:[Install the gcloud CLI](https://cloud.google.com/sdk/docs/install) 安裝完成後,進行初始化設定: ```bash! gcloud init ``` 這邊就會需要會登入 Google 帳號,選擇 GCP 專案,並設定預設地區。 ### 前端專案 這次的前端專案是透過 Vue3 搭配 Vite 建置的,使用的套件管理工具為 NPM,中間的開發流程跳過,我們直接快轉到專案部署的部分。 下圖中是我們現在 `package.json` 裡的腳本指令,目前有區分 development 跟 production 環境,也已經準備好相對應的環境檔案 `.env.development` 跟 `.env.production`。  ## Dockerfile 接下來我們需要一個 `Dockerfile` 檔案,把專案包成一個 Docker image 。以下是我們的 Dockerfile,裡面的內容可以根據讀者的需求去做修改。 ```dockerfile! # build stage FROM node:20-alpine AS build-stage WORKDIR /app COPY package*.json ./ RUN npm install COPY . . ARG BUILD_ENV RUN npm run build:${BUILD_ENV} # production stage FROM nginx:stable-alpine AS production-stage COPY --from=build-stage /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 8080 CMD ["nginx", "-g", "daemon off;"] ``` 這邊透過多階段建置(Multi-stage build) * 使用 `node:20-alpine` 建置 Vue 3 專案。 * 將建置好的 `dist` 目錄內容複製到 Nginx 的預設目錄中,不包含 node_modules 等開發資源。 將建置和部署分開,可以減少最終 image 的大小。另外可以傳入變數 `${BUILD_ENV}` 來 build 相對應的環境。 ## nginx.conf 因為我們在 Docker 裡是用 Nginx 來提供打包後的 dist 檔案,所以需要一個 `nginx.conf` 來正確設定伺服器行為。 > 如果是用 Nginx image 來部署 Vue 專案,就會需要一份 `nginx.conf`,用來設定靜態檔案路由、錯誤處理、快取機制等。最常見的用途是解決 Vue Router 的 history 模式會造成 reload 404 的問題。 ```nginx! server { # 指定 Nginx 監聽的 port,這邊是 8080 listen 8080; server_name localhost; client_max_body_size 100m; client_body_buffer_size 128k; proxy_connect_timeout 5; proxy_send_timeout 1800; proxy_read_timeout 1800; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; auth_basic "status"; # 開啟 gzip 壓縮,減少傳輸檔案的大小,加快載入速度 gzip on; # 只有大於 1KB 的檔案才會被壓縮,太小的檔案壓縮效益不高 gzip_min_length 1k; # 壓縮等級:1~9,數字越高壓縮效果越好,但耗 CPU,5 是推薦的平衡值 gzip_comp_level 5; # 只壓縮這些 MIME 類型的回應內容,圖片類型(如 .png, .jpg)不應壓縮,因為它們本來就壓縮過了 gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css; # 停用 IE6 以下版本的 gzip,因為他們可能無法處理壓縮檔案 gzip_disable "MSIE [1-6]\."; # 加上 Vary: Accept-Encoding 標頭,告訴瀏覽器這是根據使用者是否支援 gzip 所決定的內容格式,有助於 CDN 快取管理。 gzip_vary on; # 主要內容路由設定 location / { root /usr/share/nginx/html; index index.html index.htm; try_files $uri $uri/ /index.html; # 針對 Vue、React 等 SPA 的設定 } # 錯誤頁面處理 # 當出現伺服器錯誤(500~504)時,自訂錯誤頁面為 /usr/share/nginx/html/50x.html。這樣使用者會看到設計好的錯誤頁面,而不是預設的 Nginx 頁面。 error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } ``` ## 部署 最後我們回到 `package.json` 在 script 中補上這三條指令: ```javascript! "scripts": { "docker:build": "docker build . -t LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/PACKAGE[:TAG] --platform linux/amd64", "docker:run": "docker run LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/PACKAGE[:TAG]", "docker:push": "docker push LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/PACKAGE[:TAG]" } ``` `LOCATION`:填入 Artifact Registry 的位置,像是 `asia-east1` `PROJECT_ID`:GCP 專案 ID,我們可以到 GCP 上查找 `REPOSITORY`:在 Artifact Registry 上命名的倉庫名稱,例如:`my-frontend-repo` `PACKAGE`:要自己命名的 image 名稱,像是:`my-vue-app` `[:TAG]`:選填,可以當版號標記,像是 `:v1.2.3`,如果沒填的話預設是 `:latest` 成功把 image 推上 Artifact Registry 後,我們可以到 GCP 專案的 Cloud Run 頁面直接手動部署,也可以在本地寫指令。 ```javascript! "deploy:cloudrun": "gcloud run deploy CLOUD_RUN_SERVER --image LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/PACKAGE[:TAG] --platform managed --region LOCATION --allow-unauthenticated" ``` `CLOUD_RUN_SERVER`: 要部署的 Cloud Run 名稱 如果想達到懶人一鍵部署,可以把上述的指令全部整理起來,這樣每次要上版的時候,只要跑 `npm run deploy` 就可以上版囉~ ```javascript! "deploy": "npm run docker:build && npm run docker:push && npm run deploy:cloudrun" ``` --- 以上都完成後,就可以成功在 Cloud Run 提供的 URL 看到我們的網站囉 🎉 此文同步發佈於 Medium:[[雲端教學] Vue 3 專案部署 Cloud Run 全攻略](https://medium.com/@liz665319/vue3-deploy-to-cloud-run-guide-f2422fc5480f)
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up