8. النشر باستخدام الحاويات

توجد طرق عديدة لاستخدام التطبيقات المعبأة في حاويات، من أبسطها (صور Docker البسيطة) إلى أكثرها تطورًا (Kubernetes وغيرها).

ملاحظة

يتطلب هذا النوع من النشر أن يكون تطبيق Docker مثبتًا وقيد التشغيل. راجع هذا الدرس التعليمي.

تلميح

يشغّل Docker تطبيقات معبأة مسبقًا (تُسمى الصور Images)، ويمكن الحصول عليها إما مصادرَ (ملف Dockerfile والموارد) لبنائها، أو جاهزة البناء من السجلات (Registries) الخاصة أو العامة.

ملاحظة

تتطلب تنزيلات حزم QGIS لـ Debian-Ubuntu مفتاح مصادقة gpg صالحًا. يرجى الرجوع إلى صفحات التثبيت لتحديث ملف Dockerfile التالي.

8.1. صور Docker بسيطة

بما أن صورة Docker غير موجودة في سجل عام، فستحتاج إلى بنائها. للقيام بذلك أنشئ مجلدًا باسم qgis-server، وداخل هذا المجلد:

  • أنشئ ملفًا باسم Dockerfile بهذا المحتوى:

FROM debian:bookworm-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://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/resources/installation-guide/#repositories)
    && echo "deb [signed-by=/etc/apt/keyrings/qgis-archive-keyring.gpg] https://qgis.org/debian bookworm 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"]
  • أنشئ ملفًا باسم cmd.sh بهذا المحتوى:

#!/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
  • ابنِ الصورة باستخدام:

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

8.1.1. التشغيل الأول

لتشغيل الخادم ستحتاج إلى ملف مشروع QGIS. يمكنك استخدام أحد مشاريعك أو اختيار هذا المثال.

للقيام بذلك، أنشئ مجلدًا باسم data داخل المجلد qgis-server وانسخ ملفك إليه. ولتتوافق مع الشروح التالية، أعد تسميته إلى osm.qgs.

ملاحظة

قد تحتاج إلى إضافة عناوين URL المُعلَنة ضمن تبويب QGIS Server في Project ► Properties إذا كانت استجابة GetCapabilites معطوبة. فمثلًا إذا كان خادمك مكشوفًا على المنفذ 8080، فاكتب عنوان URL المُعلَن التالي http://localhost:8080/qgis-server/. تتوفر معلومات إضافية في القسم ضبط مشروعك والأقسام التي تليه.

يمكنك الآن تشغيل الخادم باستخدام:

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

الخيارات المستخدمة:

  • -d: التشغيل في الخلفية

  • --rm: إزالة الحاوية عند إيقافها

  • --name: اسم الحاوية المراد إنشاؤها

  • --net: الشبكة الفرعية (المنشأة مسبقًا)

  • --hostname: اسم المضيف للحاوية، للإشارة إليها لاحقًا

  • -v: مجلد البيانات المحلي المراد ربطه (Mount) داخل الحاوية

  • -p: ربط منفذ المضيف بمنفذ الحاوية

  • -e: متغير البيئة المراد استخدامه في الحاوية

للتحقق، اكتب docker ps | grep qgis-server ويُفترض أن ترى سطرًا يحتوي على 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. مثال قابل للاستخدام

بما أن الخادم لا يقبل إلا اتصالات fastcgi، فأنت بحاجة إلى خادم HTTP يتعامل مع هذا البروتوكول. لذلك علينا إنشاء ملف إعدادات Nginx بسيط وتشغيل صورة Nginx.

أنشئ ملفًا باسم nginx.conf في المجلد الحالي بهذا المحتوى:

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

ثم اكتب هذا الأمر:

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

للتحقق من توفر الإمكانات (Capabilities)، اكتب في المتصفح http://localhost:8080/qgis-server/?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities

8.1.3. التنظيف

لتنظيف الصور قيد التشغيل، اكتب:

docker stop qgis-server nginx

8.2. مكدسات Docker

الطريقة السابقة قابلة للأتمتة بالسكربتات، لكنها ليست سهلة التحزيم ولا قياسية ولا سهلة الإدارة.

للعمل مع مجموعة من صور Docker يمكنك استخدام مكدس Docker (Stack) يديره منسّق (Orchestrator). في المكدس تعمل الصور ضمن الشبكة الخاصة نفسها، ويمكنك تشغيل المكدس بأكمله أو إيقافه أو نشره على عُقد عاملة أخرى. توجد منسّقات عديدة، مثل Swarm و Kubernetes و Mesos.

سنعرض فيما يلي إعدادات بسيطة لأغراض الاختبار، وهي غير مناسبة لبيئات الإنتاج.

8.2.1. Swarm و docker-compose

أصبح لدى Docker الآن منسّقه الخاص: Swarm (المتوافق مع ملفات docker-compose). عليك تفعيله (نسخة Mac ستعمل أيضًا مع Linux).

وصف المكدس

