Cách triển khai một trang web có Giao diện người dùng tạo sinh trên Cloud Run

1. Giới thiệu

Tổng quan

Trong phòng thí nghiệm này, bạn sẽ xây dựng và triển khai một trang web có nội dung được tạo tức thì bởi các mô hình ngôn ngữ lớn Gemini của Google. Trang web này sẽ là một trình điều hướng đơn giản theo kiểu "chọn cuộc phiêu lưu của riêng bạn" để khám phá các chủ đề, trong đó mỗi lần nhấp sẽ tạo một trang mới có các đường liên kết mới dựa trên lựa chọn của bạn. Bạn sẽ xây dựng trang web này bằng Node.js và Fastify, sử dụng Vertex AI SDK để gọi Gemini, triển khai trang web này dưới dạng một dịch vụ an toàn, sẵn sàng cho hoạt động sản xuất trên Cloud Run và bảo mật trang web này bằng Identity-Aware Proxy (IAP).

Bạn sẽ thực hiện

  • Tạo một ứng dụng Node.js Fastify sử dụng Vertex AI.
  • Triển khai ứng dụng lên Cloud Run từ nguồn mà không cần Dockerfile.
  • Bảo mật điểm cuối Cloud Run bằng Identity-Aware Proxy (IAP).

Kiến thức bạn sẽ học được

  • Cách sử dụng Vertex AI SDK cho Node.js để tạo nội dung.
  • Cách triển khai một ứng dụng Node.js lên Cloud Run.
  • Cách bảo mật một ứng dụng Cloud Run bằng IAP.

2. Thiết lập dự án

  1. Nếu chưa có Tài khoản Google, bạn phải tạo một Tài khoản Google.
    • Sử dụng tài khoản cá nhân thay vì tài khoản cơ quan hoặc trường học. Tài khoản cơ quan và trường học có thể có các hạn chế khiến bạn không thể bật các API cần thiết cho phòng thí nghiệm này.
  2. Đăng nhập vào Google Cloud Console.
  3. Bật tính năng thanh toán trong Cloud Console.
    • Việc hoàn thành phòng thí nghiệm này sẽ tốn ít hơn 1 USD tài nguyên Cloud.
    • Bạn có thể làm theo các bước ở cuối phòng thí nghiệm này để xoá tài nguyên nhằm tránh bị tính thêm phí.
    • Người dùng mới đủ điều kiện dùng thử miễn phí 300 USD.
  4. Tạo một dự án mới hoặc chọn sử dụng lại một dự án hiện có.
    • Nếu bạn thấy lỗi về hạn mức dự án, hãy sử dụng lại một dự án hiện có hoặc xoá một dự án hiện có để tạo một dự án mới.

3. Mở Trình chỉnh sửa Cloud Shell

  1. Nhấp vào đường liên kết này để chuyển trực tiếp đến Trình chỉnh sửa Cloud Shell
  2. Nếu được nhắc uỷ quyền vào bất kỳ thời điểm nào trong ngày hôm nay, hãy nhấp vào Uỷ quyền để tiếp tục. Nhấp để uỷ quyền cho Cloud Shell
  3. Nếu thiết bị đầu cuối không xuất hiện ở cuối màn hình, hãy mở thiết bị đầu cuối:
    • Nhấp vào Xem
    • Nhấp vào Thiết bị đầu cuốiMở cửa sổ dòng lệnh mới trong Trình chỉnh sửa Cloud Shell
  4. Trong thiết bị đầu cuối, hãy đặt dự án của bạn bằng lệnh này:
    • Định dạng:
      gcloud config set project [PROJECT_ID]
      
    • Ví dụ:
      gcloud config set project lab-project-id-example
      
    • Nếu bạn không nhớ mã dự án:
      • Bạn có thể liệt kê tất cả mã dự án bằng:
        gcloud projects list | awk '/PROJECT_ID/{print $2}'
        
      Đặt mã dự án trong thiết bị đầu cuối Cloud Shell Editor
  5. Bạn sẽ thấy thông báo này:
    Updated property [core/project].
    
    Nếu bạn thấy WARNING và được hỏi Do you want to continue (Y/n)?, thì có thể bạn đã nhập sai mã dự án. Nhấn n, nhấn Enter rồi thử chạy lại lệnh gcloud config set project.
  1. Đặt biến môi trường GOOGLE_CLOUD_PROJECT
    export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)
    

