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 lớp học thực hành 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ằng các mô hình ngôn ngữ lớn của 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ượt nhấp sẽ tạo ra 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ẽ tạo ứng dụng này bằng Node.js và Fastify, sử dụng Vertex AI SDK để gọi Gemini, triển khai ứng dụng 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 ứng dụng 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 trường học hoặc tài khoản do nơi làm việc cấp. Tài khoản do nơi làm việc hoặc trường học cấp có thể có các hạn chế khiến bạn không bật được những API cần thiết cho lớp học 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 bài tập thực hành này sẽ tốn ít hơn 1 USD cho các tài nguyên trên đám mây.
    • Bạn có thể làm theo các bước ở cuối bài thực hành 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í trị giá 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 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 Cloud Shell Editor
  2. Nếu được nhắc uỷ quyền vào bất kỳ thời điểm nào trong 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 Terminal (Thiết bị đầu cuối)Mở 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 thiết lập dự án bằng lệnh sau:
    • Đị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 của mình, hãy làm như sau:
      • Bạn có thể liệt kê tất cả mã dự án bằng cách sử dụ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 sau:
    Updated property [core/project].
    
    Nếu thấy biểu tượng WARNING và được yêu cầu 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 dòng lệnh, 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 khởi động 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 cửa sổ dòng lệnh.
  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-west1',
    });
    
    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();
    

Đoạn mã này thiết lập một máy chủ web để nhận các yêu cầu HTTP GET trên đường dẫn gốc (/). Khi nhận được 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 câu lệnh cho mô hình Gemini 2.5 Flash thông qua Vertex AI. SYSTEM_INSTRUCTION hướng dẫn mô hình trả về một trang HTML chứa các đường liên kết, trong đó mỗi đường liên kết đều có 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 gen-navigator-sa:
    gcloud iam service-accounts create gen-navigator-sa --display-name="Generative Navigator Service Account"
    
  2. Cấp cho tài khoản dịch vụ quyền 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

Giờ đây, bạn có thể triển khai ứng dụng lên Cloud Run ngay 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-west1 \
        --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-west1"
    
    Chúng ta sử dụng một số cờ quan trọng ở đây:
    • --source . --no-build --base-image=nodejs24: Lệnh này yêu cầu Cloud Run triển khai mã nguồn từ thư mục hiện tại, bỏ qua giai đoạn tạo bản 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: Điều 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: Tuỳ chọn này cho phép 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à ngữ 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ư sau:
    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 của mình, nhưng vẫn cần định cấu hình tính năng mua hàng trong ứng dụng để 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 họ 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 bản thân (hoặc 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. Số này là thông tin cần thiết để xác định nhân viên hỗ trợ 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-west1 \
        --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. Nhờ đó, bạn có thể 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-west1 \
        --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-west1
    
  2. Sao chép URL rồi mở trong trình duyệt web. Vì dịch vụ này đượ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 một đường liên kết bất kỳ để chuyển đến một trang mới. Trang này sẽ do AI tạo dựa trên đường liên kết mà bạn đã nhấp vào!

Bạn đã hoàn thành! Bạn đã triển khai thành công một trang web có 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 có 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 nội dung đã tạo, bạn có thể xoá dự án trên đám mây để tránh phát sinh thêm chi 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ó. Khi bạn xoá dự án trên đám mây, hệ thống sẽ ngừng tính phí cho tất cả tài nguyên được 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 của lớp học lập trình:
    rm -rf ~/gen-ui-on-cloudrun
    
  2. Cảnh báo! Bạn không thể huỷ thao tác tiếp theo này sau khi thực hiện! 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 gốc. 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