Closed7

fly.ioを試してみる

kun432kun432

公式ハンズオン

まずは公式ハンズオンに従ってやってみる

https://fly.io/docs/hands-on/

VS Codeでdevcontainerを立ち上げて試してみる。今回はMS公式のPython3のイメージを使う。

devcontainerが立ち上がったらターミナルからflyctlをインストール。

$ curl -L https://fly.io/install.sh | sh
set channel to shell
flyctl was installed successfully to /home/vscode/.fly/bin/flyctl
Manually add the directory to your $HOME/.bash_profile (or similar)
  export FLYCTL_INSTALL="/home/vscode/.fly"
  export PATH="$FLYCTL_INSTALL/bin:$PATH"
Run '/home/vscode/.fly/bin/flyctl --help' to get started

今回は適当なdevcontainerなので、環境変数は直接セットする。実際にレポジトリ等で管理する場合には別途設定が必要。

$ export FLYCTL_INSTALL="/home/vscode/.fly"
$ export PATH="$FLYCTL_INSTALL/bin:$PATH"

パスが通っている

$ which fly
/home/vscode/.fly/bin/fly

アカウントの作成。私の場合はfly.ioのウェブサイトで先にやってしまったのでスキップ。実行するとアカウント作成画面が表示されて支払い情報の登録が必要になるっぽい。支払い情報は無料プランであっても必要になる模様。

ということでウェブサイトでアカウント作成済みの場合も、事前に支払い情報を設定しておく必要があることを忘れずに(支払い情報がないとデプロイの最後で「We need your payment information to continue! Add a credit card or buy credit」となって失敗する)

$ fly auth signup

ログイン。多分ローカルだとブラウザが立ち上がって認証画面がでるっぽい。うちの環境はリモートサーバのdevcontainerからだったせいか、開かなかった。URLをクリックして直接開く。

