Deploy a kmviz instance¶
This page describes how to deploy an instance of kmviz along with a kmindex server and a MySQL DB for metadata using docker compose
, and tlemane/kmviz, tlemane/kmindex, mysql/mysql-server docker images.
0. Index construction¶
This guide does not describe how to build an index. See index construction for instructions.
For the example, we assume that the index was built using: kmindex build -i kmindex_directory/global_index -r index_1 -d kmindex_directory/index_1_directory ...
.
A kmindex index is a directory composed of one json file, index.json
, and one or more symlinks for each registered sub-index. According to the previous command, we have one index index_1
registered in the global index global_index
, as illustrated below.
kmindex_directory
├── global_index
│ ├── index_1 -> /path/to/kmindex_directory/index_1_directory
│ └── index.json
└── index_1_directory
1. The kmindex-service
¶
The kmindex-service
is a docker container that runs a kmindex-server
instance allowing to query kmindex
indexes through HTTP requests.
services:
kmindex-service:
container_name: kmindex-service_cnt
image: tlemane/kmindex:latest
volumes:
- ./kmindex_directory:/home/
entrypoint: kmindex-server
command: "--index /home/global_index -a 0.0.0.0 --port 8080 -d /home/kmindex_logs"
ports:
- "8080:8080"
Patch the index¶
The index produced by kmindex
requires small patches to be used in this configuration. These patches can be applied using the following script.
#!/usr/bin/env bash
index_path=$1
new_path_prefix="/home"
indexes=$(ls --ignore=index.json ${index_path})
for index in ${indexes}
do
path=$(realpath ${index_path}/${index})
base=$(basename ${path})
rm ${index_path}/${index}
ln -s ${new_path_prefix}/${base} ${index_path}/${index}
done
new_index_path=${new_path_prefix}/$(basename ${index_path})
jq --arg new_index_path "$new_index_path" '.path = $new_index_path' ${index_path}/index.json > tmp.json
mv tmp.json ${index_path}/index.json
About the patches
Fix symlinks¶
A kmindex
index is a directory composed of one json file, index.json
, and one or more symlink pointing to the index directories. In the example, only one sub-index index_1
is registered. Within the docker, kmindex_directory
is mounted at /home/
. As a result, the symlink global_index/index_1
should point to the index directory /home/index_1_directory
kmindex_directory
├── index
│ ├── index_1 -> /path/to/kmindex_directory/index_1_directory
│ └── index.json
└── index_1_directory
Fix json index path¶
The index.json
file contains an absolute path to its parent directory, e.g. "path": "<prefix>/kmindex_directory/index"
. This field should be replaced with "path": "/home/<directory_name>"
.
2. The metadata-service
¶
The metadata-service
is a docker container that runs a mysql
server. In this example, the we assume a database mydb
containing a mytable
table. The db is created by init.sql
instructions on the first container run.
services:
metadata-service:
container_name: metadata-service_cnt
image: mysql/mysql-server
environment:
MYSQL_ROOT_PASSWORD: kmviz_password
MYSQL_ROOT_HOST: '%'
volumes:
- mysql-storage:/var/lib/mysql
- init.sql:/home/init.sql # Instructions to create the db and the table
command: "--init-file /home/init.sql"
ports:
- "3036:3036"
# Create a /var/lib/docker/volumes/mysql-storage on the host to
# store the db data in a persistent way.
# 'docker compose down' will not remove the volume
# Use 'docker compose down -v' to delete the volume (and data)
volumes:
- mysql-storage:
3. The kmviz-service
¶
The kmviz-service
is a docker container that runs the kmviz web service. It depends on the previous services kmindex-service
and metadata-service
.
services:
kmviz:
image: tlemane/kmviz:latest
volumes:
- ./kmviz_directory:/home/
depends_on:
- kmindex-service
- metadata-service
command: "-w 1 -u 0.0.0.0 -p 5000"
ports:
- "5000:5000"
[databases]
[databases.TARA]
type = "kmindex-server"
[databases.TARA.params]
url = "kmindex-service"
port = 8080
[databases.TARA.metadata]
type = "mysql"
[databases.TARA.metadata.params]
host = "metadata-service"
database = "mydb"
user = "root"
password = "kmviz_example"
idx = "ID"
table = "mytable"
geodata = { latitude = "Lat", longitude = "Long"}
[cache]
[cache.serverside]
type = "disk"
params.cache_dir = ".results/kmviz_serverside_cache"
params.threshold = 0
params.default_timeout = 86400
[cache.manager]
type = "disk"
params.directory = ".results/kmviz_manager_cache"
[cache.result]
type = "disk"
params.cache_dir = ".results/kmviz_result_cache"
params.threshold = 0
params.default_timeout = 1209600
4. Start the service¶
compose.yml
kmindex_directory
├── global_index
│ ├── index_1 -> /home/index_1
│ └── index.json
└── index_1
kmviz_directory
└── config.toml
services:
kmindex-service:
image: tlemane/kmindex:latest
volumes:
- ./kmindex_directory:/home/
entrypoint: kmindex-server
command: "--index /home/index -a 0.0.0.0 --port 8080 -d /home/kmindex_logs"
ports:
- "8080:8080"
metadata-service:
image: mysql/mysql-server
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_ROOT_HOST: '%'
volumes:
- mysql-storage:/var/lib/mysql
- init.sql:/home/init.sql
command: "--init-file /home/init.sql"
ports:
- "3036:3036"
kmviz-service:
image: tlemane/kmviz:latest
volumes:
- ./kmviz_directory:/home/
depends_on:
- kmindex-service
- metadata-service
command: "-w 1 -u 0.0.0.0 -p 5000"
ports:
- "5000:5000"
volumes:
mysql-storage:
The kmviz instance is now available at localhost:5000
.
Appendix¶
Appendix: Load a kmindex plugin¶
The default docker image does not contain any plugins. To install and use plugins, we create a new docker image based on tlemane/kmviz
as described below.
services:
kmviz-service:
build:
context: ./kmviz_docker
dockerfile: Dockerfile
volumes:
- ./kmviz_directory:/home/
depends_on:
- kmindex-service
- metadata-service
command: "-w 1 -u 0.0.0.0 -p 5000"
ports:
- "5000:5000"
volumes:
mysql-storage:
FROM tlemane/kmviz:latest
RUN apt-get install -y git
ENV PIP_SRC=/opt/
RUN pip install -e "git+https://github.com/tlemane/kmviz.git#subdirectory=plugins/kmviz_instance_plugin&egg=kmviz_instance_plugin"
Appendix: Use Redis caching¶
services:
redis-service:
image: redis:alpine
ports:
- "6379:6379"
kmviz-service:
image: tlemane/kmviz:latest
volumes:
- ./kmviz_directory:/home/
depends_on:
- kmindex-service
- metadata-service
- redis-service
command: "-w 1 -u 0.0.0.0 -p 5000"
ports:
- "5000:5000"
volumes:
mysql-storage:
[databases]
[databases.TARA]
type = "kmindex-server"
[databases.TARA.params]
url = "kmindex-service"
port = 8080
[databases.TARA.metadata]
type = "mysql"
[databases.TARA.metadata.params]
host = "metadata-service"
database = "mydb"
user = "root"
password = "kmviz_example"
idx = "ID"
table = "mytable"
geodata = { latitude = "Lat", longitude = "Long"}
[cache]
[cache.serverside]
type = "redis"
params.host = "redis-service"
params.db = 0
[cache.manager]
type = "disk"
params.directory = ".results/kmviz_manager_cache"
[cache.result]
type = "redis"
params.host = "redis-service"
params.db = 1
Appendix: Load balancing¶
See Compose Deploy Specification
services:
kmindex-service:
image: tlemane/kmindex:latest
volumes:
- ./kmindex_directory:/home/
entrypoint: kmindex-server
command: "--index /home/index -a 0.0.0.0 --port 8080 -d /home/kmindex_logs"
expose:
- 8080
deploy:
replicas: 3
endpoint_mode: dnsrr
Appendix: Analytics with Matomo¶
Requires kmviz
>=v0.3.2
Create the matomo
service¶
services:
matomo:
image: matomo
volumes:
- matomo:/var/www/html:z
environment:
- MATOMO_DATABASE_HOST=matomo
- MYSQL_PASSWORD=password
- MYSQL_DATABASE=matomo
- MYSQL_USER=root
- MATOMO_DATABASE_ADAPTER=mysql
- MATOMO_DATABASE_TABLES_PREFIX=matomo_
- MATOMO_DATABASE_USERNAME=root
- MATOMO_DATABASE_PASSWORD=password
- MATOMO_DATABASE_DBNAME=matomo
depends_on:
- metadata-service
expose:
- 80
ports:
- 8040:80
volumes:
mysql-storage:
matomo:
Note that we use the database hosted by metadata-service
to store the matomo
tables.
Because matomo
does not support headless setup, you have to run the instance to follow the setup wizard.
docker compose up metadata-service matomo
- Go to
localhost:8040
and follow the setup. For thekmviz
url, usehttp/localhost:8090
. - Copy the js tag provided by
matomo
and put inkmviz_directory/template.html
, as described below.
<!DOCTYPE html>
<html>
<head>
{%metas%}
<title>{%title%}</title>
{%favicon%}
{%css%}
</head>
<script>
var _paq = window._paq = window._paq || [];
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//localhost:8040/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '1']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<body>
{%app_entry%}
<footer>
{%config%}
{%scripts%}
{%renderer%}
</footer>
</body>
</html>
kmviz_directory/config.toml
to pass the html template, as described below.
5. Start all the services and finalize the tracking configuration in matomo
.
Self-contained example¶
A self-contained example is available here: self.tar.bz2.