Table of Contents
Was this article helpful?

1  out of  2 found this helpful

Try Vultr Today with

$50 Free on Us!

Want to contribute?

You could earn up to $600 by adding new articles.

How to Deploy Strapi on the Vultr Kubernetes Engine

Author: Mirdul Swarup

Last Updated: Wed, Jul 12, 2023
CMS Kubernetes Node.js


Strapi is a headless Content Management System (CMS) that assists users to create and manage content for various platforms such as websites, web, and mobile applications. It offers a user-friendly UI admin dashboard that allows users to edit, delete or add content without prior technical knowledge. Users can also define content types and data structures providing more flexibility in content customization. Its seamless integration with third-party tools allows users to connect with different front-end frameworks, databases, and third-party services.

strapi flow chart

Strapi can handle large amounts of content and serve it to a growing number of users, which makes it suitable to deploy on a Kubernetes cluster for scalability and deployment in multiple environments. It also provides role-based authentication and user permissions to ensure that only authorized individuals can access or modify your content making it a secure application to run in a cluster.

This article explains how to deploy a Strapi application, containerize, deploy, and scale it on a Vultr Kubernetes Engine (VKE) cluster.


Before you begin, you should:

Build a Strapi Application

  1. Add the Node.js repository to the server.

    $ curl -sL | sudo -E bash -  
  2. Install Node.js

    $ sudo apt install nodejs
  3. Using the npx utility, create a new project.

    $ npx create-strapi-app@latest strapi-project 

    The above command creates a new Strapi application called strapi-project. Then installs the latest version of the create-strapi-app package. The package creates the necessary structure and installs all necessary dependencies.

    When prompted, press enter to Choose Quickstart as your installation type.

    Once installation is complete, press CTRL + C to stop the server and configure other application values.

  4. Change to the project directory.

    $ cd strapi-project

Containerize the Strapi Application

