如何使用 Vultr Kubernetes 引擎和 Vultr 負載均衡器部署 Next.js 應用程序

介紹

Next.js 是一個流行的 React 框架,用於開發靜態網站和現代 Web 應用程序。 Next.js 應用程序通常部署在無服務器平台上。 但是,您希望在受控服務器上實施一些方案並跨基礎架構進行擴展。 本教程介紹瞭如何在 Vultr Kubernetes Engine 上部署全棧 Next.js 應用程序。 示例 該應用程序使用 Next.js 構建,並使用 Prisma 連接到 MySQL 數據庫。

以下是這種方法的一些優點:

  • 將 Next.js 應用程序部署到盡可能靠近數據庫的位置。
  • 避免無服務器方法中的冷啟動問題。
  • 與無服務器平台相比,可預測的雲服務器定價和帶寬。

本教程分為三個獨立的部分:

  • 第 1 部分:構建 Docker 映像並將其推送到 Docker Hub 映像註冊表
  • 第 2 部分:使用 Vultr Kubernetes Engine 部署和擴展 Next.js 應用程序
  • 第 3 部分:使用安全 SSL 證書公開 Next.js 應用程序

以前的要求

在開始之前,您必須:

  • 有一個外部 MySQL 數據庫
  • 實施一個Vultr Kubernetes 集群至少有 3 個節點。
  • 設置 kubectl git 在你的機器上。
  • 在你的機器上安裝 Docker
  • 註冊一個 Docker Hub 賬戶來存儲 Docker 鏡像

第 1 部分:構建 Docker 映像並將其推送到 Docker Hub 映像註冊表

本教程中使用的 Next.js 應用程序是一個完整的堆棧應用程序,名為 next-short-urls . 此應用程序的源代碼可在以下位置找到這個存儲庫. Vultr 還在這裡存檔了存儲庫。

這是一個使用 Next.js、TypeScript 和 Prisma 構建的簡單 URL 縮短器。 Prisma 是一個開源 ORM,可幫助您創建和管理 MySQL 數據庫。

  1. 克隆示例請求的源代碼:

                              
                                $ git clone -b v1.10.0 https://github.com/quanhua92/next-short-urls
    
                              
                            
  2. 準備一個 .env 具有以下內容的文件環境。 東方 .env 該文件在 Docker 映像構建階段用於生成靜態頁面。 最終的生產 Docker 映像不包含在此文件中。

                              
                                DATABASE_URL="DATABASE_URL_HERE"
    SECRET_COOKIE_PASSWORD="SOME_SECRET_PASSWORD_WITH_MIN_LENGTH_32"
    AWAIT_HISTORY_UPDATE="0"
    
                              
                            

    以下是對內容的簡要說明 .env 訴訟程序:

    • DATABASE_URL 是一個數據庫連接字符串,以 mysql://
    • SECRET_COOKIE_PASSWORD 是應用程序指定的密碼,最小長度為 32
    • AWAIT_HISTORY_UPDATE 它是應用程序所需的環境變量。
  3. 確保 DockerFile 該文件包含以下內容。 這是一個多階段的 DockerFile deps , builder runner 階段

                              
                                # Install dependencies only when needed
    FROM node:16-alpine AS deps
    # Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
    RUN apk add --no-cache libc6-compat
    WORKDIR /app
    
    COPY package.json yarn.lock ./
    RUN yarn install --frozen-lockfile
    
    # If using npm with a `package-lock.json` comment out above and use below instead
    # COPY package.json package-lock.json / 
    # RUN npm install
    
    # Rebuild the source code only when needed
    FROM node:16-alpine AS builder
    WORKDIR /app
    COPY --from=deps /app/node_modules ./node_modules
    COPY . .
    # generate the prisma type
    RUN npx prisma generate
    
    RUN yarn build && yarn install --production --ignore-scripts --prefer-offline
    # Production image, copy all the files and run next
    FROM node:16-alpine AS runner
    WORKDIR /app
    
    ENV NODE_ENV production
    
    RUN addgroup -g 1001 -S nodejs
    RUN adduser -S nextjs -u 1001
    
    # Prepare the cache folder for next/image
    RUN mkdir -p /app/.next/cache/images && chown nextjs:nodejs /app/.next/cache/images
    VOLUME /app/.next/cache/images
    
    # You only need to copy next.config.js if you are NOT using the default configuration
    COPY --from=builder /app/next.config.js ./
    COPY --from=builder /app/public ./public
    COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next
    COPY --from=builder /app/package.json ./package.json
    COPY --from=builder /app/node_modules ./node_modules
    
    USER nextjs
    
    EXPOSE 3000
    
    ENV PORT 3000
    
    # Next.js collects completely anonymous telemetry data about general usage.
    # Learn more here: https://nextjs.org/telemetry
    # Uncomment the following line in case you want to disable telemetry.
    # ENV NEXT_TELEMETRY_DISABLED 1
    CMD ["node_modules/.bin/next", "start"]
    
                              
                            

    以下是為 next-short-urls 要求。 在建造者階段, RUN npx prisma generate 從 Prisma 模式生成類型。 在走廊階段,製作一個文件夾。 /app/.next/cache/images 並準備文件夾權限。 這用於 Next.js 中的自動圖像優化功能。

  4. 創建 Docker 鏡像

                              
                                $ docker build . -t next-short-urls
    
                              
                            
  5. 登錄 Docker 中心

                              
                                $ docker login
    
                              
                            
  6. 使用您的 Docker Hub ID 標記 Docker 映像並將其推送到 Docker Hub。 代替 <YOUR_DOCKER_HUB_ID> 使用您的 Docker Hub 帳戶 ID。

                              
                                $ docker tag next-short-urls <YOUR_DOCKER_HUB_ID>/next-short-urls:latest
    $ docker push <YOUR_DOCKER_HUB_ID>/next-short-urls:latest
    
                              
                            
  7. 運行本地 Docker 以驗證 Docker 映像。 導航https://localhost:3000訪問應用程序

                              
                                $ docker run --rm -p 3000:3000 <YOUR_DOCKER_HUB_ID>/next-short-urls
    
                              
                            
  8. (可選)轉到您的 Docker Hub 儀表板並確保您的映像是私有的。

