SuiteCRM installation problems with fileshare and Azure Container App

We have installed the latest Bitnami SuiteCRM container image on an Azure Container App. We are using an Azure MySQL Flexserver Instance for the database and have created an Azure Fileshare which is registered to the container app environment. The fileshare is mounted to the container using the mountpoint /bitnami/suitecrm.

When we start the container it is failing to startup because, even though the fileshare is empty, it thinks it is restoring a persisted configuration.

If we start the container without the fileshare it starts up fine using the Azure SQL database.

If we copy files over to the fileshare and remount it the container starts but is very slow. We think this is a caching issue according to chatgpt.

The setup we are using is the same as we have used to deploy the Bitnami Drupal image and this starts up and uses the file share with no issue.

Has anyone successfully deployed SuiteCRM in an Azure container app with an external file share for persistence. If so could they share any information on what they did to get this working properly.

Thanks in advance.

Hello Arnold,

I don’t have a solution to your described problem - just a word of caution:

Additionally, I’ve tried to customize and upgrade a few Bitnami installations. My recommendation is: Don’t use it. It’ll make your life easier in the long run. :wink:

Hi Bastian
thanks for this. I am aware of the recent situation with Bitnami images. Currently we are developing a POC to test the feasibility of using SuiteCRM for a proposed case management system and as we have no familiarity with the product it looked like a good option. It looks like we will have to build our own containerised version using an official SuiteCRM image.

Do you have any hints and tips on how to go about this? We will be running SuiteCRM in a container app with an external Azure file share for persistence and an Azure MySQL Flexserver instance as the database.

Hi
I have managed to resolve this issue by adding the environment variable parameter : SUITECRM_DATA_TO_PERSIST with the values ‘public/legacy/config.php public/legacy/config_override.php public/legacy/custom public/legacy/upload public/legacy/themes public/legacy/cache .env.local’

You have to specify the files and folders that you want to persist.

For info I am deploying V8 to an Azure Container App.

The steps are:

  1. Create a container app environment
  2. Create a storage account and Azure File Share
  3. Mount the file share to the container app environment
  4. Create an Azure MySQL Flexserver instance and blank database
  5. Configure the provided YAML with the container app, MySQL and Fileshare info
  6. Deploy the container app using the YAML

Script used is:
#Set up parameters

SET RESOURCE_GROUP “my-suitecrm-apps-group”
SET ENVIRONMENT_NAME “my-suitecrm-storage-environment”
SET LOCATION “uksouth”
ECHO $RESOURCE_GROUP
ECHO $ENVIRONMENT_NAME
ECHO $LOCATION

#Create a Resource Group
az group create --name $RESOURCE_GROUP --location $LOCATION --query “properties.provisioningState”

#Create a Azure Container App Environment
az containerapp env create --name $ENVIRONMENT_NAME --resource-group $RESOURCE_GROUP --location “$LOCATION” --query “properties.provisioningState”

SET ENVIRONMENT_ID $(az containerapp env show --name $ENVIRONMENT_NAME --resource-group $RESOURCE_GROUP --query “id” --output tsv)
echo $ENVIRONMENT_ID

Set up a storage account

use a unique random identifier

SET RAND 12345678

SET STORAGE_ACCOUNT_NAME “myscrmaca$RAND”
echo “Storage account name is” $STORAGE_ACCOUNT_NAME

az provider register -n Microsoft.Storage
az provider show -n Microsoft.Storage

az storage account create --resource-group $RESOURCE_GROUP --name $STORAGE_ACCOUNT_NAME --location “$LOCATION” --kind StorageV2 --sku Standard_LRS --enable-large-file-share --query provisioningState

#Create a File Share
SET FILE_SHARE_NAME “mysuitecrmfileshare”

az storage share create --name $FILE_SHARE_NAME --account-name $STORAGE_ACCOUNT_NAME --only-show-errors --output table

SET STORAGE_ACCOUNT_KEY $(az storage account keys list --resource-group $RESOURCE_GROUP --account-name $STORAGE_ACCOUNT_NAME --query “[0].value” --output tsv)

echo “Storage Account Key is $STORAGE_ACCOUNT_KEY”

#Create a storage mount
SET STORAGE_MOUNT_NAME “mysuitecrmstoragemount”

az containerapp env storage set --access-mode ReadWrite --azure-file-account-name $STORAGE_ACCOUNT_NAME --azure-file-account-key $STORAGE_ACCOUNT_KEY --azure-file-share-name $FILE_SHARE_NAME --storage-name $STORAGE_MOUNT_NAME --name $ENVIRONMENT_NAME --resource-group $RESOURCE_GROUP --output table

#Create AzureDB Flexserver for MySQL
SET DB_SERVER_NAME suitecrm-db-srv-$RAND # Must be globally unique, ie: ‘SUITECRM-db-srv-’
SET SUITECRM_DB_HOST $DB_SERVER_NAME.mysql.database.azure.com
SET DB_SERVER_SKU GP_Gen5_2 # Azure Database SKU
SET SUITECRM_DB_USER myAdmin # Cannot be ‘admin’.
SET SUITECRM_DB_PASSWORD Zx3$RAND # Must include uppercase, lowercase, and numeric
SET SUITECRM_DB_NAME suitecrm_db