In this section, configure your Strapi application to use a Vultr Managed Database for PostgreSQL, then set up an environment variable in the app's server file. Additionally, build the app's docker container image to deploy it on the Kubernetes cluster as described below.

  1. Back up the original config/database.js file.

    $ mv config/database.js config/database.ORIG
  2. Using a text editor such as nano, re-create the file.

    $ nano config/database.js
  3. Add the following configurations to the file.

           module.exports = ({ env }) => ({
               connection: {
                   client: 'postgres',
                   connection: {
                       host: env('DATABASE_HOST', ''),
                       port:'DATABASE_PORT', 5432),
                       database: env('DATABASE_NAME', 'default'),
                       user: env('DATABASE_USERNAME', 'user'),
                       password: env('DATABASE_PASSWORD', 'password'),
                       schema: env('DATABASE_SCHEMA', 'public'), // Not required
                       ssl: {
                           rejectUnauthorized: env.bool('DATABASE_SSL_SELF', false),
                   debug: false,

    Save and close the file.

    The above configuration defines the database connection details for the PostgreSQL database. Replace, 5432, user, and password with your actual database details.

  4. Back up the original config/server.js file.

    $ mv config/server.js config/server.ORIG
  5. Re-create the file.

    $ nano config/server.js
  6. Add the following configurations to the file.

     module.exports = ({ env }) => ({
           host: env('HOST', ''),
           port:'PORT', 1337),
           url: env('STRAPI_URL'),
           app: {
             keys: env.array('APP_KEYS'),
           webhooks: {
             populateRelations: env.bool('WEBHOOKS_POPULATE_RELATIONS', false),

    Save and close the file.

    The above code exports a configuration object that sets the host, port, url, and webhooks settings for the Strapi application. It also retrieves values from the environment variable.

  7. Define the STRAPI_URL environment variable.

    $ export STRAPI_URL=""

    The above command sets the environment variable STRAPI_URL to the localhost Strapi server and port.

  8. Install the PostgreSQL library for Node.js to enable the database connection.

    $ npm install pg --save
  9. Rebuild the package.

    $ npm run build

    The above command runs the app's build script to incorporate all changes to the files.

  10. Start the application in the background.

     $ npm run start &

    The above command starts the application in the production environment state. To verify that the Strapi Application runs correctly. Load port 1337 using your Server IP in a web browser.

    The Strapi dashboard should appear with a login screen appears to create the first administrator.

    Strapi Application Dashboard

Create the Docker Image

  1. Within the project directory, create a new Dockerfile.

    $ nano Dockerfile
  2. Add the following contents to the file.

    FROM node:16-alpine
    RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev nasm bash vips-dev
    ARG NODE_ENV=development
    WORKDIR /opt/
    COPY package.json package-lock.json ./
    RUN npm install
    ENV PATH /opt/node_modules/.bin:$PATH
    WORKDIR /opt/app
    COPY . .
    RUN chown -R node:node /opt/app
    USER node
    RUN ["npm", "run", "build"]
    EXPOSE 1337
    CMD ["npm", "run", "start"]

    Save and close the file.

    The above instructions inherit the base as node:16-alpine. It installs various dependencies necessary for the application. It uses /opt/app as a working directory and copies the package.json and the package-lock.json and installs the dependencies using npm install.

    The configuration exposes the Strapi port 1337 which is the default port used by Strapi, then starts the server using the npm run start command.

  3. Create a file named .dockerignore.

    $ nano .dockerignore

    The .dockerignore file declares a list of files and directories to ignore while building the image.

  4. Add the following content to the file


    The above directive prevents duplication of libraries installed on the host machine and lets Docker install all libraries under the dependencies section.

  5. Log in to your DockerHub account.

    $ docker login

    Enter your DockerHub username and password when prompted. To create a new username, visit the DockerHub registry.

  6. Build the Docker image.

    $ docker build -t example-user/strapi:latest .
  7. Push the image to DockerHub.

    $ docker push example-user/strapi:latest

Prepare the Kubernetes Cluster

You must prepare the Kubernetes cluster for deploying the Strapi application by installing the required plugins and creating a few resources. This section demonstrates the steps to install the ingress-nginx controller, install the cert-manager plugin, and create a ClusterIssuer resource for issuing Let's Encrypt certificates.

Before Installing the Strapi application, prepare the Kubernetes cluster with the necessary plugins and resources as described in this section.

  1. Install CertManager to issue SSL certificates.

    $ kubectl apply -f <>
  2. Get the load balancer IP address.

    $ kubectl get services/ingress-nginx-controller -n ingress-nginx


    NAME                       TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
    ingress-nginx-controller   LoadBalancer     80:30420/TCP,443:30061/TCP   7m37s

    The load balancer may take up to 10 minutes to get ready. You can verify the load balancer deployment by opening the cluster page in your customer portal and navigating to the Linked Resources tab. Set up your domain A record for to point to the load balancer's IP Address.

  3. Create a new manifest named clusterissuer.yaml.

    $ nano clusterissuer.yaml
  4. Add the following contents to the file.

         kind: ClusterIssuer
             name: letsencrypt-prod
                 server: <>
                 email: "<>"
                     name: letsencrypt-prod
                     - http01:
                             class: nginx

    Save and close the file.

    The above configuration creates a ClusterIssuer resource for issuing Let's Encrypt certificates. It uses the HTTP01 challenge solver to verify the ownership. Replace with your actual email address.

  5. Apply the Issuer to the cluster.

    $ kubectl apply -f clusterissuer.yaml
  6. Verify the deployment.

    $ kubectl get clusterissuer letsencrypt-prod


    NAME               READY   AGE
    letsencrypt-prod   True   8m27s

Deploy the Strapi Application

  1. Create a new deployment file strapi-deployment.yaml.

    $ nano strapi-deployment.yaml
  2. Add the following configurations to the file.

     apiVersion: apps/v1
     kind: Deployment
       name: strapi-deployment
       replicas: 2
           name: strapi-app
             name: strapi-app
             - name: regcred
             - name: strapi
               image: example-user/strapi:latest
               imagePullPolicy: Always
               command: ["npm", "run", "build", "&&", "npm", "run", "develop"]
                 - containerPort: 1337
                 - name: STRAPI_URL
                   value: ""

    Save and close the file.

    The above configuration creates a Deployment resource:

    • It creates 2 initial pods with the container image you built, and the pods have the label strapi-app.

    • It uses the regcred secret resource to fetch the credentials. Replace the image example-user/strapi:latest with your actual repository.

    • Replace with your actual domain pointing to the cluster load balancer.

  3. Create the deployment.

    $ kubectl apply -f strapi-deployment.yaml
  4. Verify the deployment

    $ kubectl get deployment strapi-deployment


      NAME                READY   UP-TO-DATE   AVAILABLE   AGE
      strapi-deployment   1/2     2            1           20m
  5. Create a new service manifest.

    $ nano strapi-service.yaml
  6. Add the following configurations to the file.

         apiVersion: v1
         kind: Service
             name: strapi-service
               - name: http
                 port: 80
                 protocol: TCP
                 targetPort: 1337
               name: strapi-app
  7. Apply the Service.

    $ kubectl apply -f strapi-service.yaml
  8. Create a new Ingree Manifest.

    $ nano strapi-ingress.yaml
  9. Add the following configurations to the file.

     kind: Ingress
       name: strapi-ingress
         - secretName: strapi-tls
         - host:
               - path: /
                 pathType: Prefix
                     name: strapi-service
                       number: 80

    Save and close the file.

    The Ingress resource allows external access to the strapi-service resource. It uses the cluster issuer resource letsencrypt-prod to issue a new SSL certificate for and store it as a secret resource strapi-tls.

  10. Apply the Ingress resource.

     $ kubectl apply -f strapi-ingress.yaml
  11. Verify the Ingress resource.

     $ kubectl get ingress


    NAME             CLASS    HOSTS                  ADDRESS          PORTS     AGE
    strapi-ingress   <none>   80, 443   10m
  12. In a web browser, visit the Strapi application and verify that you can access the Strapi Application over HTTPS.

Scale the Strapi Deployment

Scaling the Strapi application makes it efficient to handle large loads of traffic without any interruption or downtime. In this section, scale the Strapi deployments by increasing the number of replicas.

  1. Increase the number of running replicas.

    $ kubectl scale deployment/strapi-deployment --replicas=4

    The above command increases the number of running replicas to 4.

  2. Check the deployment status.

    $ kubectl get deployment strapi-deployment


      NAME                READY   UP-TO-DATE   AVAILABLE   AGE
      strapi-deployment   0/4     4            0           29m
  3. View available Pods.

    $ kubectl get pods
  4. Decrease the number of pods.

    $ kubectl scale deployment/strapi-deployment --replicas=2

You can also run the kubectl delete pod command to do a fault tolerance check. Kubernetes detects changes that occur by the command and automatically creates a new pod instantly. New pods are then detected by the ingress resource which starts serving requests instantly.


In this article, you created an example Strapi application using the Strapi API with PostgreSQL configuration along with its containerization, deployment, and scaling. You also configured CertManager to issue Let's Encrypt certificates and the Nginx Ingress controller to allow external access to cluster services.

Strapi focuses on efficient content management via a web interface without the need for technical knowledge which makes it to build low-code or no-code backends. For more information, visit the following resources.

Want to contribute?

You could earn up to $600 by adding new articles.