Running SailPoint IdentityIQ 8.5 with Docker, MySQL, and Tomcat

Published Jun 13, 2026

Categories: Identity Governance , SailPoint , Docker

Tags: sailpoint-iiq , identityiq , identityiq-8-5 , docker , docker-compose , mysql , tomcat , proxmox , identity-governance

Series: SailPoint IIQ Lab

There are plenty of SailPoint IdentityIQ installation notes for Windows or traditional Linux servers, but not many practical guides for running IdentityIQ in Docker with the database and application tier separated cleanly.

This post walks through a working lab build for SailPoint IdentityIQ 8.5 using:

  • A Linux VM running on Proxmox
  • Docker and Docker Compose
  • A dedicated MySQL container
  • A dedicated Tomcat container
  • Host-mounted directories for database files, application files, logs, and backups
  • The original SailPoint IdentityIQ 8.5 zip/WAR and database scripts

The goal is not to build a production-grade Kubernetes platform. The goal is to create a repeatable IdentityIQ lab environment that is easy to inspect, back up, destroy, and rebuild.

Important: This guide assumes you already have legitimate access to the SailPoint IdentityIQ 8.5 installation zip/WAR and product documentation. It does not redistribute SailPoint software.

Architecture

The final setup uses two separate Docker Compose projects.

flowchart TD A[Linux VM on Proxmox] --> B[Host directory: /srv/sailpoint/iiq85] B --> C[MySQL Compose Project] B --> D[Tomcat / IIQ Compose Project] C --> C1[Container: iiq85-mysql] C1 --> C2[MySQL data files
/srv/sailpoint/iiq85/mysql/data] C1 --> C3[Init SQL scripts
/srv/sailpoint/iiq85/mysql/init-sql] C1 --> C4[MySQL config
/srv/sailpoint/iiq85/mysql/conf.d] D --> D1[Container: iiq85-tomcat] D1 --> D2[Exploded identityiq webapp
/srv/sailpoint/iiq85/app/webapps/identityiq] D1 --> D3[Tomcat logs
/srv/sailpoint/iiq85/app/logs] D1 --> D4[External files / backups
/srv/sailpoint/iiq85/app/files] D1 -->|JDBC over Docker network| C1

The database and application are intentionally split into separate Compose files:

  • The database can be started, stopped, backed up, and inspected independently.
  • The application tier can be rebuilt without touching database files.
  • All important files live outside the container layers.
  • The setup remains easy to move to another Linux host.

Directory layout

This guide uses the following base path:

/srv/sailpoint/iiq85

The final directory layout looks like this:

/srv/sailpoint/iiq85/
  db/
    docker-compose.db.yml

  iiq/
    docker-compose.iiq.yml

  software/
    IdentityIQ-8.5.zip
    extracted/

  mysql/
    data/
    conf.d/
      iiq.cnf
    init-sql/
      10-create_identityiq_tables-8.5.sql
    backups/

  app/
    webapps/
      identityiq/
    logs/
    files/

  secrets/
    db.env
    iiq-db-users.env

  iiq85-env.sh

The most important design decision is that the persistent state lives on the host:

/srv/sailpoint/iiq85/mysql/data        MySQL data files
/srv/sailpoint/iiq85/app/webapps       Exploded IdentityIQ web application
/srv/sailpoint/iiq85/app/logs          Tomcat logs
/srv/sailpoint/iiq85/app/files         External file and backup area
/srv/sailpoint/iiq85/secrets           Local password files

Prerequisites

This post assumes:

  • A Linux VM or server
  • Docker installed
  • Docker Compose available through docker compose
  • The SailPoint IdentityIQ 8.5 shipped zip file
  • Enough memory for IIQ and MySQL

For a lab VM, I would start with at least:

CPU:     4 vCPU
Memory:  8 GB minimum, 12-16 GB preferred
Disk:    80 GB+ depending on test data

