ウェブサイト検索

12 日間 (4 日目) - 関数を使用した誕生日通知の展開


12 日間の DigitalOcean の 4 日目 へようこそ!昨日、Twilio SMS 通知を誕生日リマインダー サービスに追加し、今日の誕生日にテキスト メッセージを送信できるようにしました。 🎂

今日は、スクリプトを DigitalOcean Functions にデプロイすることで、物事を次のレベルに進めていきます。これにより、専用サーバーを必要とせずにサービスをクラウドで実行できるようになり、アプリが軽量でスケーラブルになり、自動化に対応できるようになります。

この設定を使用すると、コンピュータの電源がオフの場合やインターネットに接続されていない場合でも、誕生日のリマインダーを受け取ることができます。マシン上でスクリプトを手動で実行する必要はもうありません。 🎉

DigitalOcean が機能する理由

時々実行される単純なスクリプトだけが必要な場合もあります。このようなインフラストラクチャを管理するのは過剰な作業になる可能性があります。ここで関数が登場します。これはサーバーレス プラットフォームです。つまり、必要な場合にのみ実行されるコードをデプロイでき、使用した分だけ料金を支払います。誕生日の確認や毎日のリマインダーの送信など、私たちのユースケースに最適です。

🚀 学習内容

今日が終わるまでに、次の方法がわかるようになります。

  1. DigitalOcean の doctl CLI ツールをセットアップします。
  2. サーバーレスの名前空間を作成して接続します (機能を整理しておくための DigitalOcean の方法)。
  3. 誕生日リマインダー サービスをパッケージ化してDigitalOcean 機能にデプロイします。
  4. デプロイされた関数をクラウドでテストします。

🛠 必要なもの

始める前に、次のものが揃っていることを確認してください。

  • DigitalOcean アカウント。
  • PostgreSQL データベース認証情報と Twilio 認証情報を含む .env ファイル

    • 「1 日目: 誕生日リマインダー用の PostgreSQL データベースのセットアップ」を参照してください。
    • 3 日目: 誕生日の確認と SMS 通知の送信を参照してください。

🧑🍳 4 日目のレシピ: DigitalOcean 機能へのデプロイ

ステップ 1: doctl CLI をセットアップする

すでにマシンに doctl を設定している場合は、この手順をスキップできます。設定する必要がある場合は、次の手順に従ってください。

始める前に、doctl について簡単に説明しましょう。これは、端末からクラウド リソースを直接管理できる DigitalOcean の公式コマンドライン インターフェイス ツールです。これを使用して、名前空間 (サーバーレス関数用のフォルダー) を作成し、Python スクリプトをデプロイし、関数をテストします。

設定は簡単です。

  1. doctl をインストールします: オペレーティング システムのインストール ガイドに従ってください。

  2. doctl を認証します: 以下を実行して、DigitalOcean アカウントに接続します。

    doctl auth init
    
  3. インストールを確認します: 次のコマンドを実行して、すべてが動作していることを確認します。

    doctl account get
    

成功すると、このコマンドは電子メールやアカウント ID など、DigitalOcean アカウントに関する詳細を返します。

ステップ 2: サーバーレス ソフトウェアをインストールする

DigitalOcean Functions にはサーバーレス サポート ソフトウェアが必要であり、インストールする必要があります。これは 1 回限りのセットアップであるため、一度インストールすると、今後のプロジェクトで再度セットアップする必要はありません。

次のコマンドを実行します。

doctl serverless install

インストール状況は次のようにして確認できます。

doctl serverless status

次のようなエラーが表示された場合:

Error: serverless support is installed but not connected to a functions namespace

心配しないでください。これは、まだ名前空間を作成していない、または名前空間に接続していないことを意味します。これについては次のステップで処理します。

ステップ 3: ネームスペースを作成して接続する