4. Bật API

Trong thiết bị đầu cuối, hãy bật các API:

gcloud services enable \
  run.googleapis.com \
  aiplatform.googleapis.com \
  cloudresourcemanager.googleapis.com \
  iap.googleapis.com

Nếu được nhắc uỷ quyền, hãy nhấp vào Uỷ quyền để tiếp tục. Nhấp để uỷ quyền cho Cloud Shell

Lệnh này có thể mất vài phút để hoàn tất, nhưng cuối cùng sẽ tạo ra một thông báo thành công tương tự như thông báo này:

Operation "operations/acf.p2-73d90d00-47ee-447a-b600" finished successfully.

5. Chuẩn bị dự án Node.js

  1. Tạo một thư mục có tên là gen-ui-on-cloudrun để lưu trữ mã nguồn cho quá trình triển khai:
    mkdir gen-ui-on-cloudrun && cd gen-ui-on-cloudrun
    
  2. Khởi chạy một dự án Node.js:
    npm init -y
    
  3. Định cấu hình dự án để sử dụng các mô-đun ES và xác định một tập lệnh bắt đầu bằng cách chạy các lệnh sau:
    npm pkg set type="module"
    
  4. Cài đặt fastify cho máy chủ web và @google/genai cho Vertex AI SDK:
    npm install fastify @google/genai
    

6. Tạo mã xử lý ứng dụng

  1. Tạo và mở một tệp index.ts mới cho mã nguồn ứng dụng:
    cloudshell edit ~/gen-ui-on-cloudrun/index.ts
    
    Lệnh cloudshell edit sẽ mở tệp index.ts trong trình chỉnh sửa phía trên thiết bị đầu cuối.
  2. Thêm mã nguồn máy chủ giao diện người dùng tạo sinh sau đây vào tệp index.ts:
    import fastifyLib from 'fastify';
    import { GoogleGenAI } from '@google/genai';
    
    const fastify = fastifyLib({ logger: true });
    
    const ai = new GoogleGenAI({
        vertexai: true,
        project: process.env.GOOGLE_CLOUD_PROJECT,
        location: process.env.GOOGLE_CLOUD_LOCATION || 'europe-west4',
    });
    
    const SYSTEM_INSTRUCTION = `The user should have submitted an html page and the id of the element just clicked.
    Given the next page description, create a new webpage with a link back to "Start Over" (the / route), a brief overview of the topic, and a list of clickable link elements related to the page.
    When an element is clicked, the webpage should link to the base route / with the nextPageDescription as a query string parameter.
    All information needed to generate the next page should be included in the nextPageDescription without additional context.
    Each nextPageDescription should be less than 1500 characters.
    
    Example:
    If the current HTML page is for a small pet store, it might include a link to an "About" page.
    The href for the about page link should be /?nextPageDescription=about%20page%20for%20small%20pet%20store%20website
    
    All responses should be valid HTML without markdown backticks.`;
    
    interface QueryParams {
        nextPageDescription?: string;
    }
    
    fastify.get<{ Querystring: QueryParams }>('/', async (request, reply) => {
        const {
            nextPageDescription = 'A web page with interesting fun facts where I can select a fact to learn more about that topic.'
        } = request.query;
    
        try {
            const response = await ai.models.generateContent({
                model: 'gemini-2.5-flash',
                contents: nextPageDescription,
                config: {
                    systemInstruction: SYSTEM_INSTRUCTION,
                    temperature: 0.9,
                }
            });
    
            reply.type('text/html; charset=utf-8').send(response.text);
        } catch (error: any) {
            request.log.error(error);
            reply.status(500).send('An error occurred calling the AI.');
        }
    });
    
    const start = async () => {
        try {
            await fastify.listen({ port: Number(process.env.PORT) || 8080, host: '0.0.0.0' });
        } catch (err) {
            fastify.log.error(err);
            process.exit(1);
        }
    };
    
    start();
    

