Running Docker images 24/7 on GCP for $1.83/month (using Konlet & Pulumi)

Sometimes your hobby project needs to run something continuouly, even in this ‘serverless-era’. In most situations you could get away with CronJobs (Google Cloud Scheduler) and static hosting & serverless functions, but not always. For example, if you consume an API that is only available over WebSockets, like when building a chat bot for example.

These applications often sit idle most of the time. They simply leave the connection running, “awaking” only when a message comes in. If there is computationally expensive processing involved for each message you could easily offload this to a high powered serverless function.

Most people would now consider renting a VPS or VM with Linode, DigitalOcean or some other company. Their cheapest offers are often around $60/year (5$/month) which is just a tad too much for my hobby projects.

There is however, a very cheap alternative on GCP: using “preemptible” or “spot” machines that live temporarily and are replaced (at most once a day) irregularly. The savings with respect to regular e2-machines is around 60-91%, for a total cost of around 1.83$/month for e2-micro (2 vCPU / 1GB mem).

The only downside is that 1) you need to deal with GCP VM’s, which are not simple Docker images, and 2) need a Managed Instance Group with an Instance Template so that a new instance can be created if the old one is removed by Google. The first problem can be solved by using Konlet and the second problem by using a few cli commands.

export DOCKER_IMAGE=gcr.io/cloud-marketplace/google/nginx1:15

# Single instance (will not be preemptible/cheap!)
gcloud compute instances create-with-container VM_NAME \
    --container-image $DOCKER_IMAGE \
    --machine-type e2-micro

# or with a MIG and template
gcloud compute instance-templates create-with-container nginx-template \
    --container-image $DOCKER_IMAGE \
    --machine-type e2-micro \
    --preemptible
gcloud compute instance-groups managed create example-group \
    --base-instance-name nginx-vm --size 1 --template nginx-template

The last hurdle is that it is not convenient to update this Instance Template when you publish a new Docker image. That is where my konlet-pulumi project comes in. Simply copy that repo (and Star it thank you) into your project to hit the road running: by running pulumi up you can now instantly deploy a new version of your cheap Dockerized GCP VM.

N.B.: There is also f1-micro with 0.2 vCPU’s which is included in the Free Tier, but you can not create endless instances of those within the Free Tier, and outside of the free tier it is more expensive than e2-micro.