Stats Web Avec Fathom

Je recherchais depuis quelques temps un outils permettant de calculer et stocker les stats des visites sur mon site. Le plus connu en libre est semble t-il piwik devenu matomo mais la lourdeur de PHP/mysql me rebutait. J’ai tendance à privilégier autant que possible des services en Go, léger et rapide, avec une base sqlite.
Ca tombe bien puisque j’ai découvert fathom qui répond exactement à ce “cahier des charges”.

La page github du projet propose un lien vers leur image docker cependant nul présence d’une image pour ARM64… C’est le moment de se retrousser les manches.

Installation

La première étape est de git clone le projet puis d’adapter leur Dockerfile pour une cible ARM64 :

cat Dockerfile.arm64v8 

FROM arm64v8/node:alpine AS assetbuilder
WORKDIR /app
COPY package*.json ./
COPY gulpfile.js ./
COPY assets/ ./assets/
RUN npm install && NODE_ENV=production ./node_modules/gulp/bin/gulp.js

FROM arm64v8/golang:alpine AS binarybuilder
RUN apk add -U --no-cache git build-base
RUN go get -u github.com/gobuffalo/packr/packr
WORKDIR /go/src/github.com/usefathom/fathom
COPY . /go/src/github.com/usefathom/fathom
COPY --from=assetbuilder /app/assets/build ./assets/build
COPY Makefile.arm64v8 ./
RUN make -f Makefile.arm64v8 docker

FROM arm64v8/alpine:latest
EXPOSE 8080
HEALTHCHECK --retries=10 CMD ["wget", "-qO-", "http://localhost:8080/health"]
RUN apk add --update --no-cache bash ca-certificates
WORKDIR /app
COPY --from=binarybuilder /go/src/github.com/usefathom/fathom/fathom .
CMD ["./fathom", "server"]

A noter que le Dockerfile d’origine lance un make qui utilise ce Makefile, or celui-ci force l’architecture cible en AMD64 :

GOARCH=amd64

J’ai donc copié ce fichier vers un Makefile.arm64v8 où la cible est GOARCH=arm64. Ne pas oublier de faire un COPY de ce nouveau fichier vers le conteneur : COPY Makefile.arm64v8 ./

On peut ensuite lancer un build sur une machine ARM64 :

docker build -f Dockerfile.arm64v8 -t fredix/arm64v8-fathom:latest 
--build-arg http_proxy="http://fredix:PASS@192.168.254.10:3128" 
--build-arg https_proxy="http://fredix:PASS@192.168.254.10:3128" .

les options –build-arg sont nécessaire sur mon infra pour permettre à Docker de sortir vers Internet via un proxy squid. Pour rappel un serveur qui n’a pas d’IP publique chez scaleway ne peut pas sortir vers Internet.

puis

docker push fredix/arm64v8-fathom:latest

Mon image est disponible sur le Docker hub : https://hub.docker.com/r/fredix/arm64v8-fathom

On peut maintenant l’instancier dans le docker swarm :

docker service create --name fathom --constraint 'node.labels.location == cloud-arm64' 
--network traefik-net --label traefik.frontend.rule=Host:fathom.fredix.xyz 
--label traefik.docker.network=traefik-net --label traefik.port=8080 
--label traefik.backend=fathom fredix/arm64v8-fathom:latest
docker service rm fathom

Tel quel fathom va utiliser une base sqlite, mais elle sera stockée dans le conteneur dans /app/fathom.db, or je veux la stocker dans glusterfs. Sur un noeud gluster faire :

mkdir /swarm/volumes/fathom
touch /swarm/volumes/fathom/fathom.db

on peut maintenant lancer le service avec les options de montage qui vont bien

docker service create --name fathom --constraint 'node.labels.location == cloud-arm64' 
--network traefik-net --label traefik.frontend.rule=Host:fathom.fredix.xyz 
--label traefik.docker.network=traefik-net --label traefik.port=8080 
--label traefik.backend=fathom 
--mount type=bind,source=/swarm/volumes/fathom/fathom.db,target=/app/fathom.db 
fredix/arm64v8-fathom:latest

Pour info on ne map pas /app mais directement /app/fathom.db car le binaire fathom se trouve dans /app. Si on map comme ceci

--mount type=bind,source=/swarm/volumes/fathom,target=/app 

/app sera vide dans le conteneur puisqu’il correspondra à celui du serveur hote qui n’a pas le binaire fathom. Le service ne pourrait donc pas démarrer.

Le service est lancé mais attention par défaut l’interface web est publique. Il est nécessaire de créer un utilisateur avec un login/pass. Pour cela il faut savoir sur quel noeud du swarm est lancé le conteneur

docker service ps fathom
ID                  NAME                IMAGE                          NODE                DESIRED STATE       CURRENT STATE          ERROR               PORTS
snp83agcyeps        fathom.1            fredix/arm64v8-fathom:latest   proxy               Running             Running 18 hours ago                       

On se connecte sur le noeud proxy puis un docker ps indique le conteneur ID de fathom

docker ps
CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS                  PORTS               NAMES
eeb508f7fd11        fredix/arm64v8-fathom:latest   "./fathom server"        18 hours ago        Up 18 hours (healthy)   8080/tcp            fathom.1.snp83agcyeps9pv56f4yj5nzl

On peut alors créer l’utilisateur

docker exec eeb508f7fd11 ./fathom user add --email="fredix@protonmail.com" --password="PASS"

L’interface web est maintenant vérouillée comme on peut le constater sur mon instance https://fathom.fredix.xyz/.

Intégration

Une fois connecté l’interface propose de saisir le nom de domaine de son site web afin de générer le javascript à intégrer dans les pages. Ce javascript devra être inséré dans la balise <head></head>. Pour Hugo il suffit de créer un fichier partial dans le thème utilisé

cat themes/blackburn/layouts/partials/fathom.html  
<!-- Fathom - simple website analytics - https://github.com/usefathom/fathom -->
<script>
(function(f, a, t, h, o, m){
	a[h]=a[h]||function(){
		(a[h].q=a[h].q||[]).push(arguments)
	};
	o=f.createElement('script'),
	m=f.getElementsByTagName('script')[0];
	o.async=1; o.src=t; o.id='fathom-script';
	m.parentNode.insertBefore(o,m)
})(document, window, '//fathom.fredix.xyz/tracker.js', 'fathom');
fathom('set', 'siteId', 'MELRX');
fathom('trackPageview');
</script>
<!-- / Fathom -->

puis d’ajouter ce partial dans le partial head.html

cat themes/blackburn/layouts/partials/head.html
...
  {{ partial "fathom.html" . }}
</head>

Après un déploiement les premières stats arrivent

fathom.png

l’interface est plutôt sobre et efficace, même si ce n’est pas aussi complet qu’un matomo c’est largement suffisant. Voir la live demo.

Sources :

https://schaper.io/2018/07/using-fathom-with-postgres-and-docker/
https://www.dwastudio.fr/article/analysez-les-donnees-de-votre-site-simplement-avec-fathom/