7. Despliegue en contenedores

Hay muchas formas de utilizar aplicaciones en contenedores, desde las más simples (imágenes simples de Docker) hasta las más sofisticadas (Kubernetes, etc.).

Nota

Este tipo de implementación necesita que la aplicación docker <https://www.docker.com> _ esté instalada y en ejecución. Mira este tutorial.

Consejo

Docker ejecuta una aplicación preempaquetada (también conocida como imágenes) que se pueden recuperar como fuentes (Dockerfile y recursos) para compilar o ya compiladas a partir de registros (privados o públicos).

Nota

Las descargas de paquetes QGIS Debian-Ubuntu necesitan una clave de autenticación gpg válida. Consulte las páginas de instalación para actualizar el siguiente Dockerfile con la última huella dactilar clave

7.1. Imágenes de simple docker

Como la imagen de la ventana acoplable no existe en un registro público. necesitarás construirlo. Para hacerlo, cree un directorio qgis-server y dentro de su directorio:

  • cree un archivo Dockerfile con este contenido:

FROM debian:buster-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 - As the key changes every year at least
    # Please refer to QGIS install documentation and replace it with the latest one
    && wget -O - https://qgis.org/downloads/qgis-2020.gpg.key | gpg --import \
    && gpg --export --armor F7E06F06199EF2F2 | apt-key add - \
    && echo "deb http://qgis.org/debian buster main" >> /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.17.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"]
  • cree un archivo cmd.sh con este contenido:

#!/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
  • construya la imagen con:

docker build -f Dockerfile -t qgis-server ./

7.1.1. Primero ejecute

Para ejecutar el servidor, necesitará un archivo de proyecto QGIS. Puede usar uno de los suyos o elegir esta muestra.

Para hacerlo, cree un directorio: archivo: datos dentro del directorio qgis-server y copie su archivo en él. Para cumplir con las siguientes explicaciones, cámbiele el nombre a osm.qgs.

Ahora, puede ejecutar el servidor 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

Opciones usadas:

  • -d: ejecuta en segundo plano

  • –rm: borra el contenedor cuando es detenido

  • –name: nombre del contenedor a crear

  • –net: (creada previamente) subred

  • –hostname: nombre de host del contenedor, para referenciación posterior

  • -v: directorio de datos local a montar en el contenedor

  • -p: mapeo del puerto del host/contenedor

  • -e: variable de entorno a usar en el contenedor

Para probar, escriba docker ps | grep qgis-server and you should see a line with 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

7.1.2. Muestra utilizable

Como el servidor solo acepta conexiones fastcgi, necesita un servidor HTTP que maneje este protocolo. Para hacerlo, tenemos que crear un archivo de configuración Nginx simple e iniciar una imagen Nginx.

Cree un archivo nginx.conf en el directorio actual con este contenido:

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;
  }
}

y escriba este 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

Para verificar la disponibilidad de capacidades, escriba un navegador http://localhost:8080/qgis-server/?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities

7.1.3. Limpieza

Para limpiar las imágenes cargadas, escriba:

docker stop qgis-server nginx

7.2. Pilas de Docker

El método anterior es programable, pero no es fácil de empaquetar, estandarizar o administrar.

Para trabajar con un conjunto de imágenes de la ventana acoplable, puede usar una pila de la ventana acoplable administrada por un orquestador. En una pila, las imágenes funcionan en la misma red privada y puede iniciar / detener toda la pila o implementar la pila en otros trabajadores. Hay muchos orquestadores, por ejemplo Swarm, Kubernetes y Mesos.

A continuación, presentaremos configuraciones simples con fines de prueba. No son aptos para la producción.

7.2.1. Swarm/docker-compose

Docker ahora tiene su propio orquestador: Swarm (compatible con archivos de composición de Docker). Tienes que “habilitarlo <https://docs.docker.com/get-started/orchestration/#enable-docker-swarm>`_ (la versión para Mac también funcionará con Linux).

7.2.1.1. Descripción de pila

Ahora que tiene Swarm funcionando, cree el archivo de servicio (consulte `Implementar en Swarm<https://docs.docker.com/get-started/swarm-deploy/>`_) 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

Para implementar (o actualizar) la pila, escriba:

docker stack deploy -c qgis-stack.yaml qgis-stack

Verifique el estado de implementación de la pila hasta que obtenga 1/1 en la columna réplicas:

