Hosting: Fly
Esta guía te explica las formas de alojar tus bots de grammY en Fly, ya sea usando Deno o Node.js.
Preparando tu código
Puedes ejecutar tu bot usando ambos webhooks o long polling.
Webhooks
Recuerda que no debes llamar a
bot
en tu código cuando uses webhooks..start()
- Asegúrate de tener un archivo que exporte tu objeto
Bot
, para poder importarlo después y ejecutarlo. - Crea un archivo llamado
app
o.ts app
, o en realidad cualquier nombre que te guste (pero deberías recordarlo y usarlo como el archivo principal para desplegar), con el siguiente contenido:.js
import { serve } from "https://deno.land/std@0.174.0/http/server.ts";
import { webhookCallback } from "https://deno.land/x/grammy@v1.13.1/mod.ts";
// Podrías modificar esto a la forma correcta de importar tu objeto `Bot`.
import { bot } from "./bot.ts";
const port = 8000;
const handleUpdate = webhookCallback(bot, "std/http");
serve(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();
}, { port });
import express from "express";
import { webhookCallback } from "grammy";
// Podrías modificar esto a la forma correcta de importar tu objeto `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(`listening on port ${port}`));
Le aconsejamos que tenga su manejador en alguna ruta secreta en lugar de la raíz (/
). Como se muestra en la línea resaltada arriba, estamos usando el token del bot (/<bot token>
) como ruta secreta.
Long Polling
Crea un archivo llamado app
o app
, o en realidad cualquier nombre que te guste (pero deberías recordar y usar este como el archivo principal para desplegar), con el siguiente contenido:
import { Bot } from "https://deno.land/x/grammy@v1.13.1/mod.ts";
// Aquí, tomamos el token del bot de la variable de entorno "BOT_TOKEN".
const bot = new Bot(Deno.env.get("BOT_TOKEN") ?? "");
bot.command(
"start",
(ctx) => ctx.reply("I'm running on Fly using long polling!"),
);
Deno.addSignalListener("SIGINT", () => bot.stop());
Deno.addSignalListener("SIGTERM", () => bot.stop());
bot.start();
import { Bot } from "grammy";
// Aquí, tomamos el token del bot de la variable de entorno "BOT_TOKEN".
const bot = new Bot(process.env.BOT_TOKEN ?? "");
bot.command(
"start",
(ctx) => ctx.reply("I'm running on Fly using long polling!"),
);
process.once("SIGINT", () => bot.stop());
process.once("SIGTERM", () => bot.stop());
bot.start();
Como puedes ver en la línea resaltada arriba, tomamos algunos valores sensibles (tu token de bot) de las variables de entorno. Fly nos permite almacenar ese secreto ejecutando este comando:
flyctl secrets set BOT_TOKEN="AAAA:12345"
Puedes especificar otros secretos de la misma manera. Para más información sobre estos secretos, véase https://
Despliegue
flyctl
Método 1: Con Este es el método más sencillo.
- Instalar flyctl e inicia la sesión.
- Ejecuta
flyctl launch
para generar unDockerfile
y un archivofly
para el despliegue. Pero NO despliega..toml
flyctl launch
Creating 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`
flyctl launch
Creating 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`
Deno: Cambiar la versión de Deno y eliminar
CMD
si existe en el archivoDockerfile
. Por ejemplo, en este caso, actualizamosDENO
a_VERSION 1
..25 .2 Node.js: Para cambiar la versión de Node.js, necesitas insertar una propiedad
"node"
dentro de una propiedad"engines"
dentro depackage
. Por ejemplo, actualizamos la versión de Node.js a.json 16
en el siguiente ejemplo..14 .0
# 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 /deno /bin/deno
WORKDIR /deno-dir
COPY . .
ENTRYPOINT ["/bin/deno"]
# CMD es eliminado
// 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"
}
}
- Edita
app
dentro del archivofly
. La ruta.toml .
(o/app .ts .
para Node.js) en el ejemplo de abajo se refiere al directorio del archivo principal. Puedes modificarlos para que coincidan con el directorio de tu proyecto. Si estás usando webhooks, asegúrate de que el puerto es el mismo que el de tu configuración (/app .js 8000
).
# 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"
# fly.toml
app = "grammy"
kill_signal = "SIGINT"
kill_timeout = 5
[processes]
app = "run --allow-net ./app.ts"
# Simplemente omitiendo toda la sección de [[services]] ya que no estamos escuchando HTTP.
# fly.toml
app = "grammy"
kill_signal = "SIGINT"
kill_timeout = 5
[processes]
app = "node ./build/app.js"
# Ajuste la variable de entorno NODE_ENV para suprimir la advertencia
[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"
# fly.toml
app = "grammy"
kill_signal = "SIGINT"
kill_timeout = 5
[processes]
app = "node ./build/app.js"
# Ajuste la variable de entorno NODE_ENV para suprimir la advertencia
[build.args]
NODE_ENV = "production"
[build]
builder = "heroku/buildpacks:20"
# Simplemente omitiendo toda la sección de [[servicios]] ya que no estamos escuchando HTTP.
- Ejecuta
flyctl deploy
para desplegar tu código.
Método 2: Con acciones de GitHub
La principal ventaja del siguiente método es que Fly vigilará los cambios en tu repositorio que incluye el código de tu bot, y desplegará las nuevas versiones automáticamente. Visite https://
- Instala flyctl e inicia la sesión.
- Obtén un token de la API de Fly ejecutando
flyctl auth token
. - Crea un repositorio en GitHub, puede ser privado o público.
- Ve a Configuración, elige Secretos y crea un secreto llamado
FLY
con el valor del token del paso 2._API _TOKEN - Crea
.github
con estos contenidos:/workflows /main .yml
name: 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
- Sigue los pasos 2 a 4 del Método 1 anterior. Recuerda saltarte el último paso (paso 5) ya que no vamos a desplegar el código directamente.
- Confirma tus cambios y envíalos a GitHub.
- A partir de ahora, cada vez que envíes un cambio, la aplicación se desplegará automáticamente.
Configuración de la URL del Webhook
Si estás utilizando webhooks, después de poner en marcha tu aplicación, debes configurar los ajustes de webhook de tu bot para que apunte a tu aplicación. Para ello, envía una petición a
https://api.telegram.org/bot<token>/setWebhook?url=<url>
sustituyendo <token>
por el token de tu bot, y <url>
por la URL completa de tu app junto con la ruta al manejador del webhook.
Optimización de Dockerfile
Cuando nuestro Dockerfile
se ejecuta, copia todo desde el directorio a la imagen Docker. Para las aplicaciones Node.js, algunos directorios como node
van a ser reconstruidos de todos modos, así que no hay necesidad de copiarlos. Crea un archivo .dockerignore
y añade node
a él para hacer esto. También puedes utilizar .dockerignore
para no copiar ningún otro archivo que no sea necesario en tiempo de ejecución.