ネームスペースは、サーバーレス機能を整理するためのフォルダーのようなものです。誕生日リマインダー サービス用に作成しましょう。

  1. 新しい名前空間を作成します。

    doctl serverless namespaces create --label "my-birthday-reminder-namespace" --region "nyc1"
    

  2. ネームスペースに接続します。

    doctl serverless connect my-birthday-reminder-namespace
    

  3. 接続を確認します。

    doctl serverless status
    

ネームスペースに接続していることを確認するメッセージが表示されます。

上級者向けのヒント: 使用可能なすべての名前空間のリストを表示するには、次のコマンドを使用します。

doctl serverless namespaces list

これは、複数のプロジェクトを管理している場合、または作成したばかりの名前空間を確認したい場合に便利です。

ステップ 4: プロジェクト構造の初期化とセットアップ

DigitalOcean Functions は、サーバーレス展開用の特定のプロジェクト構造を想定しています。 doctl serverless init を使用してこの構造をキックスタートしたり、手動で作成したり、スターター リポジトリのクローンを作成したりすることができます。物事を簡単にするために、doctl serverless init を使用してセットアップします。

  1. 次のコマンドを実行してプロジェクトを初期化します:

    doctl serverless init --language python birthday-reminder-service
    

    これにより、次のデフォルト構造を持つ my-birthday-reminder-service という名前のローカル プロジェクト ディレクトリが作成されます。

    my-birthday-reminder-service/
    ├── packages
    │   └── sample
    │       └── hello
    │           └── hello.py
    └── project.yml
    

  2. プロジェクト ディレクトリに移動します。

    cd my-birthday-reminder-service
    
  3. ユースケースに合わせてフォルダーの名前を変更します:

    mv packages/sample packages/reminders
    mv packages/reminders/hello packages/reminders/birthdays
    mv packages/reminders/birthdays/hello.py packages/reminders/birthdays/__main__.py
    
  4. 必要なファイルを作成します:

    • プロジェクトのルートに空の .env ファイルを作成します。
    touch .env
    

    これにはデータベースと Twilio 認証情報が保持されます。このファイルは、my-birthday-reminder-service フォルダーのルートに配置されます。

    • birthdays フォルダーに requirements.txt ファイルを作成します。
    touch packages/reminders/birthdays/requirements.txt
    

    このファイルには、関数に必要な Python の依存関係がリストされます。これは packages/reminders/birthdays の下にあります。

    • 誕生日フォルダーに build.sh ファイルを作成します。
    touch packages/reminders/birthdays/build.sh
    chmod +x packages/reminders/birthdays/build.sh
    

    build.sh スクリプトは、外部依存関係のある関数をデプロイするために必要です。 chmod コマンドは、スクリプトが Mac/Linux システム上で実行可能であることを確認します。

更新された構造: これらの手順を完了すると、プロジェクトの構造は次のようになります。

my-birthday-reminder-service/
├── project.yml
├── .env
├── packages
│   └── reminders
│       └── birthdays
│           ├── __main__.py
│           ├── requirements.txt
│           ├── build.sh
├── .gitignore

専門的なヒント: 誤ってフォルダの名前を間違えた場合は、コマンドを再度実行するか、ファイル エクスプローラで手動で名前を変更できます。

ステップ 5: ファイルを更新する

構造が整ったので、必要なファイルを追加しましょう。お気に入りのコード エディターで my-birthday-reminder-service ディレクトリを開きます

1. project.yml を更新します。

project.yml ファイルは、サーバーレス プロジェクトの構造、環境変数、および関数を定義する構成ファイルです。

このファイルはリマインダー パッケージを設定し、環境変数を DigitalOcean 関数にマップします。各変数は、データベースと Twilio の統合に必要な認証情報に対応します。

2. .env ファイルを更新します

データベース認証情報については「1 日目: 誕生日リマインダー用の PostgreSQL データベースの設定」を参照し、Twilio 認証情報については「3 日目: 誕生日の確認と SMS 通知の送信」を参照して、次の値を入力します。