Step 1: Create the host directories

Run these commands on the Linux host:

sudo mkdir -p /srv/sailpoint/iiq85/{db,iiq,software,mysql/data,mysql/conf.d,mysql/init-sql,mysql/backups,app/webapps,app/logs,app/files,secrets}

sudo chown -R "$USER":"$USER" /srv/sailpoint/iiq85
chmod 700 /srv/sailpoint/iiq85/secrets

Check Docker:

docker --version
docker compose version

Step 2: Copy and extract the IdentityIQ 8.5 zip

Copy your SailPoint-provided zip file to:

/srv/sailpoint/iiq85/software/IdentityIQ-8.5.zip

Then extract it:

cd /srv/sailpoint/iiq85/software
unzip -q IdentityIQ-8.5.zip -d extracted

Find the WAR and database script:

find /srv/sailpoint/iiq85/software/extracted -type f -name 'identityiq.war'
find /srv/sailpoint/iiq85/software/extracted -type f -name '*.mysql'

You should see the IdentityIQ WAR and the SailPoint-provided MySQL schema script.

Step 3: Create local secret files

Create a root password file for MySQL:

ROOTPW="$(openssl rand -hex 24)"

cat > /srv/sailpoint/iiq85/secrets/db.env <<'EOF'
MYSQL_ROOT_PASSWORD=replace_this_with_generated_root_password
TZ=UTC
EOF

sed -i "s/replace_this_with_generated_root_password/${ROOTPW}/" /srv/sailpoint/iiq85/secrets/db.env
chmod 600 /srv/sailpoint/iiq85/secrets/db.env

Create IdentityIQ database user passwords:

cat > /srv/sailpoint/iiq85/secrets/iiq-db-users.env <<EOF
IIQ_APP_DB=identityiq
IIQ_APP_USER=identityiq
IIQ_APP_PASSWORD=$(openssl rand -hex 24)

IIQ_PLUGIN_DB=identityiqPlugin
IIQ_PLUGIN_USER=identityiqPlugin
IIQ_PLUGIN_PASSWORD=$(openssl rand -hex 24)

IIQ_AH_DB=identityiqah
IIQ_AH_USER=identityiqah
IIQ_AH_PASSWORD=$(openssl rand -hex 24)
EOF

chmod 600 /srv/sailpoint/iiq85/secrets/iiq-db-users.env

You can view the generated values when needed:

cat /srv/sailpoint/iiq85/secrets/iiq-db-users.env

Do not commit these secret files to Git.

Step 4: Prepare the SailPoint MySQL initialization script

Find the SailPoint MySQL script:

DBSCRIPT="$(find /srv/sailpoint/iiq85/software/extracted -type f -name 'create_identityiq_tables-8.5.mysql' | head -n 1)"
echo "$DBSCRIPT"

Copy it into the MySQL init directory and rename it to .sql:

cp "$DBSCRIPT" /srv/sailpoint/iiq85/mysql/init-sql/10-create_identityiq_tables-8.5.sql

Edit the copied file:

nano /srv/sailpoint/iiq85/mysql/init-sql/10-create_identityiq_tables-8.5.sql

Update the database usernames and passwords to match:

cat /srv/sailpoint/iiq85/secrets/iiq-db-users.env

Keep the database names consistent:

identityiq
identityiqPlugin
identityiqah

MySQL 8.4 authentication note

If the SailPoint script uses this pattern:

CREATE USER 'identityiq'@'%' IDENTIFIED WITH mysql_native_password BY 'password';

change it to:

CREATE USER 'identityiq'@'%' IDENTIFIED BY 'password';

Do the same for the plugin and access history users.

Why? MySQL 8.4 uses caching_sha2_password by default. The older mysql_native_password plugin is disabled by default in MySQL 8.4 and removed in MySQL 9.0. Using IDENTIFIED BY lets MySQL use its default authentication plugin.