Mã này thiết lập một máy chủ web lắng nghe các yêu cầu HTTP GET trên đường dẫn gốc (/). Khi nhận được một yêu cầu, máy chủ sẽ sử dụng tham số truy vấn nextPageDescription (hoặc giá trị mặc định) làm lời nhắc cho mô hình Gemini 2.5 Flash thông qua Vertex AI. SYSTEM_INSTRUCTION hướng dẫn mô hình này trả về một trang HTML chứa các đường liên kết, trong đó mỗi đường liên kết bao gồm một nextPageDescription để tạo trang tiếp theo.

7. Tạo tài khoản dịch vụ

Bạn cần có một tài khoản dịch vụ cho dịch vụ Cloud Run để xác thực bằng Vertex AI API.

  1. Tạo một tài khoản dịch vụ có tên là gen-navigator-sa:
    gcloud iam service-accounts create gen-navigator-sa --display-name="Generative Navigator Service Account"
    
  2. Cấp quyền cho tài khoản dịch vụ sử dụng Vertex AI:
    gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
        --member="serviceAccount:gen-navigator-sa@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com" \
        --role="roles/aiplatform.user"
    

8. Triển khai lên Cloud Run

Bây giờ, hãy triển khai ứng dụng lên Cloud Run trực tiếp từ mã nguồn mà không cần Dockerfile.

  1. Chạy lệnh gcloud để triển khai ứng dụng:
    cd ~/gen-ui-on-cloudrun
    gcloud beta run deploy generative-web-navigator \
        --source . \
        --no-build \
        --base-image=nodejs24 \
        --command="node" \
        --args="index.ts" \
        --region=europe-west4 \
        --no-allow-unauthenticated \
        --iap \
        --service-account="gen-navigator-sa@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com" \
        --set-env-vars GOOGLE_CLOUD_PROJECT="$GOOGLE_CLOUD_PROJECT",GOOGLE_CLOUD_LOCATION="europe-west4"
    
    Chúng tôi sử dụng một vài cờ quan trọng ở đây:
    • --source . --no-build --base-image=nodejs24: Cờ này cho Cloud Run biết để triển khai mã nguồn từ thư mục hiện tại, bỏ qua giai đoạn xây dựng và chạy ứng dụng bằng hình ảnh cơ sở Node.js 24 được tạo sẵn.
    • --no-allow-unauthenticated: Cờ này đảm bảo rằng chỉ những người dùng đã xác thực mới có thể truy cập vào dịch vụ.
    • --iap: Cờ này bật Identity-Aware Proxy (IAP) để quản lý quyền truy cập vào ứng dụng của bạn. IAP cho phép bạn kiểm soát quyền truy cập dựa trên danh tính và bối cảnh của người dùng, thay vì chỉ dựa trên địa chỉ IP.
  2. Sau vài phút, bạn sẽ thấy một thông báo như:
    Service [generative-web-navigator] revision [generative-web-navigator-12345-abc] has been deployed and is serving 100 percent of traffic.
    

Bạn đã triển khai ứng dụng, nhưng vẫn cần định cấu hình IAP để cho phép truy cập.

9. Định cấu hình quyền truy cập IAP