# Database credentials (from Day 1)
DB_HOST=<your-database-hostname>
DB_NAME=<your-database-name>
DB_USER=<your-database-username>
DB_PASSWORD=<your-database-password>
DB_PORT=5432  # Default PostgreSQL port
Twilio credentials (from Day 3)
TWILIO_ACCOUNT_SID=<your-twilio-account-sid>
TWILIO_AUTH_TOKEN=<your-twilio-auth-token>
TWILIO_PHONE_FROM=<your-twilio-phone-number>
TWILIO_PHONE_TO=<your-personal-phone-number>

注: .env ファイルは、機密の認証情報を安全に保存するために使用されます。 project.yml ファイルはこれらの値を読み取り、デプロイメント中にサーバーレス環境にマップし、クラウド内の関数からアクセスできるようにします。

3. 依存関係を追加する

次の依存関係を含む requirements.txt ファイルを更新します。

pg8000  
python-dotenv  
twilio  

pg8000: 純粋な Python PostgreSQL クライアント ライブラリ。

python-dotenv: .env ファイルから環境変数をロードするために使用されます。

twilio: SMS メッセージを送信するための Twilio Python ライブラリ。

4. build.shを更新する

次のスクリプトを build.sh ファイルに追加します。

#!/bin/bash
set -e
Print the current working directory for debugging
echo "Current working directory: $(pwd)"
Check if requirements.txt exists
if [[ -f "requirements.txt" ]]; then
  echo "Found requirements.txt in $(pwd)"
else
  echo "Error: requirements.txt not found in $(pwd)"
  exit 1
fi
Create a virtual environment
virtualenv --without-pip virtualenv
Install dependencies from requirements.txt
pip install -r requirements.txt --target virtualenv/lib/python3.9/site-packages

このスクリプトにより、すべての依存関係が関数とともに正しくパッケージ化されることが保証されます。ステップ 4 の chmod +x コマンドにより、コマンドが実行可能であることが確認されます。

5. __main__.py を更新します。

これは、誕生日リマインダー サービスのメイン スクリプトです。基本的には、誕生日通知を送信するために 3 日目に作成したスクリプトを使用しています。ただし、DigitalOcean Functions と互換性を持たせるには、いくつかの小さな調整を行う必要があります。

__main__.py ファイルを次の内容で更新します。

# birthday_reminder_service/__main__.py

from datetime import datetime
import pg8000
from dotenv import load_dotenv
from twilio.rest import Client
import os
Load environment variables
load_dotenv()

def main(params):
    """DigitalOcean Functions entry point."""
    try:
        # Connect to the database
        connection = pg8000.connect(
            host=os.getenv("DO_DB_HOST"),
            database=os.getenv("DO_DB_NAME"),
            user=os.getenv("DO_DB_USER"),
            password=os.getenv("DO_DB_PASSWORD"),
            port=int(os.getenv("DO_DB_PORT"))
        )
        cursor = connection.cursor()

        # Get today's month and day
        today = datetime.now()
        today_month = today.month
        today_day = today.day

        # Query to fetch contacts whose birthday matches today's date
        cursor.execute(
            """
            SELECT first_name, last_name, birthday
            FROM contacts
            WHERE EXTRACT(MONTH FROM birthday) = %s
              AND EXTRACT(DAY FROM birthday) = %s;
            """,
            (today_month, today_day)
        )
        rows = cursor.fetchall()

        # Notify for each matching contact
        if rows:
            account_sid = os.getenv("TWILIO_ACCOUNT_SID")
            auth_token = os.getenv("TWILIO_AUTH_TOKEN")
            client = Client(account_sid, auth_token)

            for row in rows:
                first_name, last_name, _ = row
                message = client.messages.create(
                    body=f"🎉 It's {first_name} {last_name or ''}'s birthday today! 🎂",
                    from_=os.getenv("TWILIO_PHONE_FROM"),
                    to=os.getenv("TWILIO_PHONE_TO")
                )
                print(f"Message sent for {first_name} {last_name}. Message SID: {message.sid}")
        else:
            print("No birthdays today.")

        # Close the cursor and connection
        cursor.close()
        connection.close()

    except Exception as e:
        print(f"An error occurred: {e}")