$ fly auth login
failed opening browser. Copy the url (https://fly.io/app/auth/cli/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX) into a browser and continue
Opening https://fly.io/app/auth/cli/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ...

Waiting for session...⣷

"Continue as 自分のメアド" をクリックする。自分の場合はすでにログイン済みだったけど、ログインしてない場合は恐らくログイン画面が挟まれるのだと思う。

以下のように表示されればOK。ブラウザを閉じる。

VS Codeのターミナルのほうもログイン済となる。

Waiting for session... Done
successfully logged in as foo@example.com

ではサンプルのアプリを立ち上げる。

$ fly launch --image flyio/hellofly:latest

ここから対話形式でセットアップしていく。まずアプリ名。アプリ名はどうやら一意である必要がある様子(すでに使用されているアプリ名を指定した場合、セットアップの最後で「Error: Validation failed: Name has already been taken」で失敗となる)

? Choose an app name (leave blank to generate one): kun432-flyio-sample

リージョン。いくつかのリージョンは有償プランのみの様子。とりあえず今回は”Tokyo, Japan”で。

? Choose a region for deployment:  [Use arrows to move, type to filter]
  Hong Kong, Hong Kong (hkg)
  Ashburn, Virginia (US) (iad)
  Johannesburg, South Africa (jnb)
  Los Angeles, California (US) (lax)
  London, United Kingdom (lhr)
  Madrid, Spain (mad)
  Miami, Florida (US) (mia)
> Tokyo, Japan (nrt)
  Chicago, Illinois (US) (ord)
  Bucharest, Romania (otp)
  Phoenix, Arizona (US) (phx)

問題なければ、ここでURLが決まる。

Hostname: kun432-flyio-sample.fly.dev

fly.ioではPostgreSQLやRedis等のデータベースも使用できる様子。今回は使わない。

? Would you like to set up a Postgresql database now? No
? Would you like to set up an Upstash Redis database now? No

設定はtomlで作成される。

Wrote config file fly.toml

デプロイする。

? Would you like to deploy now? (y/N) 

こんな感じでデプロイされる。

Validating /workspaces/fly-io-handson/fly.toml
Platform: machines
✓ Configuration is valid
==> Building image
Searching for image 'flyio/hellofly:latest' remotely...
image found: img_z1nr0lpjz9v5q98w

Watch your app at https://fly.io/apps/kun432-flyio-sample/monitoring

This deployment will:
 * create 2 "app" machines

No machines in group app, launching a new machine
  Machine 148ed666a5e489 [app] update finished: success
Creating a second machine to increase service availability
  Machine 6e82d337c43987 [app] update finished: success
Finished launching new machines

NOTE: The machines for [app] have services with 'auto_stop_machines = true' that will be stopped when idling


Visit your newly deployed app at https://kun432-flyio-sample.fly.dev/

早速URLにアクセスしてみるとHello, World的な画面が表示されている。

URL末尾にパスを追加するとメッセージが変わるように作られているらしく、/hogeを追加してみるとこうなる。

で、管理画面の方ではログなどが確認できる。なんか冗長性確保のためなのかな?もう1台用意されてるように見える。コールドスタンバイなのかな?

CLIでもアプリやVMのステータス確認ができる。

$ fly status
App
  Name     = kun432-flyio-sample          
  Owner    = personal                     
  Hostname = kun432-flyio-sample.fly.dev  
  Image    = flyio/hellofly:latest        
  Platform = machines                     

Machines
PROCESS ID              VERSION REGION  STATE   CHECKS  LAST UPDATED         
app     148ed666a5e489  1       nrt     started         2023-07-05T09:46:03Z
app     6e82d337c43987  1       nrt     stopped         2023-07-05T09:18:28Z

CLIのヘルプを見てみると、スケールさせたり、DB追加したり、ログの確認やssh/sftpなんかもできるっぽい。

$ fly help

Deploying apps and machines:
  apps            Manage apps
  machine         Commands that manage machines
  launch          Create and configure a new app from source code or a Docker image.
  deploy          Deploy Fly applications
  destroy         Permanently destroys an app
  open            Open browser to current deployed application

Scaling and configuring:
  scale           Scale app resources
  regions         V1 APPS ONLY: Manage regions
  secrets         Manage application secrets with the set and unset commands.

Provisioning storage:
  volumes         Volume management commands
  mysql           Provision and manage PlanetScale MySQL databases
  postgres        Manage Postgres clusters.
  redis           Launch and manage Redis databases managed by Upstash.com
  consul          Enable and manage Consul clusters

Networking configuration:
  ips             Manage IP addresses for apps
  wireguard       Commands that manage WireGuard peer connections
  proxy           Proxies connections to a fly VM
  certs           Manage certificates

Monitoring and managing things:
  logs            View app logs
  status          Show app status
  dashboard       Open web browser on Fly Web UI for this app
  dig             Make DNS requests against Fly.io's internal DNS server
  ping            Test connectivity with ICMP ping messages
  ssh             Use SSH to login to or run commands on VMs
  sftp            Get or put files from a remote VM.

Platform overview:
  platform        Fly platform information

Access control:
  orgs            Commands for managing Fly organizations
  auth            Manage authentication
  move            Move an app to another organization

More help:
  docs            View Fly documentation
  doctor          The DOCTOR command allows you to debug your Fly environment
  help commands   A complete list of commands (there are a bunch more)

では一旦削除する。destroyで削除。アプリ名が必要。

$ fly destroy kun432-flyio-sample
Destroying an app is not reversible.
? Destroy app kun432-flyio-sample? Yes
Destroyed app kun432-flyio-sample
kun432kun432

Pythonアプリのデプロイ

Pythonアプリのデプロイの流れは以下に記載されている。

https://fly.io/docs/languages-and-frameworks/python/

シンプルなFlaskを使ったウェブアプリの様子。サンプルコードのレポジトリは以下。

https://github.com/fly-apps/python-hellofly-flask

一応サラッとやってみる。まずレポジトリをclone。

$ git clone https://github.com/fly-apps/python-hellofly-flask
$ cd python-hellofly-flask

ファイル構成はこんな感じ。

$ tree .
.
├── Procfile
├── README.md
├── hellofly.py
├── requirements.txt
└── templates
    └── hello.html

詳細はドキュメントやレポジトリ参照。

まずパッケージをインストール。

$ pip install -r requirements.txt

まずローカルでアプリを立ち上げてみる。

$ FLASK_APP=hellofly flask run

http://127.0.0.1:5000で上がってくるのでブラウザでアクセスしてみる。

http://127.0.0.1:5000/hogeでアクセスしてみると

ということでハンズオンで使ったアプリはこれだったのね。

ではデプロイしてみる。

$ flyctl launch
Creating app in /workspaces/fly-io-handson/python-hellofly-flask
Scanning source code
Detected a Python app
Using the following build configuration:
        Builder: paketobuildpacks/builder:base
? Choose an app name (leave blank to generate one): kun432-flask-sample
automatically selected personal organization: XXXXXXXXX
Some regions require a paid plan (bom, fra, maa).
See https://fly.io/plans to set up a plan.

? Choose a region for deployment: Tokyo, Japan (nrt)
App will use 'nrt' region as primary

Created app 'kun432-flask-sample' in organization 'personal'
Admin URL: https://fly.io/apps/kun432-flask-sample
Hostname: kun432-flask-sample.fly.dev
? Overwrite "/workspaces/fly-io-handson/python-hellofly-flask/Procfile"? Yes
? Would you like to set up a Postgresql database now? No
? Would you like to set up an Upstash Redis database now? No
Wrote config file fly.toml
Validating /workspaces/fly-io-handson/python-hellofly-flask/fly.toml
Platform: machines
✓ Configuration is valid
We have generated a simple Procfile for you. Modify it to fit your needs and run "fly deploy" to deploy your application.

Pythonアプリをデプロイする場合のポイントは以下の模様

  • ディレクトリの中身は全部デプロイされるイメージにコピーされる
  • Heroku何かと同様にProcfileでアプリケーションの起動を制御する

Procfileはこんな感じ。

# Modify this Procfile to fit your needs
web: gunicorn server:app

ただこれ元々レポジトリに入っていたけど、fly launchで上書きしてしまったみたい。正しくは以下のはず。なので修正しておく。

https://github.com/fly-apps/python-hellofly-flask/blob/main/Procfile

生成されたfly.tomlはこんな感じ

app = "kun432-flask-sample"
primary_region = "nrt"

[build]
  builder = "paketobuildpacks/builder:base"

[env]
  PORT = "8080"

[http_service]
  internal_port = 8080
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 0
  processes = ["app"]

ではデプロイ。

$ fly deploy

dockerイメージが作成されているのがわかる。

==> Verifying app config
Validating /workspaces/fly-io-handson/python-hellofly-flask/fly.toml
Platform: machines
✓ Configuration is valid
--> Verified app config
==> Building image
Remote builder fly-builder-muddy-mountain-1469 ready
==> Building image with Buildpacks
--> docker host: 20.10.12 linux x86_64
base: Pulling from paketobuildpacks/builder
c6b348cd73bd: Pulling fs layer 
04519a37e0a8: Pulling fs layer 
dc5c5b9dba89: Pulling fs layer 
ae5e916f75bf: Pulling fs layer 
08e65dacaeac: Pulling fs layer 
e085946a6c12: Pulling fs layer 
1ffc8b380152: Pulling fs layer 
(snip)
f92983442b23: Pushed 
4d274d05ee12: Pushed 
548a79621a42: Pushed 
deployment-XXXXXXXXXXXXXXXXXXXXXXXXXX: digest: sha256:d69b44c82c9cb1074a6cab9dd83945dc4402bb297f46d7acd621ae07de79fc5b size: 3243
--> Pushing image done
image: registry.fly.io/kun432-flask-sample:deployment-XXXXXXXXXXXXXXXXXXXXXXXXXX
image size: 281 MB

Watch your app at https://fly.io/apps/kun432-flask-sample/monitoring

Provisioning ips for kun432-flask-sample
  Dedicated ipv6: 2a09:8280:1::37:3983
  Shared ipv4: 66.241.124.241
  Add a dedicated ipv4 with: fly ips allocate-v4
This deployment will:
 * create 2 "app" machines

No machines in group app, launching a new machine
  Machine 4d891226a1dd87 [app] update finished: success
Creating a second machine to increase service availability
  Machine e784e666f01683 [app] update finished: success
Finished launching new machines

NOTE: The machines for [app] have services with 'auto_stop_machines = true' that will be stopped when idling


Visit your newly deployed app at https://kun432-flask-sample.fly.dev/

デプロイされた。

URLにアクセスしてみたら普通に同じものが見えると思う。

kun432kun432

Dockerアプリのデプロイ再び

前回は多分テストで使ったDockerfileの設定が良くなかったと思う。ということで1から作ってみた。事前にdocker単体でも動くことを確認しつつやる。

まずdevcontainer

.devcontainer/devcontainer.json
{
	"name": "Python 3",
	"image": "mcr.microsoft.com/devcontainers/python:1-3.10-bookworm",
	"features": {
		"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {
			"version": "latest",
			"dockerDashComposeVersion": "v2"
		}
	},
	"customizations": {
		"vscode": {
			"extensions": [
				"ms-python.black-formatter",
				"ms-python.isort"
			]
		}
	}
}