第 2 部分:使用 Vultr Kubernetes Engine 部署和擴展 Next.js 應用程序

在這一部分中,您將創建一個包含 Docker Hub 憑據的密鑰,並創建一個部署來部署一些運行 Next.js 應用程序的 pod。

  1. 創建 Docker Hub 機密名稱 regcred . 將命令中的參數替換為您的 Docker Hub 憑據

                              
                                $ kubectl create secret docker-registry regcred 
        --docker-username=YOUR_DOCKER_HUB_USERNAME  
        --docker-password=YOUR_DOCKER_HUB_PASSWORD 
        --docker-email=YOUR_DOCKER_HUB_EMAIL
    
                              
                            
  2. 創建一個秘密清單文件 secrets.yaml 使用上面創建的數據 .env .

                              
                                apiVersion: v1
    kind: Secret
    metadata:
      name: next-short-urls-secrets
      namespace: default
    type: Opaque
    stringData:
      DATABASE_URL: "DATABASE_URL_HERE"
      SECRET_COOKIE_PASSWORD: "SOME_SECRET_PASSWORD_WITH_MIN_LENGTH_32"
      AWAIT_HISTORY_UPDATE: "0"
    
                              
                            
  3. 運行命令以創建密鑰。

                              
                                $ kubectl apply -f secrets.yaml
    
                              
                            
  4. 創建部署文件 deployment.yaml 與以下內容。 代替 <YOUR_DOCKER_HUB_ID> 使用您的 Docker Hub 帳戶 ID。

                              
                                apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: next-short-urls-deploy
    spec:
      replicas: 3
      selector:
        matchLabels:
          name: next-short-urls-app
      template:
        metadata:
          labels:
            name: next-short-urls-app
        spec:
          imagePullSecrets:
            - name: regcred
          containers:
            - name: next-short-urls
              image: <YOUR_DOCKER_HUB_ID>/next-short-urls:latest
              imagePullPolicy: Always
              ports:
                - containerPort: 3000
              envFrom:
              - secretRef:
                  name: next-short-urls-secrets
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: next-short-urls-service
    spec:
      ports:
        - name: http
          port: 80
          protocol: TCP
          targetPort: 3000
      selector:
        name: next-short-urls-app
    
                              
                            
  5. 運行命令以創建部署和服務。

                              
                                $ kubectl apply -f deployment.yaml
    
                              
                            
  6. 運行命令 kubectl get pods 查看新創建的 pod。 結果應該類似於:

                              
                                NAME                                      READY   STATUS    RESTARTS   AGE
    next-short-urls-deploy-764d658d49-26b5w   1/1     Running   0          62s
    next-short-urls-deploy-764d658d49-hql7q   1/1     Running   0          62s
    next-short-urls-deploy-764d658d49-nv6tr   1/1     Running   0          62s
    
                              
                            
  7. 運行命令 kubectl get services 查看新創建的服務。 結果應該類似於:

                              
                                NAME                      TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
    kubernetes                ClusterIP   10.96.0.1      <none>        443/TCP   94m
    next-short-urls-service   ClusterIP   10.99.247.34   <none>        80/TCP    39s
    
                              
                            
  8. 使用以下命令將您的應用擴展到 10 個副本。

                              
                                $ kubectl scale --replicas=10 deployment/next-short-urls-deploy
    
                              
                            
  9. 運行命令 kubectl get pods 查看新創建的 pod。 結果應該類似於:

                              
                                NAME                                      READY   STATUS    RESTARTS   AGE
    next-short-urls-deploy-764d658d49-26b5w   1/1     Running   0          3m
    next-short-urls-deploy-764d658d49-5r25t   1/1     Running   0          25s
    next-short-urls-deploy-764d658d49-hql7q   1/1     Running   0          3m
    next-short-urls-deploy-764d658d49-j6qlf   1/1     Running   0          25s
    next-short-urls-deploy-764d658d49-lvrgp   1/1     Running   0          25s
    next-short-urls-deploy-764d658d49-nv6tr   1/1     Running   0          3m
    next-short-urls-deploy-764d658d49-vkl98   1/1     Running   0          25s
    next-short-urls-deploy-764d658d49-wkclv   1/1     Running   0          25s
    next-short-urls-deploy-764d658d49-xgzs6   1/1     Running   0          25s
    next-short-urls-deploy-764d658d49-zhcdj   1/1     Running   0          25s
    
                              
                            
  10. 進行端口轉發以通過服務訪問您的應用程序。 導航https://localhost:8080訪問您的應用程序。

                              
                                $ kubectl port-forward services/next-short-urls-service 8080:80
    
                              
                            

