檢視原始碼 在 Fly.io 上部署

Fly.io 在此維護其 Elixir/Phoenix 的指南:Fly.io/docs/elixir/getting-started/ 我們會持續維護這個指南,但最新且最棒的資訊請在他們那裡查看!

我們需要

本指南唯一需要的是一個可用的 Phoenix 應用程式。對於需要一個簡單應用程式來部署的人,請遵循執行中指南。

你可以只需

$ mix phx.new my_app

目標

本指南的主要目標是讓 Phoenix 應用程式在Fly.io上執行。

部分

讓我們將此程序分為幾個步驟,以便我們可以追蹤進度。

  • 安裝 Fly.io CLI
  • 註冊 Fly.io
  • 部署應用程式到 Fly.io
  • 其他 Fly.io 技巧
  • 有用的 Fly.io 資源

安裝 Fly.io CLI

遵循此處的指示,安裝 Flyctl,這個是 Fly.io 平臺的命令列介面。

註冊 Fly.io

我們可以用 CLI 註冊帳戶

$ fly auth signup

或登入。

$ flyctl auth login

Fly 針對大多數應用程式提供免費層級。設定帳戶時需要信用卡,以防濫用。請參閱定價頁面以獲得更多資訊。

部署應用程式到 Fly.io

若要告訴 Fly 你的應用程式,請在你的 source code 目錄中執行fly launch。這將建立並設定一個 Fly.io 應用程式。

$ fly launch

這會掃描你的 source code,偵測 Phoenix 專案,並為你執行mix phx.gen.release --docker!這會為你建立一個 Dockerfile。

fly launch 指令會帶你瀏覽幾個問題。

  • 你可以替應用程式命名,或讓它為你產生一個隨機名稱。
  • 選擇一個組織(預設為personal)。組織是可以讓多個 Fly.io 使用者分享應用程式和資源的方式。
  • 選擇部署區域。預設為最靠近的 Fly.io 區域。您可以在此查看完整區域清單
  • 為您設定 Postgres 資料庫。
  • 建構 Dockerfile。
  • 部署您的應用程式!

fly launch 指令也會為您建立一個 fly.toml 檔案。您可以在這裡設定環境變數值和其他設定。

將機密儲存在 Fly.io

您可能也有一些機密需要設定在您的應用程式中。

使用 fly secrets 來設定這些機密。

$ fly secrets set MY_SECRET_KEY=my_secret_value

再次部署

當您要將變更部署到您的應用程式時,請使用 fly deploy

$ fly deploy

請注意:在 Apple Silicon (M1) 電腦上,docker 會使用 qemu 執行跨平台建置,這可能無法隨時運作。如果您收到類似以下的分段錯誤

 => [build  7/17] RUN mix deps.get --only
 => => # qemu: uncaught target signal 11 (Segmentation fault) - core dumped

您可以透過加入 --remote-only 旗標使用 Fly 的遠端建置器。

$ fly deploy --remote-only

您可以隨時查看部署狀態。

$ fly status

查看您的應用程式記錄。

$ fly logs

如果一切正常,請在 Fly 上開啟您的應用程式。

$ fly open

其他 Fly.io 訣竅

取得執行中節點中的 IEx shell

Elixir 支援取得執行中生產節點中的 IEx shell。

有一些必備條件,我們首先需要在 Fly.io 上建立一個SSH Shell存取我們的機器。

此步驟會為您的帳戶設定一個根憑證,然後發出憑證。

$ fly ssh issue --agent

設定 SSH 後,讓我們打開一個主控台。

$ fly ssh console
Connecting to my-app-1234.internal... complete
/ #

如果一切都順利,那麼您就可以使用 shell 存取機器!現在我們只需要啟動我們的遠端 IEx shell。部署 Dockerfile 被設定為將我們的應用程式拉取到 /app。所以名為 my_app 的應用程式的指令如下所示

$ app/bin/my_app remote
Erlang/OTP 23 [erts-11.2.1] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:1]

