I recently published some thoughts on Django being a great framework for applications. This post expands on that to include the other pieces of infrastructure from development to production environments.
I have used this stack (or ones that look a lot like it) to build small SaaS apps in 2018, 2019, and now in 2020.
- Linux Server/VM Hosted anywhere (I like Azure, Digital Ocean, or Scaleway)
- Docker. Just plain docker
- Traefik for reverse proxy and TLS with LetsEncrypt
- Postgresql running in docker
- Django in a container
- Intercoolerjs for easy and slick Ajax-like front-end work
- Sentry for catching production bugs (easy three-lines added to your config)
- Bitbucket pipelines for CI/CD
- ZeroTier for VPN/ControlPlane
For smaller projects I run tests locally in docker containers and then push directly into production. I don't bother with full CI/CD because I don't need the complexity of it all. That said, I do like Bitbucket Pipelines.
Woah! that is a lot to unpack here. Let's visualize this another way.
- Virtual Machine
- Volume mounted data disks
- Workers (Long-running django commands)
- Volume mounted data disks
- Volume-mounted data disks
Was this helpful? Let me know...
Your stuff needs a home (yes, even in the "serverless" world. LOL). My personal preferences are Azure, Digital Ocean (affiliate link), or Scaleway. They each offer enough compute, networking options, storage, and basic services to build out proofs-of-concept or whatever you might need.
Another honorable mention here is Hetzner. They offer a good level of hardware, service and price.
For those side projects and many enterprise applications, scale is not an issue. That means that I will not serve thousands of simultaneous users or handling terabytes of data. Therefore I can get by on the smaller offerings – usually under $20/month. Even Azure (the most expensive of the three) offer their burstable VMs. Generally I like to go with Scaleways Developer line of servers.
_ Notice that Kubernetes is missing from my stack? When scale is not an issue then you don't need Kubernetes. _
I do not rely on the OS vendor (Ubuntu) to make sure that I run the latest Docker on new VMs. Therefore I use the nice little
curl -s https://get.docker.com | sudo bash
This cure one-liner will get the best and most recent version for your machine running.
Traefik has been a God-send since I found it. Nginx is great, but it was not built for the Docker universe. Traefik has two killer features that have saved me hours upon hours:
- Automatic TLS with LetsEncrypt. Literally set-it-and-forget-it. With the right API keys and DNS provider you can also do verification with DNS.
- Automatic no-reload configuration using docker labels. When you spin up new services Traefik will pickup the changes automatically because it listens to all Docker-related events. This makes it incredibly convenient to add, remove, or merge services as needed without any hassle.
My only comment on Traefik is that there is a bit of a learning curve. You have to decide how you want to configure it (config file, command line options, yaml, or docker labels, or use a combination!)
Another note here: I have already published my production configuations for Traefik here.
Tried and True, PostgreSQL has never let me down. I usually attach one of these containers to a project that needs it without any difficulty. I simply spin up the container, bind the ports, and then bind the data volume to my host disk. Done and Done.
version: '3.1' services: db: container_name: postgres hostname: postgres image: postgres:11 restart: always environment: POSTGRES_PASSWORD: secretsonly volumes: - ./data:/var/lib/postgresql/data ports: - 5432:5432 networks: - web networks: web: external: true
Docker deploys nicely in a container, and I have been doing it for a few years now. The benefits of matching your development environment to your production one cannot be overstated, and I have Docker to thank for that.
Also, for asynchronous tasks I simply use custom Django commands which are a part of the standard framework. The pattern here is a simple
while loop with a
sleep() period. It polls the database for relevant actions and then does it's thing.
IntercoolerJS keeps that old-school "Ajax" (remember that word) goodness and allows me to update the DOM with HTML from the backend. It is seamless, smooth, and really convenient for things like logins and small form updates.
I strongly suggest you check it out: Learn more about IntercoolerJS
I make mistakes. Lots of mistakes--but there is no need to show them to my users, right? Sentry gives me an easy and convenient way to capture production bugs as they happen. Some cool things about them:
- Open source, so you can host yourself if that is your thing.
- Easy few lines added to your
settings.pyfile in Django and that is it.
- Tight integration to your Git repos and Issue tracking systems for full production defect traceability.
Another nice thing is that you can disable it for development.
There are so many CI/CD offerings out there today, but I have been happy with Bitbucket's offering called Pipelines. They offer you a few hundred minutes free every month with the option to top-up as needed for a small fee. I have rarely had problems, and I really enjoy their YAML configuraiton / directive files.
bitbucket-pipelines.yml file I have been able to do full end-to-end testing by spinning up multiple docker containers, loading the databases, and running hundreds of test in just a few minutes. This was key in speeding things up in our team and enabling 5+ pushes to production per day.
Finally, we come to the bit of tech that is largely optional but nice to have. Zerotier is a unique kind of network/VPN that I use to link all my personal machines. It works though firewalls (at home, in office) and offers an easy 1 minute setup.
Using ZeroTier in my last company we were able to remove the SSH Jump Servers which caused a headache in terms of key management and shared bandwidth on a single machine.
Zerotier work on Linux, Mac, Windows, Android, and iPhone, so you are pretty much covered.
The one downside to ZeroTier is that I don't entirely understand how it works. It is a lot like MacOS or iPhone in that it "just works" as expected and I rarely (never) have problems. That is a strength from a user experience perspective but a WTF? from a CTO perspective.
Hopefully this deeper-dive will prompt some interest and curiosity about Docker, Django, Traefik, and especially IntercoolerJS. It is simple, easy to work with, and allows you to grow out of it when the time comes.