I use Dokku for managing my apps.
Dokku is basically an "host your own" version of the Heroku interface. Set your app using a particular pattern of files (in particular a Procfile) then deploy via git push. And, like Heroku, you can scale your app using a single command and add additional services (MySQL or Postgres, Redis and so on).
Unlike Heroku, Dokku is open-source and the plugins are hosted on your own server, not on an external, paid-for, service. So you can choose your own hosting company (Brightbox and Hetzner for me - both highly recommended) instead of going with AWS.
To set up dokku, you add in an app.json file that describes your app (plus stuff like cron jobs), a Procfile for managing processes and a CHECKS file for health checks. Plus, of course, a Dockerfile to define your dependencies.
You tell it which environment variables you want, install the app, then set up your git remote and do a git push. Dokku handles all the rest - setting up Nginx proxies, managing your containers, handling SSL/TLS via the Let's Encrypt plugin. It's kind of like docker compose but it includes the stuff docker compose leaves out.
However, I've got loads of apps on dokku now, including a couple that have multiple servers behind a load-balancer (which dokku isn't really designed for). And each server is set up slightly differently, keeping the environment variables up to date is getting to be a problem, as is keeping track of all the different configurations.
So I wrote Anvil - a tool for managing dokku so it can manage your app.
Anvil can generate a cloudinit file, which installs your required software and sets up your configuration, while the server is first being created. As your server builds, you can write an Anvil configuration file, containing server details, environment variables, plugins and any post-deployment scripts you need.
The cloudinit and anvil configuration files can live in your source repo, so your setup is documented and repeatable. Of course, you don't want to store sensitive data, passwords and encryption keys etc, in your repo. But Anvil has you covered as you can pipe in secrets from elsewhere.
Once cloudinit has finished configuring your new server, run
anvil app install from within your app's root folder. This SSH's to the server and configures dokku for you.
anvil app deploy. This creates git remotes for each server (handling multi-server deployments) then pushes your code, running any post-deployment scripts you have specified. And for subsequent deploys, just repeat the
anvil app deploy command.
I'm already using Anvil in production and it seems to work well. Of course, there's more to do - not least, it's very tied to my own preferences - but I'm really pleased with how it's turned out so far.
So why not give Anvil (and Dokku) a try?