Interactive Elixir (1.11.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(my_app@fdaa:0:1da8:a7b:ac4:b204:7e29:2)1>

現在我們有一個執行的 IEx shell 可以存取我們的節點!您可以使用 CTRL+C、CTRL+C 安全地斷線。

將您的應用程式進行叢集

Elixir 和 BEAM 具有驚人的能力可以相互叢集,並在節點間無縫傳遞訊息。本指南的這一部分將帶您逐步叢集您的 Elixir 應用程式。

要在 Fly.io 上快速設定叢集,有 2 部分。

  • 安裝和使用 libcluster
  • 將應用程式擴充到多個執行個體

加入 libcluster

廣泛採用的函式庫 libcluster 在此有所幫助。

有許多策略可供 libcluster 尋找並與其他節點連線。我們在 Fly.io 上採用的策略是 DNSPoll

安裝好 libcluster 後,像這樣將它加入應用程式

defmodule MyApp.Application do
  use Application

  def start(_type, _args) do
    topologies = Application.get_env(:libcluster, :topologies) || []

    children = [
      # ...
      # setup for clustering
      {Cluster.Supervisor, [topologies, [name: MyApp.ClusterSupervisor]]}
    ]

    # ...
  end

  # ...
end

接下來,我們將將 topologies 組態設為 config/runtime.exs

  app_name =
    System.get_env("FLY_APP_NAME") ||
      raise "FLY_APP_NAME not available"

  config :libcluster,
    topologies: [
      fly6pn: [
        strategy: Cluster.Strategy.DNSPoll,
        config: [
          polling_interval: 5_000,
          query: "#{app_name}.internal",
          node_basename: app_name
        ]
      ]
    ]

此組態將設定 libcluster 使用 DNSPoll 策略,並利用 .internal 私密網路尋找使用 $FLY_APP_NAME 的其他已部署應用程式。

控制節點的名稱

我們需要控制 Elixir 節點的命名。為了幫助它們連線,我們會利用此模式命名:your-fly-app-name@the.ipv6.address.on.fly。为此,我們將產生釋出組態。

$ mix release.init

接著編輯產生的 rel/env.sh.eex 檔案,並加入以下各行

ip=$(grep fly-local-6pn /etc/hosts | cut -f 1)
export RELEASE_DISTRIBUTION=name
export RELEASE_NODE=$FLY_APP_NAME@$ip

變更後,部署您的應用程式!

$ fly deploy

若要對應用程式進行叢集,我們必須有數個執行個體。接下來,我們將加入其他節點執行個體。

執行多個執行個體

有兩種執行多個執行個體的方法。

  1. 將我們的應用程式擴充至在一個區域有數個執行個體。
  2. 在其他區域加入執行個體(多個區域)。

首先,讓我們先從我們單一部署的基準線開始。

$ fly status
...
Instances
ID       VERSION REGION DESIRED STATUS  HEALTH CHECKS      RESTARTS CREATED
f9014bf7 26      sea    run     running 1 total, 1 passing 0        1h8m ago

在單一區域擴充

我們在目前區域向上擴充至 2 個執行個體。

$ fly scale count 2
Count changed to 2

檢查狀態,看看產生什麼事。

$ fly status
...
Instances
ID       VERSION REGION DESIRED STATUS  HEALTH CHECKS      RESTARTS CREATED
eb4119d3 27      sea    run     running 1 total, 1 passing 0        39s ago
f9014bf7 27      sea    run     running 1 total, 1 passing 0        1h13m ago

我們現在在同一個區域有兩個執行個體。

確定這些執行個體集中在一起。我們可以檢查記錄檔

$ fly logs
...
app[eb4119d3] sea [info] 21:50:21.924 [info] [libcluster:fly6pn] connected to :"my-app-1234@fdaa:0:1da8:a7b:ac2:f901:4bf7:2"
...

不過,從節點內部來看不會這麼有收穫。使用 IEx shell,我們可以詢問已連線的節點,它還能看見什麼其他節點。

$ fly ssh console -C "/app/bin/my_app remote"
iex(my-app-1234@fdaa:0:1da8:a7b:ac2:f901:4bf7:2)1> Node.list
[:"my-app-1234@fdaa:0:1da8:a7b:ac4:eb41:19d3:2"]

IEx 提示字元會包含在此,有助於顯示我們已連線節點的 IP 位址。接著取得 Node.list 會傳回另一個節點。我們這兩個執行個體連線且集中在一起!

擴充至多個區域

Fly 可輕易將執行個體部署在更靠近使用者的位置。透過 DNS 的魔力,使用者會被導向應用程式所在的最近區域。在此處,您可以深入了解 Fly.io 區域

從我們的基準線開始,單一執行個體在 sea 中執行,這是位於華盛頓州西雅圖的(美國),讓我們加入 ewr 區域,這是位於紐澤西州帕西帕尼(美國)。這使得美國的兩岸都有執行個體。

$ fly regions add ewr
Region Pool:
ewr
sea
Backup Region:
iad
lax
sjc
vin

查看狀態,顯示我們只有 1 個區域,因為我們的計數設為 1。

$ fly status
...
Instances
ID       VERSION REGION DESIRED STATUS  HEALTH CHECKS      RESTARTS CREATED
cdf6c422 29      sea    run     running 1 total, 1 passing 0        58s ago

我們來加入第 2 個執行個體,看看它會部署到 ewr 中。

$ fly scale count 2
Count changed to 2

現在,狀態顯示我們有兩個執行個體分佈在兩個區域中!

$ fly status
...
Instances
ID       VERSION REGION DESIRED STATUS  HEALTH CHECKS      RESTARTS CREATED
0a8e6666 30      ewr    run     running 1 total, 1 passing 0        16s ago
cdf6c422 30      sea    run     running 1 total, 1 passing 0        6m47s ago

讓我們確定它們被分組在一起。

$ fly ssh console -C "/app/bin/my_app remote"
iex(my-app-1234@fdaa:0:1da8:a7b:ac2:cdf6:c422:2)1> Node.list
[:"my-app-1234@fdaa:0:1da8:a7b:ab2:a8e:6666:2"]

我們有兩個應用程式實例部署到北美洲的西岸和東岸,而且它們被分組在一起!我們的使用者將自動被導向距離他們最近的伺服器。

Fly.io 平台有內建的分散式支援,讓分組分散式的 Elixir 節點於多個區域變得容易。

有用的 Fly.io 資源

開啟您帳戶的儀表板

$ fly dashboard

部署您的應用程式

$ fly deploy

顯示您的已部署應用程式的狀態

$ fly status

存取並尾隨日誌

$ fly logs

向上或向下擴充您的應用程式

$ fly scale count 2

參考 Fly.io Elixir 文件 以取得更多資訊。

處理 Fly.io 應用程式 涵蓋了以下事項

  • 狀態和日誌
  • 自訂網域名稱
  • 憑證

疑難排解

請參閱 疑難排解Elixir 疑難排解

前往 Fly.io 社群 尋找解法和提出問題。