您已在 Vultr Kubernetes Engine 上成功部署了帶有 MySQL 數據庫的 Next.js 應用程序,集群中有 10 個副本。

第 3 部分:使用安全 SSL 證書公開 Next.js 應用程序

在這一部分中,您將安裝 NGINX 入口控制器並通過具有安全 SSL 證書的域名公開您的應用程序。

  1. 安裝 ingress-nginx .

                              
                                $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.1/deploy/static/provider/cloud/deploy.yaml 
    
                              
                            
  2. 轉到您的負載均衡器儀表板,網址為https://my.vultr.com/loadbalancers/並獲取新創建的負載均衡器的 IP 地址。 這是為 NGINX 入口構建的負載均衡器。

  3. 在您的域的 DNS 中創建一條指向上述 IP 地址的 A 記錄。

  4. 安裝 cert-manager 管理 SSL 證書

                              
                                $ kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.7.0/cert-manager.yaml
    
                              
                            
  5. 創建清單文件 letsencrypt.yaml 處理 Let's Encrypt 證書。 代替 使用您的真實電子郵件。

                              
                                apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: letsencrypt-staging
    spec:
      acme:
        # The ACME server URL
        server: https://acme-staging-v02.api.letsencrypt.org/directory
        preferredChain: "ISRG Root X1"
        # Email address used for ACME registration
        email: <YOUR_EMAIL>
        # Name of a secret used to store the ACME account private key
        privateKeySecretRef:
          name: letsencrypt-staging
        solvers:
          - http01:
              ingress:
                class: nginx
    ---
    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: letsencrypt-prod
    spec:
      acme:
        # The ACME server URL
        server: https://acme-v02.api.letsencrypt.org/directory
        # Email address used for ACME registration
        email: <YOUR_EMAIL>
        # Name of a secret used to store the ACME account private key
        privateKeySecretRef:
          name: letsencrypt-prod
        solvers:
          - http01:
              ingress:
                class: nginx
    
                              
                            
  6. 運行命令安裝以前的 Let's Encrypt 發行者。

                              
                                $ kubectl apply -f letsencrypt.yaml
    
                              
                            
  7. 創建登錄清單文件 ingress.yaml 與以下內容。 替換 與您在上一步中在 A 記錄中創建的域。

                              
                                apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: next-short-urls-ingress
      annotations:
        kubernetes.io/ingress.class: nginx
        cert-manager.io/cluster-issuer: letsencrypt-prod
    spec:
      tls:
        - secretName: next-short-urls-tls
          hosts:
            - <YOUR_DOMAIN>
      rules:
        - host: <YOUR_DOMAIN>
          http:
            paths:
              - path: /
                pathType: Prefix
                backend:
                  service:
                    name: next-short-urls-service
                    port:
                      number: 80
    
                              
                            
  8. 運行命令以創建條目。

                              
                                $ kubectl apply -f ingress.yaml
    
                              
                            
  9. 運行命令 kubectl get ingress 查看新創建的條目。 結果應該類似於:

                              
                                NAME                      CLASS    HOSTS               ADDRESS        PORTS     AGE
    next-short-urls-ingress   <none>   <YOUR_DOMAIN>      140.82.41.69   80, 443   37s
    
                              
                            
  10. 導航 https://<YOUR_DOMAIN 訪問您的應用程序。

更多信息

文章標題 名稱(可選) 電子郵件(可選) 描述

發送建議

相關文章