🚨 Announcement: A New Chapter for Vendure read more

← Back to the blog

Serverless e-commerce: Vendure on Google Cloud Run

Author avatar
November 30, 2021
Martijn van de Brug

Google’s Cloud Run is a scalable, containerized, fully managed serverless platform. It’s cheap and handles infrastructure and scaling for us. Sounds perfect to run a headless Vendure instance on, right?

Here is what we need to do. Don’t worry, for most of these you can use a plugin:

  • Create a database
  • Use Cloud Storage for assets
  • Use Cloud Tasks to process worker jobs
  • Dockerize Vendure
  • Build image and deploy to Google Cloud Run

We assume you already have:

Create a database for Vendure

Vendure requires a database to store its products, orders, customers etc. In this tutorial, we will use Google’s Cloud SQL: a managed database platform.

  1. Enable Cloud SQL in your dashboard and create a database.
  2. For this example, 1vcpu and 10 GB SSD is sufficient. PostgreSQL or MySQL is up to you. Make sure to write down the password you entered.
  3. Create a database named vendure
  4. Click on your instance, and go to connection > add network. Create a new network with IP range 0.0.0.0/0. Careful with production environments, this will make your SQL instance publicly available!

Configure Vendure to use the new database:

// vendure-config.ts
dbConnectionOptions: {
    type: 'mysql',
    synchronize: true, // Disable this after first startup
    logging: false,
    username: 'root', // Don't use this in production
    password: 'your-password',
    host: '192.56.298.3', // The public IP of your SQL instance
    database: 'vendure',
},

Setup Cloud Storage

Cloud run instances are stateless, which also means you shouldn’t use its local file system. Instead, we will use Google Cloud Storage.

Create a storage bucket and make it publicly accessible, so that the images can be used in a storefront. You can use this plugin to connect Vendure to the bucket.

Note: In this article, yarn is used, but you can replace these with the equivalent npm commands if you prefer.

yarn add vendure-plugin-google-storage-assets

Then configure the storage strategy:

// vendure-config.ts
plugins: [
  AssetServerPlugin.init({
    storageStrategyFactory: () => new GoogleStorageStrategy({bucketName: 'your-bucket-name'}),
    route: 'assets',
    assetUploadDir: '/tmp/vendure/assets',
  })
],

Alternatively, you can implement the AssetStorageStrategy yourself.

Setup Cloud Tasks

Cloud run allows no processing outside request context. As soon as your server returned a response, there is no guarantee that any leftover processes will be finished. Because of this, we need some way to wrap the Vendure worker Jobs in a request. We can do that with this plugin.

yarn add vendure-plugin-google-cloud-tasks

This plugin puts jobs in a queue and Cloud Tasks posts the messages back to a publicly available endpoint in your Vendure application.

// vendure-config.ts
plugins: [
  CloudTasksPlugin.init({
    // This endpoint needs to be accesible by Google Cloud Tasks
    taskHandlerHost: 'https://your-instance-sds34vbs-ew.a.run.app', 
    projectId: 'your-projectId',
    location: 'europe-west1',
    authSecret: 'some-secret',
  }),
]

For simplicity, we will start the worker in the same instance as the application:

// index.ts
bootstrap(config)
  .then(app => app.get(JobQueueService).start())
  .catch(err => {
    console.log(err);
    process.exit(1);
  });

This is not recommended for production! Read more about the worker here.

Alternatively, you could implement the JobQueueStrategy yourself.

Dockerize Vendure

Cloud Run requires Vendure to be Dockerized. We can simply create a Dockerfile in the root of the project:

# Dockerfile
FROM node:16
WORKDIR /usr/src/app
COPY . .
RUN yarn install --production
RUN yarn build
CMD [ "node", "dist/index.js" ]

Deploy

First we need to build an image and push it to Google’s container registry:

  1. Install docker

  2. Execute these commands in the root of your project:

    docker build -t eu.gcr.io/your-projectId/vendure .
    # Configure docker to use Google authentication
    gcloud auth configure-docker -q
    docker push eu.gcr.io/your-projectId/vendure
    

    Now all that’s left is deploying the image to Google Cloud Run:

    # This sets all your secrets from a .env file in a variable, so we can pass it to Cloud Run
    export ENV_VARS=$(paste -sd, .env)
    gcloud run deploy shops-test \
                --quiet \
                --image "eu.gcr.io/your-projectId/vendure:latest" \
                --region "europe-west1" \
                --platform "managed" \
                --allow-unauthenticated \
                --memory=1G \
                --project=your-projectId \
                --set-env-vars=$ENV_VARS 
    

    Go to https://console.cloud.google.com/run to view your public URL. It should look something like https://your-instance-sds34vbs-ew.a.run.app. Make sure to also set this URL as taskHandlerHost in the Cloud Tasks plugin if you haven’t already.

  3. Go to https://your-instance-sds34vbs-ew.a.run.app/admin and login with your super admin user

  4. Go to products and create a new product

  5. Add an image to the product

  6. Save the product and go back to the overview

  7. Your product should appear in the product overview in the admin

  8. Congratulations, this means everything works as expected!

Make sure you set synchronize: false after the database has been populated!

Some optional improvements:

  1. Set up a separate worker instance
  2. Restrict access to your database to specific IP’s.
  3. Use Unix sockets for database access

That’s it! Reach out to me on Slack if you need any help.

Author avatar
Written by
Martijn van de Brug
Martijn is the Founder of Pinelab, a Vendure partner and active member of the Vendure community.
GitHub logo GitHub logo