docker stack services qgis-stack

Algo como:

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

Para verificar las capacidades de WMS, escriba un navegador web http://localhost:8080/qgis-server/?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities

7.2.1.2. Limpieza

Para limpiar, escriba:

docker stack rm qgis-stack

7.2.2. Kubernetes

7.2.2.1. Instalación

Si tiene una instalación de Docker Desktop, usar Kubernetes (también conocido como k8s) es bastante sencillo: habilitar k8s.

Si no, siga el tutorial de minikube o microk8s para Ubuntu.

Como la instalación de Kubernetes puede ser realmente compleja, solo nos centraremos en los aspectos utilizados por esta demostración. Para obtener más información / más detallada, consulte la documentación oficial.

7.2.2.1.1. microk8s

microk8s necesita pasos adicionales: debe habilitar el registro y etiquetar la imagen del servidor qgis para que Kubernetes encuentre las imágenes creadas.

Primero, habilite el registro:

microk8s enable dashboard dns registry

Luego, etiquete y envíe la imagen a su registro recién creado:

docker tag qgis-server 127.0.0.1:32000/qgis-server && docker push 127.0.0.1:32000/qgis-server

Finalmente, agregue o complete el /etc/docker/daemon.json para tener su registro**127.0.0.1:32000** enumerados en el campo registros inseguros:

{
  "insecure-registries": ["127.0.0.1:32000"]
}

7.2.2.2. Creando manifiestos

Kubernetes describe los objetos para implementar en manifiestos yaml. Hay muchos tipos diferentes, pero solo usaremos implementaciones (manejar pods, es decir, imágenes de Docker) y servicios para exponer las implementaciones a propósitos internos o externos.

7.2.2.2.1. Manifiestos de implementación

Cree un archivo deployments.yaml con este contenido:

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
7.2.2.2.2. Manifiestos de servicio

Cree un archivo services.yaml con este contenido:

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

7.2.2.3. Implementar manifiesto

Para implementar las imágenes y los servicios en Kubernetes, se puede usar el panel (haga clic en + en la parte superior derecha) o la línea de comandos.

Nota

Cuando use la línea de comando con microk8s, tendrá que anteponer cada comando con microk8s.

Para implementar o actualizar sus manifiestos:

kubectl apply -k ./

Para verificar qué está implementado actualmente:

kubectl get pods,services,deployment

Debería obtener algo como:

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

Para leer los registros de nginx / qgis, escriba:

kubectl logs -f POD_NAME

Para verificar las capacidades de WMS, escriba un navegador web http://localhost:30080/qgis-server/?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities

7.2.2.4. Limpieza

Para limpiar, escriba:

kubectl delete -n default service/qgis-server service/qgis-nginx deployment/qgis-nginx deployment/qgis-server

7.3. Implementar nube

Administrar su propio clúster de servidores para manejar la implementación de aplicaciones en contenedores es un trabajo complejo. Tiene que manejar varios problemas, como hardware, ancho de banda y seguridad en diferentes niveles.

Las soluciones de implementación en la nube pueden ser una buena alternativa cuando no desea centrarse en la gestión de la infraestructura.

Una implementación en la nube puede utilizar mecanismos propietarios, pero también son compatibles con las etapas explicadas anteriormente. (docker images y stack management).

7.3.1. Caso de uso de AWS

Con Amazon AWS, a través de ʻECS (Elastic Container Service)<https://console.aws.amazon.com/ecs/home>`_ funcionalidades, puede usar contenedores compatibles con Docker-compose o Kubernetes para administrar su pila. Tendrá que crear un registro de imágenes <https://console.aws.amazon.com/ecr/home>`_ para que sus imágenes personalizadas sean accesibles.

Para usar funcionalidades similares de docker-compose, necesita instalar el cliente ecs-cli y tener los permisos/roles adecuados <https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_execution_IAM_role.html>`_. Luego, con la ayuda de los comandos ʻecs-cli compose` (ver el manual ʻecs-cli compose <https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cmd-ecs-cli-compose.html>`_ y ecs-cli tutorial), puedes reutilizar el stack description.

Para usar Kubernetes, puede usar la consola web de AWS o la herramienta de línea de comandos eksctl y tener los permisos / roles adecuados. Luego, con un entorno kubectl bien configurado, puede reusar la Kubernetes manifests.