はじめに
私が書いた記事を参考にDiscordBOTを作ってくれる方にcogsの使い方がわからんなどの話を聞いたりして、現在ほとんどDockerで環境を作ってそこで実行しているのであてになる記事になってないな、ということでDockerを使ってBOTを作成する方法を紹介したいと思った次第。
そんなわけでDockerでの環境構築からBOTの疎通確認レベルのコードを書いてきます。(Docker環境の構築については書きません)
前提
OS
- Windos10 (ubuntuなどでもだいたい一緒)
インストールするもの
- DockerDesktop
- Python 3.10
- py-cord
BOTの作成
ディレクトリの構成として以下のような状態を想定しています
.
┣━ docker-compose.yaml
┣━ Dockerfile
┣━ requirements.txt
┣━ .env
┗━ bot
┣━ main.py
┗━ cogs
┗━ sub.py
Dockerの構成
Dockerfile
Dockerfile
はアプリケーションを実行するための環境を定義するものです。
そのため、ここではpythonのイメージを取得してrequirements.txt
に書かれたライブラリをpip install
するという事が書かれています。
FROM python:3.10.5-alpine3.16
WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
requirements.txt
requirements.txt
には必要なライブラリを記述します。
この時バージョンを指定することもできるので、現在ローカルの環境で使われているPycordのバージョンに合わせておくとトラブルが起きにくいです
py-cord == 2.2.2
docker-compose.yaml
docker-compose.yaml
を作成します。
イメージとしては以下のような事をしています。
- Dockerfileのビルドを行いイメージとして利用する
- ディレクトリをボリュームとしてマウント
- 環境変数を渡す
- コマンドの実行
version: '3.8'
services:
bot:
# . は現在docker-compose.yamlと同じディレクトリのDockerfileを指しています。
# 複数のイメージを使う場合などは./botなどディレクトリを指定します。
build: .
volumes:
# ./botのディレクトリを仮想環境の/usr/src/appにマウントする
# rwと記述することで書き込みも可能なディレクトリとして認識される
- ./bot:/usr/src/app:rw
environment:
# ${}で囲んだものは.envファイルから環境変数を取得する
- TOKEN=${TOKEN}
- GUILDS=${GUILDS}
command: ["python3", "main.py"]
tty: true
.env
.env
ファイルは基本的にはBOTを動かすためのトークンの記述の他に実行するサーバーのIDなども一緒に定義しておきます
# DiscordDevで発行したトークン
TOKEN="TOKEN"
# DiscordサーバーのID(カンマ区切りで複数設定できるようにしてます)
GUILDS="000000000,000000000"
BOTの構成
main.py
main.py
ではbotをインスタンス化してcogsからコマンドなどを読み込む処理をします。
コマンドをこのファイルに書くと読みづらくなってしまうので基本書きません。
import discord
from discord.ext import commands
import os
# docker-composeから渡された環境変数の設定
TOKEN = os.getenv("TOKEN")
GUILDS = [int(v) for v in os.getenv("GUILDS").split(",")]
# intentsの設定(エラーが出るまで基本defaultで良いです)
intents = discord.Intents.default()
# debug_guildsは公開BOTの場合は必要ないです
bot = commands.Bot(
debug_guilds=GUILDS,
intents=intents
)
# botが動いてるか確認するだけのヤツ
@bot.event
async def on_ready():
print(f"Bot名:{bot.user} On ready!!")
# cogsディレクトリにあるsub.pyを読み込む処理です
bot.load_extensions(
"cogs.sub",
# "cogs.hoge", # 複数読み込む場合は並べてかけます
store=False # cog読み込み中にエラーが起きた時に止まる様に設定しています。
)
# botの起動
bot.run(TOKEN)
コマンドを増やしたい場合などはcogs
にpythonファイル生やしてload_extensions
で読み込ませるというような使い方になると思います。
sub.py
sub.py
では基本的にコマンドを定義していきます。
ここではcom
というコマンドグループを定義し、その中にhello
というコマンドを定義しています。
実際に使うときはcom hello name: 名前
のようなコマンドになります
import discord
from discord.ext import commands
from discord import SlashCommandGroup, Option, SlashCommandOptionType
# main.pyで読み込ませるためのCogを継承したクラスを作成します。
class SubCog(commands.Cog):
def __init__(self, bot):
print("start sub init")
self.bot = bot
# comというコマンドグループを定義します
com = SlashCommandGroup("com", "comコマンドのグループ")
# comというコマンドグループにhelloコマンドを定義します
@com.command(name="hello", description="挨拶するだけのコマンド")
async def hello(
self,
ctx: discord.ApplicationContext,
# name引数を受け取る様に設定します。
name: Option(
str,
description="引数の説明",
)
):
# 引数の段階だと型がstr型かわかりにくいので注釈をつけてます
name: str = name
# 名前にさんづけしてこんにちはするだけの処理
await ctx.response.send_message(f"{name}さん、こんにちは!")
# main.pyのload_extensionsのが実行する実際の関数を定義します
def setup(bot):
bot.add_cog(SubCog(bot)) #add_cog関数にSubCogのインスタンスを渡します
実行方法など
仮想環境上で先程書いてもらったmain.py
を実行するわけだが、Dockerの場合ほとんどPythonを直接実行するのとイメージは変わらない。
VSCodeなどでターミナルを開きdocker-compose.yaml
があるディレクトリに移動してdocker-compose build
コマンドを打ち込むだけでimageなどが用意され実行環境が整います。
実行環境が整ったらそのままdocker-compose up
のコマンドを実行すれば実行がされます。
あとはコマンドを呼べるサーバーでcom hello name: 名前
のように打ち込めばスラッシュコマンドが使える事が確認できると思います
終わりに
Pycordを使ったPythonのコードに関する部分などは疎通確認レベルのコードしか書いていません。
実際にbotを作成する場合はPycordなどのドキュメントを読んだりなんだりする必要が出てきます。
正直Discord.pyの方が公式で作られており、ドキュメントも日本語化されているのでオススメですが、DockerでBOTを動かす点でいえば一緒なので参考になれば、と思います。