الآن بعد أن أصبح Swarm يعمل، أنشئ ملف الخدمة qgis-stack.yaml (انظر النشر على Swarm):

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

لنشر المكدس (أو تحديثه)، اكتب:

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

تحقق من حالة نشر المكدس حتى تحصل على 1/1 في العمود replicas:

docker stack services qgis-stack

شيء من قبيل:

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

للتحقق من إمكانات WMS، اكتب في متصفح الويب http://localhost:8080/qgis-server/?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities

التنظيف

للتنظيف، اكتب:

docker stack rm qgis-stack

8.2.2. Kubernetes

التركيب

إذا كان لديك تثبيت لـ Docker Desktop، فإن استخدام Kubernetes (المعروف اختصارًا بـ k8s) سهل جدًا: فعّل k8s.

وإن لم يكن كذلك، فاتبع درس minikube التعليمي أو microk8s لـ Ubuntu.

بما أن تثبيت Kubernetes قد يكون معقدًا جدًا، فسنركز فقط على الجوانب المستخدمة في هذا العرض التوضيحي. لمعلومات إضافية أو أعمق، راجع الوثائق الرسمية.

microk8s

يحتاج microk8s إلى خطوات إضافية: عليك تفعيل السجل (Registry) ووسم صورة qgis-server لكي يعثر Kubernetes على الصور المنشأة.

أولًا، فعّل السجل:

microk8s enable dashboard dns registry

ثم ضع وسمًا على الصورة وادفعها إلى السجل الذي أنشأته للتو:

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

أخيرًا، أضف الملف /etc/docker/daemon.json أو أكمله ليتضمن سجلك 127.0.0.1:32000 في الحقل insecure-registries:

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

إنشاء ملفات البيان (Manifests)

يصف Kubernetes الكائنات المراد نشرها في ملفات بيان بصيغة yaml. وتوجد أنواع كثيرة منها، لكننا سنستخدم فقط عمليات النشر (Deployments) (التي تدير الـ Pods، أي صور Docker) والخدمات (Services) لكشف عمليات النشر لأغراض داخلية أو خارجية.

ملفات بيان النشر

أنشئ ملفًا باسم deployments.yaml بهذا المحتوى:

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: Always
          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/
      volumes:
        - name: nginx-conf
          configMap:
            name: nginx-configuration

---
kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-configuration
data:
  nginx.conf: |
    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;
        }
      }
ملفات بيان الخدمات

أنشئ ملفًا باسم services.yaml بهذا المحتوى:

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

نشر ملفات البيان

لنشر الصور والخدمات في Kubernetes، يمكنك استخدام لوحة التحكم (انقر على + في الأعلى يمينًا) أو سطر الأوامر.

ملاحظة

عند استخدام سطر الأوامر مع microk8s، عليك أن تسبق كل أمر بالكلمة microk8s.

لنشر ملفات البيان أو تحديثها:

kubectl apply -f ./

للتحقق مما هو منشور حاليًا:

kubectl get pods,services,deployment

يُفترض أن تحصل على شيء من قبيل:

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

لقراءة سجلات nginx/qgis، اكتب:

kubectl logs -f POD_NAME

للتحقق من إمكانات WMS، اكتب في متصفح الويب http://localhost:30080/qgis-server/?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities

التنظيف

للتنظيف، اكتب:

kubectl delete service/qgis-server service/qgis-nginx deployment/qgis-nginx deployment/qgis-server configmap/nginx-configuration

8.3. النشر السحابي

إن إدارة عنقود خوادم خاص بك للتعامل مع نشر التطبيقات المعبأة في حاويات مهمة معقدة، إذ عليك التعامل مع قضايا متعددة مثل العتاد وعرض النطاق الترددي والأمان على مستويات مختلفة.

يمكن أن تكون حلول النشر السحابي بديلًا جيدًا عندما لا ترغب في التركيز على إدارة البنية التحتية.

قد يستخدم النشر السحابي آليات مملوكة لمزوّد الخدمة، لكنها متوافقة أيضًا مع المراحل الموضحة سابقًا (صور Docker و إدارة المكدسات).

8.3.1. حالة استخدام AWS

مع Amazon AWS، ومن خلال وظائف ECS (Elastic Container Service)، يمكنك استخدام أغلفة متوافقة مع docker-compose أو Kubernetes لإدارة مكدسك. وسيتعين عليك إنشاء سجل صور لتكون صورك المخصصة قابلة للوصول.

لاستخدام وظائف مشابهة لـ docker-compose، عليك تثبيت العميل ecs-cli وامتلاك الصلاحيات / الأدوار المناسبة. ثم يمكنك، بمساعدة أوامر ecs-cli compose، إعادة استخدام وصف المكدس.

لاستخدام Kubernetes، يمكنك استخدام وحدة تحكم الويب في AWS أو أداة سطر الأوامر eksctl مع امتلاك الصلاحيات / الأدوار المناسبة. ثم يمكنك، مع بيئة kubectl مضبوطة جيدًا، إعادة استخدام ملفات بيان Kubernetes.