Хостинг: Fly
Это руководство расскажет вам о том, как вы можете разместить своих ботов grammY на Fly, используя Deno или Node.js.
Подготовка кода
Вы можете запустить своего бота, используя оба варианта вебхуки или long polling.
Вебхуки
Помните, что при использовании вебхуков не следует вызывать
bot
в коде..start()
- Убедитесь, что у вас есть файл, который экспортирует ваш объект
Bot
, чтобы вы могли импортировать его позже для запуска. - Создайте файл с именем
app
или.ts app
, или вообще любым другим именем, которое вам нравится (но вы должны запомнить и использовать его как основной файл для развертывания), со следующим содержанием:.js
import { webhookCallback } from "https://deno.land/x/grammy@v1.30.0/mod.ts";
// Вы можете изменить это, чтобы правильно импортировать свой объект `Bot`.
import { bot } from "./bot.ts";
const port = 8000;
const handleUpdate = webhookCallback(bot, "std/http");
Deno.serve({ port }, async (req) => {
const url = new URL(req.url);
if (req.method === "POST" && url.pathname.slice(1) === bot.token) {
try {
return await handleUpdate(req);
} catch (err) {
console.error(err);
}
}
return new Response();
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import express from "express";
import { webhookCallback } from "grammy";
// Вы можете изменить это, чтобы правильно импортировать свой объект `Bot`.
import { bot } from "./bot";
const port = 8000;
const app = express();
app.use(express.json());
app.use(`/${bot.token}`, webhookCallback(bot, "express"));
app.use((_req, res) => res.status(200).send());
app.listen(port, () => console.log(`прослушиваю порт ${port}`));
2
3
4
5
6
7
8
9
10
11
12
13
Мы советуем располагать обработчик не в корне (/
), а на каком-то секретном пути. Как показано в выделенной строке выше, мы используем токен бота (/<токен бота>
) в качестве секретного пути.
Long Polling
Создайте файл с именем app
или app
, или вообще любым другим именем, которое вам нравится (но вы должны запомнить и использовать этот файл как основной для развертывания), со следующим содержимым:
import { Bot } from "https://deno.land/x/grammy@v1.30.0/mod.ts";
const token = Deno.env.get("BOT_TOKEN");
if (!token) throw new Error("BOT_TOKEN не установлен");
const bot = new Bot(token);
bot.command(
"start",
(ctx) => ctx.reply("Я запущен на хостинге Fly с помощью long polling!"),
);
Deno.addSignalListener("SIGINT", () => bot.stop());
Deno.addSignalListener("SIGTERM", () => bot.stop());
bot.start();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { Bot } from "grammy";
const token = process.env.BOT_TOKEN;
if (!token) throw new Error("BOT_TOKEN не установлен");
const bot = new Bot(token);
bot.command(
"start",
(ctx) => ctx.reply("Я запущен на хостинге Fly с помощью long polling!"),
);
process.once("SIGINT", () => bot.stop());
process.once("SIGTERM", () => bot.stop());
bot.start();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Как вы можете видеть в выделенной строке выше, мы берем некоторые чувствительные значения (ваш токен бота) из переменных окружения. Fly позволяет нам сохранить этот секрет, выполнив эту команду:
flyctl secrets set BOT_TOKEN="AAAA:12345"
Аналогичным образом можно указать и другие секреты. Более подробную информацию об этих секретах см. по адресу https://
Развертывание
Метод 1: С помощью flyctl
Это самый простой метод.
Установите flyctl и войдите в аккаунт.
Запустите
flyctl launch
для созданияDockerfile
иfly
файлов для развертывания. Но НЕ развертывайте..toml shflyctl launch
1logCreating app in /my/telegram/bot Scanning source code Detected a Deno app ? App Name (leave blank to use an auto-generated name): grammy Automatically selected personal organization: CatDestroyer ? Select region: ams (Amsterdam, Netherlands) Created app grammy in organization personal Wrote config file fly.toml ? Would you like to set up a Postgresql database now? No ? Would you like to deploy now? No Your app is ready. Deploy with `flyctl deploy`
1
2
3
4
5
6
7
8
9
10
11shflyctl launch
1logCreating app in /my/telegram/bot Scanning source code Detected a NodeJS app Using the following build configuration: Builder: heroku/buildpacks:20 ? App Name (leave blank to use an auto-generated name): grammy Automatically selected personal organization: CatDestroyer ? Select region: ams (Amsterdam, Netherlands) Created app grammy in organization personal Wrote config file fly.toml ? Would you like to set up a Postgresql database now? No ? Would you like to deploy now? No Your app is ready. Deploy with `flyctl deploy`
1
2
3
4
5
6
7
8
9
10
11
12
13Deno: Измените версию Deno и удалите
CMD
, если он существует в файлеDockerfile
. Например, в данном случае мы обновляемDENO
до_VERSION 1
..25 .2 Node.js: Чтобы изменить версию Node.js, вам нужно вставить свойство
"node"
внутри свойства"engines"
в файлеpackage
. Например, в примере ниже мы обновляем версию Node.js до.json 16
..14 .0 dockerfile# Dockerfile ARG DENO_VERSION=1.25.2 ARG BIN_IMAGE=denoland/deno:bin-${DENO_VERSION} FROM ${BIN_IMAGE} AS bin FROM frolvlad/alpine-glibc:alpine-3.13 RUN apk --no-cache add ca-certificates RUN addgroup --gid 1000 deno \ && adduser --uid 1000 --disabled-password deno --ingroup deno \ && mkdir /deno-dir/ \ && chown deno:deno /deno-dir/ ENV DENO_DIR /deno-dir/ ENV DENO_INSTALL_ROOT /usr/local ARG DENO_VERSION ENV DENO_VERSION=${DENO_VERSION} COPY --from=bin /deno /bin/deno WORKDIR /deno-dir COPY . . ENTRYPOINT ["/bin/deno"] # CMD is removed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26json// package.json { "name": "grammy", "version": "1.0.0", "description": "grammy", "main": "app.js", "author": "itsmeMario", "license": "MIT", "dependencies": { "express": "^4.18.1", "grammy": "^1.11.0" }, "devDependencies": { "@types/express": "^4.17.14", "@types/node": "^18.7.18", "typescript": "^4.8.3" }, "engines": { "node": "16.14.0" } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21Отредактируйте
app
внутри файлаfly
. Путь.toml .
(или/app .ts .
для Node.js) в примере ниже относится к директории главного файла. Вы можете изменить их, чтобы они соответствовали директории вашего проекта. Если вы используете вебхуки, убедитесь, что порт совпадает с портом в вашей конфигурации (/app .js 8000
).toml# fly.toml app = "grammy" kill_signal = "SIGINT" kill_timeout = 5 [processes] app = "run --allow-net ./app.ts" [[services]] http_checks = [] internal_port = 8000 processes = ["app"] protocol = "tcp" script_checks = [] [services.concurrency] hard_limit = 25 soft_limit = 20 type = "connections" [[services.ports]] force_https = true handlers = ["http"] port = 80 [[services.ports]] handlers = ["tls", "http"] port = 443 [[services.tcp_checks]] grace_period = "1s" interval = "15s" restart_limit = 0 timeout = "2s"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33toml# fly.toml app = "grammy" kill_signal = "SIGINT" kill_timeout = 5 [processes] app = "run --allow-net ./app.ts" # Просто опустите весь раздел [[services]] # поскольку мы не слушаем HTTP
1
2
3
4
5
6
7
8
9
10toml# fly.toml app = "grammy" kill_signal = "SIGINT" kill_timeout = 5 [processes] app = "node ./build/app.js" # Настройте переменную окружения NODE_ENV, чтобы убрать предупреждение [build.args] NODE_ENV = "production" [build] builder = "heroku/buildpacks:20" [[services]] http_checks = [] internal_port = 8000 processes = ["app"] protocol = "tcp" script_checks = [] [services.concurrency] hard_limit = 25 soft_limit = 20 type = "connections" [[services.ports]] force_https = true handlers = ["http"] port = 80 [[services.ports]] handlers = ["tls", "http"] port = 443 [[services.tcp_checks]] grace_period = "1s" interval = "15s" restart_limit = 0 timeout = "2s"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40toml# fly.toml app = "grammy" kill_signal = "SIGINT" kill_timeout = 5 [processes] app = "node ./build/app.js" # Настройте переменную окружения NODE_ENV, чтобы убрать предупреждение [build.args] NODE_ENV = "production" [build] builder = "heroku/buildpacks:20" # Просто опустите всю секцию [[services]], поскольку мы не слушаем HTTP.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16Запустите
flyctl deploy
, чтобы развернуть ваш код.
Метод 2: С помощью Github Actions
Основное преимущество этого метода в том, что Fly будет следить за изменениями в вашем репозитории, включающем код бота, и автоматически разворачивать новые версии. Посетите https://
Установите flyctl и войдите в аккаунт.
Получите токен Fly API, выполнив команду
flyctl auth token
.Создайте репозиторий на GitHub, он может быть как приватным, так и публичным.
Перейдите в раздел Settings, выберите Secrets и создайте секрет под названием
FLY
со значением токена из шага 2._API _TOKEN Создайте файл
.github
с таким содержимым:/workflows /main .yml ymlname: Fly Deploy on: [push] env: FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }} jobs: deploy: name: Deploy app runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: superfly/flyctl-actions/setup-flyctl@master - run: flyctl deploy --remote-only
1
2
3
4
5
6
7
8
9
10
11
12Выполните шаги со 2 по 4 из Метода 1 выше. Не забудьте пропустить последний шаг (шаг 5), поскольку мы не будем разворачивать код напрямую.
Зафиксируйте изменения и выложите их на GitHub.
Вот тут-то и происходит волшебство — push вызвал развертывание, и с этого момента при каждом изменении приложение будет автоматически развертываться.
Настройка URL вебхука
Если вы используете вебхуки, то после запуска приложения вам необходимо настроить параметры вебхуков бота так, чтобы они указывали на ваше приложение. Для этого отправьте запрос на
https://api.telegram.org/bot<токен>/setWebhook?url=<url>
заменив <токен>
на токен вашего бота, а <url>
на полный URL вашего приложения вместе с путем к обработчику вебхука.
Оптимизация Dockerfile
Когда запускается наш Dockerfile
, он копирует все из каталога в образ Docker. Для приложений Node.js некоторые каталоги, например node
, будут перестроены в любом случае, поэтому копировать их не нужно. Для этого создайте файл .dockerignore
и добавьте в него node
. Вы также можете использовать .dockerignore
, чтобы не копировать любые другие файлы, которые не нужны во время выполнения.