細かい設定は置いておいて、自分の環境では、LAN内のリモートサーバでdockerを動かす形。dockerコマンドをdevcontainer内から実行して、リモートサーバ上のdockerで作成したdockerアプリを動かすことになる。なのでDooDな環境になるので、ここでfeaturesとして追加しておく。

でDockerfile。ここはStreamlitのDockerチュートリアルを参考にした。

https://docs.streamlit.io/knowledge-base/tutorials/deploy/docker

Dockerfile
FROM python:3.9-slim

WORKDIR /app

RUN apt-get update && apt-get install -y \
    build-essential \
    curl \
    software-properties-common \
    git \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY . /app

RUN pip install -r requirements.txt

EXPOSE 8080

HEALTHCHECK CMD curl --fail http://localhost:8080/_stcore/health

ENTRYPOINT ["streamlit", "run", "streamlit_app.py", "--server.port=8080", "--server.address=0.0.0.0"]

fly.ioはデフォルトだと内部ポートが8080になるようなので(多分変更もできるとは思うけど)、それに合わせて修正した(streamlitはデフォルトだと8501)

requirements.txtとサンプルアプリもstreamlitのサンプルをそのまま使った。

https://github.com/streamlit/streamlit-example

requirements.txt
altair
pandas
streamlit
streamlit_app.py
from collections import namedtuple
import altair as alt
import math
import pandas as pd
import streamlit as st