Confirm that the deprecated plugin is no longer referenced:

grep -n -i "mysql_native_password" /srv/sailpoint/iiq85/mysql/init-sql/10-create_identityiq_tables-8.5.sql

Ideally, this returns no output.

Step 5: Create the MySQL configuration

Create:

nano /srv/sailpoint/iiq85/mysql/conf.d/iiq.cnf

Add:

[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_0900_ai_ci

innodb_file_per_table=1

sql_mode=STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION

max_allowed_packet=256M
default-time-zone='+00:00'

The key points are:

  • Use a case-insensitive collation.
  • Enable innodb_file_per_table before the schema is created.
  • Do not include ONLY_FULL_GROUP_BY in sql_mode.

Step 6: Create the database Docker Compose file

Create:

nano /srv/sailpoint/iiq85/db/docker-compose.db.yml

Paste:

name: iiq85-db

services:
  mysql:
    image: mysql:8.4
    container_name: iiq85-mysql
    restart: unless-stopped

    env_file:
      - /srv/sailpoint/iiq85/secrets/db.env

    ports:
      - "127.0.0.1:3306:3306"

    volumes:
      - /srv/sailpoint/iiq85/mysql/data:/var/lib/mysql
      - /srv/sailpoint/iiq85/mysql/conf.d:/etc/mysql/conf.d:ro
      - /srv/sailpoint/iiq85/mysql/init-sql:/docker-entrypoint-initdb.d:ro
      - /srv/sailpoint/iiq85/mysql/backups:/backups

    healthcheck:
      test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -uroot -p$${MYSQL_ROOT_PASSWORD} --silent"]
      interval: 10s
      timeout: 5s
      retries: 12

    networks:
      iiq85-net:
        aliases:
          - iiq85-mysql

networks:
  iiq85-net:
    name: iiq85-net
    driver: bridge

Start the database:

docker compose -f /srv/sailpoint/iiq85/db/docker-compose.db.yml up -d

Watch the logs:

docker logs -f iiq85-mysql

The MySQL container only runs scripts in /docker-entrypoint-initdb.d when the data directory is first initialized. If the init fails during a lab build, stop the container, fix the script, clear the data directory, and start again.

For a new lab only:

docker compose -f /srv/sailpoint/iiq85/db/docker-compose.db.yml down
sudo find /srv/sailpoint/iiq85/mysql/data -mindepth 1 -maxdepth 1 -exec rm -rf {} +
docker compose -f /srv/sailpoint/iiq85/db/docker-compose.db.yml up -d

Do not wipe this directory after you have real data.

Step 7: Verify the database initialization

Load the environment files:

set -a
. /srv/sailpoint/iiq85/secrets/db.env
. /srv/sailpoint/iiq85/secrets/iiq-db-users.env
set +a

Check container health:

docker inspect --format '{{.State.Health.Status}}' iiq85-mysql

Check table counts:

docker exec -i iiq85-mysql mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e "
SELECT table_schema, COUNT(*) AS table_count
FROM information_schema.tables
WHERE table_schema IN ('$IIQ_APP_DB', '$IIQ_PLUGIN_DB', '$IIQ_AH_DB')
GROUP BY table_schema
ORDER BY table_schema;
"

Check the database version table:

docker exec -i iiq85-mysql mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e "
SELECT * FROM \`$IIQ_APP_DB\`.spt_database_version;
"

Test the actual IdentityIQ application user:

docker run --rm \
  --network iiq85-net \
  -e MYSQL_PWD="$IIQ_APP_PASSWORD" \
  mysql:8.4 \
  mysql -h iiq85-mysql -u"$IIQ_APP_USER" "$IIQ_APP_DB" -e "SELECT COUNT(*) AS version_rows FROM spt_database_version;"

If this works, IdentityIQ should be able to connect to the database.

Step 8: Explode the IdentityIQ WAR

Set variables:

export BASE=/srv/sailpoint/iiq85
export APP=$BASE/app/webapps/identityiq

Find the WAR:

WAR="$(find "$BASE/software/extracted" -type f -name 'identityiq.war' | head -n 1)"
echo "$WAR"

Create the exploded web application directory:

rm -rf "$APP"
mkdir -p "$APP"
mkdir -p "$BASE/app/logs"
mkdir -p "$BASE/app/files"

Extract the WAR:

unzip -q "$WAR" -d "$APP"
chmod +x "$APP/WEB-INF/bin/iiq"

Verify:

ls -l "$APP/WEB-INF/bin/iiq"
ls -l "$APP/WEB-INF/classes/iiq.properties"

Step 9: Check the MySQL JDBC driver

Look for a MySQL Connector/J driver in the WAR:

find "$APP/WEB-INF/lib" -maxdepth 1 -type f \( -iname 'mysql-connector*.jar' -o -iname 'mysql-connector-j*.jar' -o -iname '*mysql*.jar' \) -print

If nothing is found, look in the extracted SailPoint package:

FOUND_JDBC="$(find "$BASE/software/extracted" -type f \( -iname 'mysql-connector*.jar' -o -iname 'mysql-connector-j*.jar' -o -iname '*mysql*.jar' \) | head -n 1)"
echo "$FOUND_JDBC"

If you find one, copy it:

cp "$FOUND_JDBC" "$APP/WEB-INF/lib/"

If you need to download MySQL Connector/J 8.4.0:

mkdir -p "$BASE/software/jdbc"

curl -fL \
  -o "$BASE/software/jdbc/mysql-connector-j-8.4.0.jar" \
  "https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/8.4.0/mysql-connector-j-8.4.0.jar"

cp "$BASE/software/jdbc/mysql-connector-j-8.4.0.jar" "$APP/WEB-INF/lib/"

Step 10: Configure iiq.properties

Load the database user values:

set -a
. /srv/sailpoint/iiq85/secrets/iiq-db-users.env
set +a

Back up the original file:

PROP=/srv/sailpoint/iiq85/app/webapps/identityiq/WEB-INF/classes/iiq.properties
cp -a "$PROP" "$PROP.bak.$(date +%Y%m%d-%H%M%S)"

Update the database settings:

python3 - <<'PY'
import os
import pathlib
import re

base = pathlib.Path("/srv/sailpoint/iiq85")
prop = base / "app/webapps/identityiq/WEB-INF/classes/iiq.properties"

jdbc_common = "useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC"

vals = {
    "dataSource.driverClassName": "com.mysql.cj.jdbc.Driver",
    "dataSource.url": f"jdbc:mysql://iiq85-mysql:3306/{os.environ['IIQ_APP_DB']}?{jdbc_common}",
    "dataSource.username": os.environ["IIQ_APP_USER"],
    "dataSource.password": os.environ["IIQ_APP_PASSWORD"],

    "pluginsDataSource.driverClassName": "com.mysql.cj.jdbc.Driver",
    "pluginsDataSource.url": f"jdbc:mysql://iiq85-mysql:3306/{os.environ['IIQ_PLUGIN_DB']}?{jdbc_common}",
    "pluginsDataSource.username": os.environ["IIQ_PLUGIN_USER"],
    "pluginsDataSource.password": os.environ["IIQ_PLUGIN_PASSWORD"],

    "dataSourceAccessHistory.driverClassName": "com.mysql.cj.jdbc.Driver",
    "dataSourceAccessHistory.url": f"jdbc:mysql://iiq85-mysql:3306/{os.environ['IIQ_AH_DB']}?{jdbc_common}",
    "dataSourceAccessHistory.username": os.environ["IIQ_AH_USER"],
    "dataSourceAccessHistory.password": os.environ["IIQ_AH_PASSWORD"],
}

lines = prop.read_text().splitlines()
out = []
seen = set()

for line in lines:
    replaced = False
    for key, value in vals.items():
        if re.match(r"^\s*#?\s*" + re.escape(key) + r"\s*=", line):
            out.append(f"{key}={value}")
            seen.add(key)
            replaced = True
            break
    if not replaced:
        out.append(line)

missing = [key for key in vals if key not in seen]
if missing:
    out.append("")
    out.append("# Docker/MySQL configuration added during IIQ 8.5 setup")
    for key in missing:
        out.append(f"{key}={vals[key]}")

prop.write_text("\n".join(out) + "\n")
print(f"Updated {prop}")
PY

Verify without printing passwords:

grep -nE '^(dataSource|pluginsDataSource|dataSourceAccessHistory)\.(driverClassName|url|username|password)=' "$PROP" \
  | sed -E 's/(password=).*/\1****/'

The database hostname must be:

iiq85-mysql

Do not use localhost inside iiq.properties. From inside the Tomcat container, localhost means the Tomcat container itself, not the MySQL container.

Step 11: Import init.xml

Run the initial IdentityIQ import before starting Tomcat:

docker run --rm -i \
  --name iiq85-init \
  --network iiq85-net \
  -v /srv/sailpoint/iiq85/app/webapps:/usr/local/tomcat/webapps \
  -v /srv/sailpoint/iiq85/app/logs:/usr/local/tomcat/logs \
  -v /srv/sailpoint/iiq85/app/files:/iiq-files \
  -e JAVA_TOOL_OPTIONS="--add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED -Dfile.encoding=UTF-8 -Duser.timezone=UTC -Xms512m -Xmx2048m" \
  tomcat:9.0-jdk17-temurin \
  bash -lc 'cd /usr/local/tomcat/webapps/identityiq/WEB-INF/bin && chmod +x iiq && printf "import init.xml\nquit\n" | ./iiq console'

If you plan to use Lifecycle Manager features, import init-lcm.xml as well:

docker run --rm -i \
  --name iiq85-init-lcm \
  --network iiq85-net \
  -v /srv/sailpoint/iiq85/app/webapps:/usr/local/tomcat/webapps \
  -v /srv/sailpoint/iiq85/app/logs:/usr/local/tomcat/logs \
  -v /srv/sailpoint/iiq85/app/files:/iiq-files \
  -e JAVA_TOOL_OPTIONS="--add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED -Dfile.encoding=UTF-8 -Duser.timezone=UTC -Xms512m -Xmx2048m" \
  tomcat:9.0-jdk17-temurin \
  bash -lc 'cd /usr/local/tomcat/webapps/identityiq/WEB-INF/bin && chmod +x iiq && printf "import ../config/init-lcm.xml\nquit\n" | ./iiq console'

Do not re-import init.xml repeatedly unless you know exactly why you are doing it.

Step 12: Create the Tomcat / IdentityIQ Compose file

Create:

nano /srv/sailpoint/iiq85/iiq/docker-compose.iiq.yml

Paste:

name: iiq85-app

services:
  iiq:
    image: tomcat:9.0-jdk17-temurin
    container_name: iiq85-tomcat
    restart: unless-stopped

    environment:
      TZ: UTC
      JAVA_TOOL_OPTIONS: >-
        --add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED
        -Dfile.encoding=UTF-8
        -Duser.timezone=UTC
      CATALINA_OPTS: >-
        -Xms2048m
        -Xmx4096m

    ports:
      - "8080:8080"

    volumes:
      - /srv/sailpoint/iiq85/app/webapps:/usr/local/tomcat/webapps
      - /srv/sailpoint/iiq85/app/logs:/usr/local/tomcat/logs
      - /srv/sailpoint/iiq85/app/files:/iiq-files

    command:
      - /bin/bash
      - -lc
      - |
        if ! grep -q 'URIEncoding="UTF-8"' /usr/local/tomcat/conf/server.xml; then
          sed -i 's/connectionTimeout="20000"/connectionTimeout="20000" URIEncoding="UTF-8"/' /usr/local/tomcat/conf/server.xml
        fi
        exec catalina.sh run

    networks:
      - iiq85-net

networks:
  iiq85-net:
    external: true
    name: iiq85-net

The important parts are:

  • Tomcat runs separately from MySQL.
  • The exploded identityiq directory is mounted from the host.
  • Logs are written to a host directory.
  • The application connects to MySQL through the Docker network name iiq85-mysql.

Step 13: Start IdentityIQ

Start the Tomcat container:

docker compose -f /srv/sailpoint/iiq85/iiq/docker-compose.iiq.yml up -d

Watch logs:

docker logs -f iiq85-tomcat

Check status:

docker ps --filter "name=iiq85"

Test from the Linux host:

curl -I http://127.0.0.1:8080/identityiq/

Then open the UI:

http://YOUR_LINUX_SERVER_IP:8080/identityiq/

The default login is usually:

Username: spadmin
Password: admin

Change the password immediately.

Step 14: Create a helper environment file

The shell variables used during setup disappear when you log out. Create a helper file:

cat > /srv/sailpoint/iiq85/iiq85-env.sh <<'EOF'
# SailPoint IdentityIQ 8.5 Docker environment

export BASE=/srv/sailpoint/iiq85
export APP=$BASE/app/webapps/identityiq

export DB_COMPOSE=$BASE/db/docker-compose.db.yml
export IIQ_COMPOSE=$BASE/iiq/docker-compose.iiq.yml

export PROP=$APP/WEB-INF/classes/iiq.properties
export SQL=$BASE/mysql/init-sql/10-create_identityiq_tables-8.5.sql

iiq85-load-secrets() {
  set -a
  [ -f "$BASE/secrets/db.env" ] && . "$BASE/secrets/db.env"
  [ -f "$BASE/secrets/iiq-db-users.env" ] && . "$BASE/secrets/iiq-db-users.env"
  set +a
}

iiq85-print() {
  echo "Non-secret IIQ variables:"
  for v in BASE APP DB_COMPOSE IIQ_COMPOSE PROP SQL; do
    printf "%-25s = %s\n" "$v" "${!v}"
  done

  echo
  echo "Secret variables status:"
  for v in MYSQL_ROOT_PASSWORD IIQ_APP_DB IIQ_APP_USER IIQ_APP_PASSWORD IIQ_PLUGIN_DB IIQ_PLUGIN_USER IIQ_PLUGIN_PASSWORD IIQ_AH_DB IIQ_AH_USER IIQ_AH_PASSWORD; do
    if [ -n "${!v:-}" ]; then
      case "$v" in
        *PASSWORD*) printf "%-25s = %s\n" "$v" "**** set ****" ;;
        *)          printf "%-25s = %s\n" "$v" "${!v}" ;;
      esac
    else
      printf "%-25s = %s\n" "$v" "not loaded"
    fi
  done
}

iiq85-db-up() {
  docker compose -f "$DB_COMPOSE" up -d
}

iiq85-db-down() {
  docker compose -f "$DB_COMPOSE" down
}

iiq85-app-up() {
  docker compose -f "$IIQ_COMPOSE" up -d
}

iiq85-app-down() {
  docker compose -f "$IIQ_COMPOSE" down
}

iiq85-db-logs() {
  docker logs -f iiq85-mysql
}

iiq85-app-logs() {
  docker logs -f iiq85-tomcat
}

iiq85-status() {
  docker ps --filter "name=iiq85"
}

iiq85-console() {
  docker exec -it iiq85-tomcat bash -lc 'cd /usr/local/tomcat/webapps/identityiq/WEB-INF/bin && ./iiq console'
}
EOF

chmod 600 /srv/sailpoint/iiq85/iiq85-env.sh

Load it:

source /srv/sailpoint/iiq85/iiq85-env.sh

Optionally add it to .bashrc:

grep -q "/srv/sailpoint/iiq85/iiq85-env.sh" ~/.bashrc || cat >> ~/.bashrc <<'EOF'

# SailPoint IdentityIQ 8.5 Docker environment
if [ -f /srv/sailpoint/iiq85/iiq85-env.sh ]; then
  source /srv/sailpoint/iiq85/iiq85-env.sh
fi
EOF

Use it:

iiq85-print
iiq85-status
iiq85-db-logs
iiq85-app-logs

Load secrets only when needed:

iiq85-load-secrets

Useful operational commands

Start database:

docker compose -f /srv/sailpoint/iiq85/db/docker-compose.db.yml up -d

Stop database:

docker compose -f /srv/sailpoint/iiq85/db/docker-compose.db.yml down

Start IdentityIQ:

docker compose -f /srv/sailpoint/iiq85/iiq/docker-compose.iiq.yml up -d

Stop IdentityIQ:

docker compose -f /srv/sailpoint/iiq85/iiq/docker-compose.iiq.yml down

Open the IIQ console from the running Tomcat container:

docker exec -it iiq85-tomcat bash -lc 'cd /usr/local/tomcat/webapps/identityiq/WEB-INF/bin && ./iiq console'

Back up the IIQ databases:

set -a
. /srv/sailpoint/iiq85/secrets/db.env
set +a

docker exec iiq85-mysql sh -lc 'mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" --databases identityiq identityiqPlugin identityiqah' \
  > /srv/sailpoint/iiq85/mysql/backups/iiq85-$(date +%F).sql

Troubleshooting notes

Error: Plugin mysql_native_password is not loaded

This happens when the SQL script tries to create users with:

IDENTIFIED WITH mysql_native_password

With MySQL 8.4, edit the script and use:

IDENTIFIED BY 'password'

Then reset the lab database directory and rerun initialization.

Error: IdentityIQ cannot connect to MySQL

Check iiq.properties:

grep -nE '^(dataSource|pluginsDataSource|dataSourceAccessHistory)\.(url|username|password)=' /srv/sailpoint/iiq85/app/webapps/identityiq/WEB-INF/classes/iiq.properties \
  | sed -E 's/(password=).*/\1****/'

The hostname should be:

iiq85-mysql

Not:

localhost

Error: spt_database_version does not exist

The database initialization probably failed or did not run. Check the MySQL logs:

docker logs iiq85-mysql

For a fresh lab, you can wipe the database directory and rerun the corrected init script. Do not do this in an environment with real data.

Tomcat starts but the IdentityIQ UI does not load

Check:

docker logs -f iiq85-tomcat

Common causes are:

  • JDBC driver missing
  • Incorrect database password
  • Wrong database hostname
  • init.xml was not imported
  • MySQL container is not healthy

Final thoughts

This pattern gives you a clean IdentityIQ lab environment without installing MySQL, Java, or Tomcat directly on the Linux host.

The main lessons from this build are:

  • Keep the database and application in separate Compose projects.
  • Store database files, logs, webapp files, and backups outside the containers.
  • Use the SailPoint-provided database scripts, but adjust authentication syntax for MySQL 8.4 if needed.
  • Import init.xml before starting Tomcat.
  • Import init-lcm.xml only if you plan to use Lifecycle Manager features.
  • Save your commonly used paths and helper functions in a reusable shell file.

For a lab, this setup is simple, transparent, and easy to rebuild. For production, you would still need to address TLS, secrets management, backup automation, monitoring, hardening, patching, and SailPoint-supported deployment requirements.

References

  • SailPoint IdentityIQ 8.5 Installation Guide
  • SailPoint IdentityIQ 8.5 Product Documentation
  • MySQL 8.4 Docker deployment documentation
  • MySQL 8.4 authentication plugin documentation
  • Apache Tomcat 9 Docker image documentation