8. Sviluppo ed esecuzione in container
Ci sono molti modi per utilizzare applicazioni containerizzate, dai più semplici (semplici immagini Docker) ai più sofisticati (Kubernetes e così via).
Nota
Questo tipo di sviluppo ha bisogno che l’applicazione docker sia installata e funzionante. Guarda questo tutorial.
Suggerimento
Docker esegue applicazioni preconfezionate (alias immagini) che possono essere recuperate come sorgenti (Dockerfile e risorse) da costruire o già costruite da registri (privati o pubblici).
Nota
I download dei package QGIS Debian-Ubuntu necessitano di una chiave di autenticazione gpg valida. Fare riferimento a installation pages per aggiornare il seguente file Docker.
8.1. Semplici immagini docker
Poiché l’immagine docker non esiste in un registro pubblico, dovrai crearla. Per farlo, crea una cartella qgis-server
e all’interno di essa:
crea un file
Dockerfile
con questo contenuto:
FROM debian:bullseye-slim
ENV LANG=en_EN.UTF-8
RUN apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests --allow-unauthenticated -y \
gnupg \
ca-certificates \
wget \
locales \
&& localedef -i en_US -f UTF-8 en_US.UTF-8 \
# Add the current key for package downloading
# Please refer to QGIS install documentation (https://www.qgis.org/fr/site/forusers/alldownloads.html#debian-ubuntu)
&& mkdir -m755 -p /etc/apt/keyrings \
&& wget -O /etc/apt/keyrings/qgis-archive-keyring.gpg https://download.qgis.org/downloads/qgis-archive-keyring.gpg \
# Add repository for latest version of qgis-server
# Please refer to QGIS repositories documentation if you want other version (https://qgis.org/en/site/forusers/alldownloads.html#repositories)
&& echo "deb [signed-by=/etc/apt/keyrings/qgis-archive-keyring.gpg] https://qgis.org/debian bullseye main" | tee /etc/apt/sources.list.d/qgis.list \
&& apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests --allow-unauthenticated -y \
qgis-server \
spawn-fcgi \
xauth \
xvfb \
&& apt-get remove --purge -y \
gnupg \
wget \
&& rm -rf /var/lib/apt/lists/*
RUN useradd -m qgis
ENV TINI_VERSION v0.19.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod +x /tini
ENV QGIS_PREFIX_PATH /usr
ENV QGIS_SERVER_LOG_STDERR 1
ENV QGIS_SERVER_LOG_LEVEL 2
COPY cmd.sh /home/qgis/cmd.sh
RUN chmod -R 777 /home/qgis/cmd.sh
RUN chown qgis:qgis /home/qgis/cmd.sh
USER qgis
WORKDIR /home/qgis
ENTRYPOINT ["/tini", "--"]
CMD ["/home/qgis/cmd.sh"]
crea un file
cmd.sh
con questo contenuto:
#!/bin/bash
[[ $DEBUG == "1" ]] && env
exec /usr/bin/xvfb-run --auto-servernum --server-num=1 /usr/bin/spawn-fcgi -p 5555 -n -d /home/qgis -- /usr/lib/cgi-bin/qgis_mapserv.fcgi
costruisci l’immagine con:
docker build -f Dockerfile -t qgis-server ./
8.1.1. Prima esecuzione
Per eseguire il server è necessario un file di progetto QGIS. Puoi utilizzare uno tuo o scegliere questo esempio.
Per farlo, crea una cartella data
all’interno della cartella qgis-server
e copia il tuo file al suo interno. Per rispettare le istruzioni seguenti, rinominalo in osm.qgs
.
Nota
Potresti dover aggiungere gli URL consigliati nella scheda QGIS Server della :menuselection: Progetto –> Proprietà se le GetCapabilites sono interrotte. Ad esempio, se il server è esposto sulla porta 8080, si inserirà l’URL pubblicizzato http://localhost:8080/qgis-server/
. Ulteriori informazioni sono disponibili nella sezione Configura il tuo progetto e successive.
Ora, puoi avviare il server con:
docker network create qgis
docker run -d --rm --name qgis-server --net=qgis --hostname=qgis-server \
-v $(pwd)/data:/data:ro -p 5555:5555 \
-e "QGIS_PROJECT_FILE=/data/osm.qgs" \
qgis-server
Opzioni utilizzate:
-d: esecuzione in background
–rm: rimuovere il contenitore quando viene arrestato
–nome: nome del contenitore da creare
–net: (precedentemente creata) sottorete
–hostname: nome host del contenitore, per riferimenti successivi
-v: cartella dati locale da installare nel contenitore
-p: mappatura porte host/contenitore
-e: variabile d’ambiente da utilizzare nel contenitore
Per verificare, digita docker ps | grep qgis-server
e si dovresti vedere una linea con qgis-server:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4de8192da76e qgis-server "/tini -- /home/qgis…" 3 seconds ago Up 2 seconds 0.0.0.0:5555->5555/tcp qgis-server
8.1.2. Esempio utilizzabile
Poiché il server accetta solo connessioni fastcgi, hai bisogno di un server HTTP che gestisca questo protocollo. Per farlo, dobbiamo creare un semplice file di configurazione di Nginx e avviare un’immagine di Nginx.
Crea un file nginx.conf
nella cartella corrente con questo contenuto:
server {
listen 80;
server_name _;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /qgis-server {
proxy_buffers 16 16k;
proxy_buffer_size 16k;
gzip off;
include fastcgi_params;
fastcgi_pass qgis-server:5555;
}
}
E digita questo comando:
docker run -d --rm --name nginx --net=qgis --hostname=nginx \
-v $(pwd)/nginx.conf:/etc/nginx/conf.d/default.conf:ro -p 8080:80 \
nginx:1.13
Per verificare le capabilities disponibili, digita nel browser http://localhost:8080/qgis-server/?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities.
8.1.3. Pulizia
Per rimuovere le immagini in esecuzione, digita:
docker stop qgis-server nginx
8.2. Stack Docker
Il metodo precedente è eseguibile tramite script, ma non è facilmente confezionabile, né standardizzabile o facilmente gestibile.
Per lavorare con un insieme di immagini docker si può usare uno stack docker gestito da un orchestratore. In uno stack, le immagini lavorano nella stessa rete privata ed è possibile avviare/arrestare l’intero stack o distribuirlo ad altri worker. Esistono molti orchestratori, ad esempio Swarm, Kubernetes e Mesos.
Di seguito presenteremo semplici configurazioni a scopo di test. Non sono adatte alla produzione.
8.2.1. Swarm/docker-compose
Docker ha ora un proprio orchestratore: Swarm (compatibile con i file docker-compose). Devi enable it (la versione per Mac funziona anche con Linux).
Descrizione stack
Ora che Swarm funziona, crea il file di servizio (vedi Deploy to Swarm) qgis-stack.yaml
:
version: '3.7'
services:
qgis-server:
# Should use version with utf-8 locale support:
image: qgis-server:latest
volumes:
- REPLACE_WITH_FULL_PATH/data:/data:ro
environment:
- LANG=en_EN.UTF-8
- QGIS_PROJECT_FILE=/data/osm.qgs
- QGIS_SERVER_LOG_LEVEL=0 # INFO (log all requests)
- DEBUG=1 # display env before spawning QGIS Server
nginx:
image: nginx:1.13
ports:
- 8080:80
volumes:
- REPLACE_WITH_FULL_PATH/nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- qgis-server
Per distribuire (o aggiornare) lo stack, digita:
docker stack deploy -c qgis-stack.yaml qgis-stack
Controlla lo stato di distribuzione dello stack fino a ottenere 1/1 nella colonna replicas:
docker stack services qgis-stack
Qualcosa come:
ID NAME MODE REPLICAS IMAGE PORTS
gmx7ewlvwsqt qgis_nginx replicated 1/1 nginx:1.13 *:8080->80/tcp
l0v2e7cl43u3 qgis_qgis-server replicated 1/1 qgis-server:latest
Per verificare le capabilities del WMS, digita in un browser web http://localhost:8080/qgis-server/?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities.
Pulizia
Per pulire, digita:
docker stack rm qgis-stack
8.2.2. Kubernetes
Installazione
Se hai un’installazione di Docker Desktop, l’uso di Kubernetes (alias k8s) è piuttosto semplice: enable k8s.
In caso contrario, segui minikube tutorial o microk8s for Ubuntu.
Poiché l’installazione di Kubernetes può essere molto complessa, ci concentreremo solo sugli aspetti utilizzati in questa demo. Per ulteriori informazioni, consulta official documentation.
microk8s
microk8s necessita di ulteriori passaggi: devi abilitare il registro e etichettare l’immagine qgis-server per far sì che Kubernetes trovi le immagini create.
Per prima cosa, abilita il registro:
microk8s enable dashboard dns registry
Quindi, etichetta e inoltra l’immagine al registro appena creato:
docker tag qgis-server 127.0.0.1:32000/qgis-server && docker push 127.0.0.1:32000/qgis-server
Infine, aggiungi o completa il /etc/docker/daemon.json
per avere il registro 127.0.0.1:32000 elencato nel campo insecure-registries:
{
"insecure-registries": ["127.0.0.1:32000"]
}
Creare manifesti
Kubernetes descrive gli oggetti da distribuire in manifesti yaml. Ne esistono di diversi tipi, ma noi useremo solo i deploy (gestire i pod, cioè le immagini docker) e i servizi per esporre i deploy a scopi interni o esterni.
Manifesti di distribuzione
Crea un file deployments.yaml
con questo contenuto:
apiVersion: apps/v1
kind: Deployment
metadata:
name: qgis-server
namespace: default
spec:
replicas: 1
selector:
matchLabels:
myLabel: qgis-server
template:
metadata:
labels:
myLabel: qgis-server
spec:
containers:
- name: qgis-server
image: localhost:32000/qgis-server:latest
imagePullPolicy: IfNotPresent
env:
- name: LANG
value: en_EN.UTF-8
- name: QGIS_PROJECT_FILE
value: /data/osm.qgs
- name: QGIS_SERVER_LOG_LEVEL
value: "0"
- name: DEBUG
value: "1"
ports:
- containerPort: 5555
volumeMounts:
- name: qgis-data
mountPath: /data/
volumes:
- name: qgis-data
hostPath:
path: REPLACE_WITH_FULL_PATH/data
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: qgis-nginx
namespace: default
spec:
replicas: 1
selector:
matchLabels:
myLabel: qgis-nginx
template:
metadata:
labels:
myLabel: qgis-nginx
spec:
containers:
- name: qgis-nginx
image: nginx:1.13
ports:
- containerPort: 80
volumeMounts:
- name: nginx-conf
mountPath: /etc/nginx/conf.d/default.conf
volumes:
- name: nginx-conf
hostPath:
path: REPLACE_WITH_FULL_PATH/nginx.conf
Manifesti di servizio
Crea un file services.yaml
con questo contenuto:
apiVersion: v1
kind: Service
metadata:
name: qgis-server
namespace: default
spec:
type: ClusterIP
selector:
myLabel: qgis-server
ports:
- port: 5555
targetPort: 5555
---
apiVersion: v1
kind: Service
metadata:
name: qgis-nginx
namespace: default
spec:
type: NodePort
selector:
myLabel: qgis-nginx
ports:
- port: 80
targetPort: 80
nodePort: 30080
Distribuzione manifesti
Per distribuire le immagini e i servizi in Kubernetes, si può usare la dashboard (fai clic su + in alto a destra) o la linea di comando.
Nota
Quando utilizzi la linea di comando con microk8s dovrai anteporre a ogni comando il prefisso microk8s.
Per distribuire o aggiornare i manifesti:
kubectl apply -k ./
Per verificare cosa è attualmente distribuito:
kubectl get pods,services,deployment
Dovresti ottenere qualcosa di simile a:
NAME READY STATUS RESTARTS AGE
pod/qgis-nginx-54845ff6f6-8skp9 1/1 Running 0 27m
pod/qgis-server-75df8ddd89-c7t7s 1/1 Running 0 27m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/Kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 5h51m
service/qgis-exec-server ClusterIP 10.152.183.218 <none> 5555/TCP 35m
service/qgis-nginx NodePort 10.152.183.234 <none> 80:30080/TCP 27m
service/qgis-server ClusterIP 10.152.183.132 <none> 5555/TCP 27m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/qgis-nginx 1/1 1 1 27m
deployment.apps/qgis-server 1/1 1 1 27m
Per leggere i log di nginx/qgis, digita:
kubectl logs -f POD_NAME
Per verificare le capabilities del WMS, digita in un browser web http://localhost:30080/qgis-server/?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities.
Pulizia
Per ripulire, digita:
kubectl delete -n default service/qgis-server service/qgis-nginx deployment/qgis-nginx deployment/qgis-server
8.3. Distribuzione in cloud
Gestire il tuo cluster di server per gestire la distribuzione di applicazioni containerizzate è un lavoro complesso. Devi gestire diversi problemi, come l’hardware, la larghezza di banda e la sicurezza a diversi livelli.
Le soluzioni di distribuzione in cloud possono essere una buona alternativa quando non ci si vuole concentrare sulla gestione dell’infrastruttura.
Una distribuzione nel cloud può utilizzare meccanismi proprietari, ma anche compatibili con le fasi spiegate in precedenza (docker images e stack management).
8.3.1. Caso d’uso AWS
Con Amazon AWS, grazie alle funzionalità di ECS (Elastic Container Service), puoi utilizzare docker-compose o wrapper compatibili con Kubernetes per gestire il tuo stack. Dovrai creare un image registry per rendere accessibili le tue immagini personalizzate.
Per utilizzare le funzionalità simili a docker-compose, devi installare il client ecs-cli e disporre di permessi/ruoli adeguati. Quindi, con l’aiuto dei comandi ecs-cli compose, puoi riutilizzare la stack description.
Per utilizzare Kubernetes, puoi utilizzare la console web di AWS o lo strumento a linea di comando eksctl e disporre dei permessi/ruoli appropriati. Quindi, con un ambiente kubectl ben configurato, puoi riutilizzare il Kubernetes manifests.