変更した点は次のとおりです。

  1. main(params) 関数が追加されました: DigitalOcean Functions は、params を受け取る main という名前のエントリ ポイント関数を期待します。口論。ここで関数の実行が開始されます。

  2. スクリプト ロジックを main 関数内に移動しました: 3 日目のコードは、この要件に合わせて main 関数内にラップされています。

  3. その他はすべて同じままです: データベース接続ロジック、誕生日チェック、SMS 通知ロジックは変更されていません。

ステップ 5: パッケージ化して展開する

すべての準備が整ったら、プロジェクトを DigitalOcean Functions にデプロイします。

  1. プロジェクトをデプロイします。
doctl serverless deploy my-birthday-reminder-service

関数が名前空間に正常にデプロイされたことを確認するには、次のようにします。

  1. DigitalOcean コントロール パネルにアクセスし、左側のバーの [機能] に移動します。
  2. 名前空間を見つけます (例: my-birthday-reminder-namespace)。
  3. 関数が名前空間の下に表示されることを確認します (通常は reminders/birthdays としてリストされます)。
  4. 関数名をクリックすると、ログ、構成、呼び出し履歴などの詳細が表示されます。

ステップ 6: デプロイされた関数をテストする

関数がデプロイされたら、テストしてみます。関数を手動で呼び出して、期待どおりに動作することを確認できます。これを行うには 2 つの方法があります。

オプション 1: DigitalOcean CLI の使用

doctl serverless functions invoke reminders/birthdays

すべてが正しく設定されていれば、関数がクラウドで実行され、今日の誕生日を確認して SMS 通知を送信します。

![https://doimages.nyc3.cdn.digitaloceanspaces.com/006Community/12-Days-of-DO/Postgressql-birthday/birthday_reminder_service_text_message.jpeg]

オプション 2: DigitalOcean ダッシュボードの使用

  1. DigitalOcean コントロール パネルに移動します。
  2. [機能] に移動し、リマインダー/誕生日機能を見つけます。
  3. 手動で実行するには、[実行] をクリックします。
  4. 出力とログをコンソールで直接表示します。

この方法は、視覚的なインターフェイスを好む場合、またはクリーンで読みやすい形式でログを確認したい場合に特に役立ちます。

テストのヒント

この関数を呼び出すと、今日の日付と一致する誕生日がチェックされます。一致する場合は、詳細が記載されたテキスト メッセージが届きます。関数を効果的にテストするには:

  • 現在の日付と一致する 1 つ以上の誕生日をデータベースに追加します。
  • コンソールまたは CLI ログをチェックして、機能が正常に実行されたことを確認します。

🎁 まとめ

今日達成したことは次のとおりです。

  1. doctl をセットアップし、プロジェクトの名前空間を作成しました。
  2. デプロイメント用に Python スクリプトをリファクタリングしました。
  3. 誕生日リマインダー サービスをパッケージ化し、DigitalOcean 機能にデプロイしました。
  4. CLI と DigitalOcean ダッシュボードを使用してクラウド機能をテストしました。

このシリーズの以前のチュートリアルは次のとおりです。

  • 1 日目: 誕生日リマインダー用に PostgreSQL データベースをセットアップする
  • 2 日目: Python を使用して PostgreSQL データベースに接続する
  • 3日目: 誕生日の確認とSMS通知の送信

次へ: これは大きな前進ですが、この関数はまだ手動で実行しています。次のチュートリアルでは、このプロセスを自動化して、誕生日リマインダー サービスが毎日特定の時刻に自動的に実行されるようにします。朝起きて指を離さずにテキストリマインダーが届くことを想像してみてください。明日はそれを実現しましょう。 🚀

5 日目の次のチュートリアルは次のとおりです。毎日のトリガーを使用して誕生日リマインダーを自動化する。