Introduction

I often get asked about what the ābestā way to deploy a Python Telegram bot is. Iāve tried a lot of different ways, and Iāve settled on a workflow that Iām quite happy with for @SuperSeriousBot. Itās probably not ideal and Iād like to change a few things, but itās a process that has evolved over the last ~4 years.
Committing
In general I like to follow KISS for my projects. The actual code of @SuperSeriousBot is fairly straightforward. In a nutshell:
- Python 3.10 (asyncio)
- Poetry for dependency management
blackfor code formatting- The fantastic
python-telegram-botwrapper as the core
The code is stored on GitHub. For releases, I follow the Angular commit message convention. Using this, Iām able to largely automate the process of version management by using semantic-release.
Building
Being on GitHub, I make heavy use of GitHub actions. I have a workflow that runs on every push to the master branch. This workflow does the following:
- Run
npx semantic-releaseto calculate the next version number - Publish a release on the repository page with an auto-generated changelog
- Build Docker images of
@SuperSeriousBotforamd64andarm64architectures - Push the Docker images to ghcr.io
Iāve tried to trim down the Docker image size but it still sits at around ~400MB. This partās still a work in progress. Lately, Iāve also been looking into Nuitka for static binaries. No luck on that front so far. All builds are cached based on poetry.lock so we never rebuild layers. It matters a lot when youāre building for multiple architectures.
As of right now, thereās no tests. Itās up for discussion if Iāll ever add any. To me, a good code review process and robust logging is sufficient for a side project.
Hereās the .releaserc I use to automate the version management and changelog generation:
{
"branches": ["master"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/git",
"@semantic-release/github"
]
}
Deploying
I use watchtower to automatically update my Docker containers. I have a docker-compose.yml file that looks like this:
version: "3"
services:
ssgbot: ...
redis: ...
watchtower:
image: containrrr/watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: --interval 30
Itās not a zero downtime deployment, so I usually like to do it in the late AMs. Along with the bot itself, I use a mix of Redis and SQLite for caching and persistence. In production, I run @SuperSeriousBot in webhook mode. I front the bot with nginx for which I use systemd.
Conclusion
I find this setup to be quite robust and easy to maintain. If you have any suggestions, feel free to reach out to me on Telegram at @obviyus.
Wishlist
- Use Hashicorp Nomad for container orchestration
- Experiment with Nuitka for static binaries
- DuckDB instead of SQLite