跳到主要內容

如何將 Deno 部署到 Digital Ocean

Digital Ocean 是一個熱門的雲端基礎架構供應商,提供各種代管服務,從網路、運算到儲存。

以下提供逐步指南,說明如何使用 Docker 和 GitHub Actions 將 Deno 應用程式部署到 Digital Ocean。

先決條件是

建立 Dockerfile 和 docker-compose.yml

為了專注於部署,我們的應用程式只會是一個傳回字串作為 HTTP 回應的 main.ts 檔案

import { Application } from "https://deno.land/x/oak/mod.ts";

const app = new Application();

app.use((ctx) => {
ctx.response.body = "Hello from Deno and Digital Ocean!";
});

await app.listen({ port: 8000 });

接下來,我們將建立兩個檔案 -- Dockerfiledocker-compose.yml -- 來建立 Docker 映像。

在我們的 Dockerfile 中,讓我們加入

FROM denoland/deno

EXPOSE 8000

WORKDIR /app

ADD . /app

RUN deno cache main.ts

CMD ["run", "--allow-net", "main.ts"]

然後,在我們的 docker-compose.yml

version: '3'

services:
web:
build: .
container_name: deno-container
image: deno-image
ports:
- "8000:8000"

讓我們透過執行 docker compose -f docker-compose.yml build,然後 docker compose up,並前往 localhost:8000 來在本地測試這項功能。

Hello from localhost

它運作了!

建立、標籤和推播您的 Docker 映像至 Digital Ocean Container Registry

Digital Ocean 有其自己的私人 Container Registry,我們可以用它來推播和拉取 Docker 映像。為了使用這個註冊表,讓我們 在命令列安裝和驗證 doctl

在那之後,我們將建立一個名為 deno-on-digital-ocean 的新私人註冊表

doctl registry create deno-on-digital-ocean

使用我們的 Dockerfile 和 docker-compose.yml,我們將建立一個新映像,標籤它,並將它推播至註冊表。請注意,docker-compose.yml 將在本地將建立命名為 deno-image

docker compose -f docker-compose.yml build

讓我們使用 new 標籤

docker tag deno-image registry.digitalocean.com/deno-on-digital-ocean/deno-image:new

現在我們可以將它推播至註冊表。

docker push registry.digitalocean.com/deno-on-digital-ocean/deno-image:new

您應該會在 Digital Ocean 容器登錄 中的 new 標籤看到新的 deno-image

New deno image on Digital Ocean container registry

完美!

透過 SSH 部署到 Digital Ocean

我們的 deno-image 在登錄中後,我們可以使用 docker run 在任何地方執行它。在這個情況下,我們會在 Digital Ocean Droplet(他們託管的虛擬機器)中執行它。

在您的 Droplet 頁面 中,按一下您的 Droplet,然後按一下 主控台 以透過 SSH 連線到虛擬機器。(或者您可以 直接從您的命令列透過 ssh 連線。)

若要拉下 deno-image 映像並執行它,我們執行

docker run -d --restart always -it -p 8000:8000 --name deno-image registry.digitalocean.com/deno-on-digital-ocean/deno-image:new

使用我們的瀏覽器前往 Digital Ocean 地址,我們現在會看到

Hello from Deno and Digital Ocean

完成!

透過 GitHub Actions 自動化部署

讓我們使用 GitHub Actions 自動化整個流程。

首先,讓我們取得登入 doctl 和透過 SSH 連線到 Droplet 所需的所有環境變數

  • DIGITALOCEAN_ACCESS_TOKEN
  • DIGITALOCEAN_HOST(您的 Droplet 的 IP 位址)
  • DIGITALOCEAN_USERNAME(預設為 root
  • DIGITALOCEAN_SSHKEY(下方有更多說明)

產生 DIGITALOCEAN_SSHKEY

DIGITALOCEAN_SSHKEY 是私密金鑰,其公開金鑰對應存在於虛擬機器中的 ~/.ssh/authorized_keys 檔案中。

若要執行此動作,首先讓我們在您的本機機器上執行 ssh-keygen

ssh-keygen

當提示輸入電子郵件時,務必使用您的 GitHub 電子郵件,以便 GitHub Action 正確驗證。您的最終輸出應該類似於以下內容

Output
Your identification has been saved in /your_home/.ssh/id_rsa
Your public key has been saved in /your_home/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:/hk7MJ5n5aiqdfTVUZr+2Qt+qCiS7BIm5Iv0dxrc3ks user@host
The key's randomart image is:
+---[RSA 3072]----+
| .|
| + |
| + |
| . o . |
|o S . o |
| + o. .oo. .. .o|
|o = oooooEo+ ...o|
|.. o *o+=.*+o....|
| =+=ooB=o.... |
+----[SHA256]-----+

接下來,我們必須將新產生的公開金鑰上傳到您的 Droplet。您可以使用 ssh-copy-id 或手動複製它,ssh 進入您的 Droplet,並將它貼到 ~/.ssh/authorized_keys

使用 ssh-copy-id

ssh-copy-id {{ username }}@{{ host }}

此命令會提示您輸入密碼。請注意,這會自動從您的本機複製 id_rsa.pub 金鑰,並將它貼到您的 Droplet 的 ~/.ssh/authorized_keys 檔案。如果您將金鑰命名為 id_rsa 以外的名稱,您可以使用 -i 旗標將它傳遞給命令

ssh-copy-id -i ~/.ssh/mykey {{ username }}@{{ host }}

要測試是否成功完成

ssh -i ~/.ssh/mykey {{ username }}@{{ host }}

太棒了!

定義 yml 檔案

最後一步是將所有這些整合在一起。我們基本上會在手動部署期間執行每個步驟,並將它們新增到 GitHub Actions 工作流程 yml 檔案

name: Deploy to Digital Ocean

on:
push:
branches:
- main

env:
REGISTRY: "registry.digitalocean.com/deno-on-digital-ocean"
IMAGE_NAME: "deno-image"

jobs:
build_and_push:
name: Build, Push, and Deploy
runs-on: ubuntu-latest
steps:
- name: Checkout main
uses: actions/checkout@v2

- name: Set $TAG from shortened sha
run: echo "TAG=`echo ${GITHUB_SHA} | cut -c1-8`" >> $GITHUB_ENV

- name: Build container image
run: docker compose -f docker-compose.yml build

- name: Tag container image
run: docker tag ${{ env.IMAGE_NAME }} ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.TAG }}

- name: Install `doctl`
uses: digitalocean/action-doctl@v2
with:
token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}

- name: Log in to Digital Ocean Container Registry
run: doctl registry login --expiry-seconds 600

- name: Push image to Digital Ocean Container Registry
run: docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.TAG }}

- name: Deploy via SSH
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.DIGITALOCEAN_HOST }}
username: ${{ secrets.DIGITALOCEAN_USERNAME }}
key: ${{ secrets.DIGITALOCEAN_SSHKEY }}
script: |
# Login to Digital Ocean Container Registry
docker login -u ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }} -p ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }} registry.digitalocean.com
# Stop and remove a running image.
docker stop ${{ env.IMAGE_NAME }}
docker rm ${{ env.IMAGE_NAME }}
# Run a new container from a new image
docker run -d --restart always -it -p 8000:8000 --name ${{ env.IMAGE_NAME }} ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.TAG }}

當您推送到 GitHub 時,此 yml 檔案會自動偵測,觸發部署動作。