az mysql flexible-server create --name $DB_SERVER_NAME --location $LOCATION --resource-group $RESOURCE_GROUP --admin-user $SUITECRM_DB_USER --admin-password $SUITECRM_DB_PASSWORD --output none

#Create a DB
az mysql flexible-server db create --database-name $SUITECRM_DB_NAME --server-name $DB_SERVER_NAME --resource-group $RESOURCE_GROUP --output none

#Turn off SSL
az mysql flexible-server parameter set -g $RESOURCE_GROUP -s $DB_SERVER_NAME -n require_secure_transport -v OFF

az mysql flexible-server parameter show -g $RESOURCE_GROUP -s $DB_SERVER_NAME -n require_secure_transport

#Test connection to DB
az mysql flexible-server connect -n $DB_SERVER_NAME -u $SUITECRM_DB_USER -p $SUITECRM_DB_PASSWORD -d $SUITECRM_DB_NAME

#Enable Azure Services in the Firewall
az mysql flexible-server firewall-rule create --rule-name AllowAllWindowsAzureIps --resource-group $RESOURCE_GROUP --name $DB_SERVER_NAME --start-ip-address 0.0.0.0 --end-ip-address 0.0.0.0 --output none

#Create the Container App
#upload yaml file before running this part of the script#
SET CONTAINER_APP_NAME “my-suitecrm-app”
az containerapp create -n $CONTAINER_APP_NAME -g $RESOURCE_GROUP --environment $ENVIRONMENT_NAME --yaml suitecrm-aca.yaml

YAML (that needs tailoring) is:
location: uksouth
name: my-suitecrm-app
resourceGroup: my-suitecrm-apps-group
type: Microsoft.App/containerApps
properties:
managedEnvironmentId: /subscriptions/mysubscriptionid/resourceGroups/my-suitecrm-apps-group/providers/Microsoft.App/managedEnvironments/my-suitecrm-storage-environment
configuration:
activeRevisionsMode: Single
dapr: null
ingress:
external: true
allowInsecure: false
targetPort: 8080
traffic:
- latestRevision: true
weight: 100
transport: Auto
registries: null
secrets:
- name: suitecrm-db-name
value: suitecrm_db
- name: suitecrm-db-password
value: Zx312345678
- name: suitecrm-db-user
value: myAdmin
- name: suitecrm-db-host
value: suitecrm-db-srv-12345678.mysql.database.azure.com

service: null

template:
revisionSuffix: ‘’
containers:
- image: docker.io/bitnami/suitecrm:latest
name: suitecrm
env:
- name: SUITECRM_DATABASE_NAME
secretRef: suitecrm-db-name
- name: SUITECRM_DATABASE_PASSWORD
secretRef: suitecrm-db-password
- name: SUITECRM_DATABASE_USER
secretRef: suitecrm-db-user
- name: SUITECRM_DATABASE_PORT_NUMBER
value: ‘3306’
- name: SUITECRM_DATABASE_HOST
secretRef: suitecrm-db-host
- name: BITNAMI_DEBUG
value: ‘true’
- name: SUITECRM_EMAIL
value: ‘john.dunne@cgi.com’
- name: SUITECRM_DATA_TO_PERSIST
value: ‘public/legacy/config.php public/legacy/config_override.php public/legacy/custom public/legacy/upload public/legacy/themes public/legacy/cache .env.local’
resources:
cpu: 2
ephemeralStorage: 8Gi
memory: 4Gi
volumeMounts:
- mountPath: /bitnami
volumeName: mystoragemount
volumes:
- name: mystoragemount
storageName: mysuitecrmstoragemount
storageType: AzureFile
scale:
minReplicas: 1
maxReplicas: 5

This is very flakey and very frustrating although I got this working it broke again.

I tried to persist the API directory by adding it to the end of the files to persist so I could store the API Keys but then the Cache directory and .env.local file did not persist and the default Suite8 theme was not created in the persisted Themes directory.

There are no issues with writing to the fileshare otherwise the other folders would not have been created along with simlinks to the external folders.

I then reverted to exactly the same parameters as before and had similar problems. Even though the Azure fileshare is cleared down each time and the database is recreated.

If you do not attach the fileshare then everything works with the Azure MySQL database.

Problem finally solved. You need to ensure you have liveliness, readiness and startup probes set up with a sufficient duration to allow the SuiteCRM to get through its long initialisation when first run.

I have also added persistence for the API keys and removed the cache persistance to improve performance.

You need to use this environment variable setting:

  - name: SUITECRM_DATA_TO_PERSIST
    value: public/legacy/config.php public/legacy/config_override.php public/legacy/custom
      public/legacy/upload public/legacy/themes public/legacy/Api/V8/OAuth2 .env.local

And add the following probes after the volumeMounts section in the yaml

  probes:
  - type: Startup
    tcpSocket:
      port: 8080
    initialDelaySeconds: 60
    periodSeconds: 20
    timeoutSeconds: 5
    successThreshold: 1
    failureThreshold: 30
  - type: Liveness
    httpGet:
      path: /
      port: 8080
    initialDelaySeconds: 0
    periodSeconds: 10
    timeoutSeconds: 5
    successThreshold: 1
    failureThreshold: 3
  - type: Readiness
    httpGet:
      path: /
      port: 8080
    initialDelaySeconds: 60
    periodSeconds: 10
    timeoutSeconds: 5
    successThreshold: 1
    failureThreshold: 30
1 Like