Khi bạn bật IAP trên Cloud Run, IAP sẽ chặn tất cả các yêu cầu và yêu cầu người dùng xác thực và được uỷ quyền trước khi có thể truy cập vào dịch vụ của bạn. Để tính năng này hoạt động, bạn cần cấp 2 quyền:

  • Cho phép chính dịch vụ IAP gọi dịch vụ Cloud Run của bạn.
  • Cho phép chính bạn (hoặc những người dùng/nhóm khác) truy cập vào ứng dụng thông qua IAP.
  1. Lấy số dự án của bạn (cần có để xác định tác nhân dịch vụ IAP):
    export PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format="value(projectNumber)")
    
  2. Cấp cho tác nhân dịch vụ IAP vai trò roles/run.invoker trên dịch vụ Cloud Run của bạn. Điều này cho phép IAP gọi dịch vụ của bạn sau khi xác thực và uỷ quyền cho người dùng.
    gcloud run services add-iam-policy-binding generative-web-navigator \
        --region=europe-west4 \
        --member="serviceAccount:service-$PROJECT_NUMBER@gcp-sa-iap.iam.gserviceaccount.com" \
        --role="roles/run.invoker"
    
  3. Cấp cho tài khoản người dùng của bạn vai trò roles/iap.httpsResourceAccessor. Điều này cho phép bạn truy cập vào các tài nguyên HTTPS được bảo mật bằng IAP.
    gcloud beta iap web add-iam-policy-binding \
        --resource-type=cloud-run \
        --region=europe-west4 \
        --service=generative-web-navigator \
        --member="user:$(gcloud config get-value account)" \
        --role="roles/iap.httpsResourceAccessor"
    

10. Kiểm thử ứng dụng

  1. Lấy URL của dịch vụ đã triển khai:
    gcloud run services describe generative-web-navigator --format='value(status.url)' --region=europe-west4
    
  2. Sao chép URL rồi mở URL đó trong trình duyệt web. Vì dịch vụ được bảo mật bằng IAP, nên bạn sẽ được nhắc đăng nhập bằng Tài khoản Google nếu chưa đăng nhập. Sau khi xác thực, bạn sẽ thấy trang đầu tiên được tạo tự động.
  3. Nhấp vào bất kỳ đường liên kết nào để chuyển đến một trang mới. Trang này sẽ được AI tạo dựa trên đường liên kết mà bạn đã nhấp!

Bạn đã hoàn tất! Bạn đã triển khai thành công một trang web giao diện người dùng tạo sinh lên Cloud Run và bảo mật trang web đó bằng IAP.

11. Kết luận

Xin chúc mừng! Bạn đã triển khai và bảo mật thành công một trang web giao diện người dùng tạo sinh bằng Cloud Run, Vertex AI và IAP.

(Không bắt buộc) Dọn dẹp

Nếu muốn dọn dẹp những gì bạn đã tạo, bạn có thể xoá dự án trên đám mây để tránh phát sinh thêm phí.

Mặc dù Cloud Run không tính phí khi dịch vụ không được sử dụng, nhưng bạn vẫn có thể bị tính phí lưu trữ các cấu phần phần mềm bản dựng nếu có. Việc xoá dự án trên đám mây sẽ dừng tính phí cho tất cả các tài nguyên được sử dụng trong dự án đó.

Nếu muốn, hãy xoá dự án:

gcloud projects delete $GOOGLE_CLOUD_PROJECT

Bạn cũng có thể muốn xoá các tài nguyên không cần thiết khỏi đĩa cloudshell. Bạn có thể:

  1. Xoá thư mục dự án lớp học lập trình:
    rm -rf ~/gen-ui-on-cloudrun
    
  2. Cảnh báo! Bạn không thể hoàn tác hành động tiếp theo này! Nếu muốn xoá mọi thứ trên Cloud Shell để giải phóng dung lượng, bạn có thể xoá toàn bộ thư mục chính. Hãy cẩn thận để đảm bảo rằng mọi thứ bạn muốn giữ lại đều được lưu ở nơi khác.
    sudo rm -rf $HOME