"""
# Welcome to Streamlit!

Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:

If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
forums](https://discuss.streamlit.io).

In the meantime, below is an example of what you can do with just a few lines of code:
"""


with st.echo(code_location='below'):
    total_points = st.slider("Number of points in spiral", 1, 5000, 2000)
    num_turns = st.slider("Number of turns in spiral", 1, 100, 9)

    Point = namedtuple('Point', 'x y')
    data = []

    points_per_turn = total_points / num_turns

    for curr_point_num in range(total_points):
        curr_turn, i = divmod(curr_point_num, points_per_turn)
        angle = (curr_turn + 1) * 2 * math.pi * i / points_per_turn
        radius = curr_point_num / total_points
        x = radius * math.cos(angle)
        y = radius * math.sin(angle)
        data.append(Point(x, y))

    st.altair_chart(alt.Chart(pd.DataFrame(data), height=500, width=500)
        .mark_circle(color='#0068c9', opacity=0.5)
        .encode(x='x:Q', y='y:Q'))

ではまずローカルのdockerでテストしてみる。

$ docker build -t streamlit_sample:latest .
$ docker run -p 8080:8080 streamlit_sample:latest

ブラウザでアクセスしてみて以下のような感じで表示されればOK。

OK。これでdockerアプリとしては動くことが確認できたので、fly.ioでデプロイしてみる。

$ curl -L https://fly.io/install.sh | sh
$ export FLYCTL_INSTALL="/home/vscode/.fly"
$ export PATH="$FLYCTL_INSTALL/bin:$PATH"
$ fly auth login
$ fly launch
Creating app in /workspaces/streamlit-docker-sample
Scanning source code
Detected a Dockerfile app
? Choose an app name (leave blank to generate one): kun432-streamlit-docker-sample
automatically selected personal organization: XXXXXXXX
Some regions require a paid plan (bom, fra, maa).
See https://fly.io/plans to set up a plan.

? Choose a region for deployment: Tokyo, Japan (nrt)
App will use 'nrt' region as primary

Created app 'kun432-streamlit-docker-sample' in organization 'personal'
Admin URL: https://fly.io/apps/kun432-streamlit-docker-sample
Hostname: kun432-streamlit-docker-sample.fly.dev
? Would you like to set up a Postgresql database now? No
? Would you like to set up an Upstash Redis database now? No
Wrote config file fly.toml
? Would you like to deploy now? Yes

(snip)

Watch your app at https://fly.io/apps/kun432-streamlit-docker-sample/monitoring

Provisioning ips for kun432-streamlit-docker-sample
  Dedicated ipv6: 2a09:8280:1::69:3789
  Shared ipv4: 66.241.124.90
  Add a dedicated ipv4 with: fly ips allocate-v4
This deployment will:
 * create 2 "app" machines

No machines in group app, launching a new machine
  Machine 91857550a95383 [app] update finished: success
Creating a second machine to increase service availability
  Machine 17811000f3d789 [app] update finished: success
Finished launching new machines

NOTE: The machines for [app] have services with 'auto_stop_machines = true' that will be stopped when idling


Visit your newly deployed app at https://kun432-streamlit-docker-sample.fly.dev/

作成されたURLにアクセスして先ほどと同じ画面が表示されればOK。

kun432kun432

まとめ

  • とりあえずめっちゃ簡単にデプロイできて楽。
  • render.comも使ってたけど、デプロイめちゃめちゃ遅い、コールドスタートから復帰しない場合がある、等いろいろあったんだけど、今触ってる感じではデプロイも普通だし、コールドスタートからの復帰もそんなに遅いとは感じない。
  • ドキュメント見る限りはいろいろできることも多そう。

Herokuの代替としてはいろいろあったけど、fly.ioでもういい気がする。個人的には有料で使ってもいいかなーと思ってるぐらい気に入った。ドキュメント見ながらいろいろ試してみたい。

このスクラップは2024/01/18にクローズされました