Vue Storefront is now Alokai! Learn More
Extensions / Custom applications / Middleware

Extensions / Custom applications / Middleware

During various phases of the project, your application might require some functionality that's not provided by the main application. To solve that problem you can run an additional service that has that functionality beside the main application.

Alokai Cloud allows you to run any Docker container on our Cloud beside your Alokai as a part of your instance.

To jump straight into the code, go to the deployment section where you will learn several ways to deploy your custom applications.

To see all possible options for configuring custom applications, check available settings

You will find examples of the actions that you can execute on custom applications in Configuring custom applications paragraphs.

Requirements

All docker images of the additional applications or middlewares have to be stored in our internal Docker Registry. Custom applications have to be enabled prior to executing any actions on them. Consult Enable custom applications.

Configuring custom applications

Enable custom applications

For safety reasons, custom applications can only be enabled by Alokai. If you want to deploy your custom application to your instance please reach out to our support first. After custom applications feature is enabled, you will be able to control additional_apps section yourself.

Deploy custom application

To deploy a custom application use a PATCH method. Provide $CLOUD_USERNAME and $CLOUD_PASSWORD environment variables, the name of the application in the JSON object and fill other properties. Replace all <...> accordingly to your instance data.

curl -s -H 'X-User-Id: $CLOUD_USERNAME'  -H 'X-Api-Key: $CLOUD_PASSWORD' -H 'Content-Type: application/json' -X PATCH -d'
{
  "additional_apps": {
    "apps":[
      {
        "name":"<additional-application-name>",
        "tag":"<docker-image-tag>",
        "image":"<docker-image-name>",
        "path":"/<path>",
        "port":"<port>"
      }
    ]
  }
}' https://farmer.storefrontcloud.io/instance/<your-instance-namespace>

Detailed information regarding possible options can be found in Available settings section.

Delete or deploy new application

A PUT request can be used to add a new application or to modify or delete an existing one.

PUT requests will overwrite the whole instance.

PUT method is overwriting all instance data with the data passed in the request - because of that use it with extreme caution. Be sure to include a complete instance dataset if you execute PUT requests.

curl -s -H 'X-User-Id: $CLOUD_USERNAME'  -H 'X-Api-Key: $CLOUD_PASSWORD' -H 'Content-Type: application/json' -X PUT -d'
{
  "additional_apps": {
    "apps":[
      {
        "name":"<additional-application-name>",
        "tag":"<docker-image-tag>",
        "image":"<docker-image-name>",
        "path":"/<path>",
        "port":"<port>"
      },
      {
        "name":"<additional-application-name-2>",
        "tag":"<docker-image-tag>",
        "image":"<docker-image-name>",
        "path":"/<path>/2",
        "port":"<port>"
      }
    ]
  }
}' https://farmer.storefrontcloud.io/instance/${{ secrets.PROJECT_NAME }}-storefrontcloud-io

When you delete a custom application, it will get scaled down to zero replicas at first, allowing the connections to close, and after that it will be removed.

Available Settings

  • name: string - the name of your custom application - it should be unique within an instance scope
  • tag: string - docker image tag - it should be different tag for each application version
  • image: string - docker image name - the name will be in the registry.vuestorefront.cloud/<your-instance-namespace>-storefrontcloud-io/<additional-application-name> format. You don't have to use <additional-application-name> a the end of docker image name but we strongly recommend it
  • path: string - your application will be serving requests on this path, eg. <your-instance-namespace>.<region>.vuestorefront.cloud/path. A base path. It should be unique within an instance scope
  • port: string - port on which your custom application is listening
  • has_base_path: bool - boolean that disables/enable the value of path as a base path. Defaults to true

High Availability

You can configure High Availability for your custom application - meaning that there will be two replicas of each of the custom application running in case one of them fails.

curl -s -H 'X-User-Id: $CLOUD_USERNAME'  -H 'X-Api-Key: $CLOUD_PASSWORD' -H 'Content-Type: application/json' -X PATCH -d'
{
  "additional_apps": {
    "apps":[
      {
        ...
      },
      {
        ...
      }
    ],
    "ha": {
      "enabled": true
    }
  }
}' https://farmer.storefrontcloud.io/instance/${{ secrets.PROJECT_NAME }}-storefrontcloud-io

Remember that high availability ha setting is being applied to every custom application from your additional_apps as it is at the same level as apps.

GitHub Actions example

This snippet of a GitHub Actions workflow file shows the whole process starting from building a Docker image to deploying your apps. Replace <..> brackets with your instance or custom application data.

name: Deploy Additional Application to Alokai Cloud

on:
  push:
    branches:
      - master

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v1
      - name: Build and publish docker image
        uses: elgohr/Publish-Docker-Github-Action@master
        with:
          name: ${{ secrets.PROJECT_NAME }}-storefrontcloud-io/vue-storefront:${{ github.sha }}
          registry: ${{ secrets.DOCKER_REGISTRY_URL || 'registry.vuestorefront.cloud' }}
          username: ${{ secrets.CLOUD_USERNAME }}
          password: ${{ secrets.CLOUD_PASSWORD }}
          dockerfile: Dockerfile
          buildoptions: "--compress"
  deploy:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - uses: chrnorm/deployment-action@releases/v1
        name: Create GitHub deployment
        id: deployment
        with:
          token: "${{ github.token }}"
          target_url: https://<instance-domain>/<path>
          environment: production
          initial_status: in_progress
      - name: Deploy on <instance-domain>/<path>
        run: |
          if curl -s -H 'X-App-Ip ${{ secrets.CLOUD_USERNAME }}'  -H 'X-Api-Key: ${{ secrets.CLOUD_PASSWORD }}' -H 'Content-Type: application/json' -X PATCH -d '
            {
              "additional_apps": {
                "apps": [
                  {
                    "name": "${{ secrets.PROJECT_NAME }}-storefrontcloud-io",
                    "tag": "${{ github.sha }}",
                    "image": "${{ secrets.DOCKER_REGISTRY_URL || 'registry.vuestorefront.cloud' }}/${{ secrets.PROJECT_NAME }}-storefrontcloud-io/<additional-application-name>",
                    "path": "/<path>",
                    "port": "<port>"
                  }
                ]
              }
            }
          ' https://farmer.storefrontcloud.io/instance/${{ secrets.PROJECT_NAME }}-storefrontcloud-io | grep -q '{"code":200,"result":"Instance updated!"}'; then
            echo "Instance updated"
          else
            echo "Something went wrong during the update process..."
            exit 1
          fi
      - name: Update deployment status (success)
        if: success()
        uses: chrnorm/deployment-status@releases/v1
        with:
          token: "${{ github.token }}"
          target_url: https://<instance-domain>/<path>
          state: "success"
          description: Congratulations! The deploy is done.
          deployment_id: ${{ steps.deployment.outputs.deployment_id }}
      - name: Update deployment status (failure)
        if: failure()
        uses: chrnorm/deployment-status@releases/v1
        with:
          token: "${{ github.token }}"
          target_url: https://<instance-domain>/<path>
          description: Unfortunately, the instance hasn't been updated.
          state: "failure"
          deployment_id: ${{ steps.deployment.outputs.deployment_id }}

All variables used in this example are exactly the same as variables used in curl example.