8. 컨테이너화 응용 프로그램 배포

컨테이너화된 응용 프로그램을 사용할 수 있는 많은 방법이 있습니다. 가장 단순한 방법(단순 도커(Doker) 이미지)부터 복잡한 방법(쿠버네티스(Kubernetes) 등)까지 말입니다.

참고

이런 종류의 배치는 도커 응용 프로그램 을 설치하고 실행해야 합니다. 이 튜토리얼 을 확인해보세요.

힌트

도커는 사전에 패키지된 응용 프로그램(이미지)을 실행합니다. 이 이미지를 빌드하기 위해 소스(도커 파일 및 리소스)로 가져올 수도 있고, 또는 (프라이빗 또는 퍼블릭) 레지스트리에 이미 빌드되어 있을 수도 있습니다.

참고

QGIS 데비안-우분투 패키지 다운로드는 무결한 GPG 인증 키가 필요합니다. 설치 페이지 를 참조해서 다음 Dockerfile을 업데이트해주십시오.

8.1. 단순 도커 이미지

퍼블릭 레지스트리에 도커 이미지가 없기 때문에, 직접 빌드해야 합니다. 그렇게 하려면 qgis-server 디렉터리를 생성하고 이 디렉터리 안에:

  • 다음 내용을 가진 Dockerfile 파일을 생성하십시오:

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"]
  • 다음 내용을 가진 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 프로젝트 파일이 필요할 것입니다. 사용자 프로젝트 가운데 하나를 사용해도 되고, 또는 이 예시 프로젝트 를 선택해도 됩니다.

QGIS 프로젝트를 사용하려면, qgis-server 디렉터리 안에 data 디렉터리를 생성하고 사용자의 파일을 복사해 넣으십시오. 다음 설명과 일치시키기 위해, 파일을 osm.qgs 로 재명명하십시오.

참고

GetCapabilites가 손상된 경우 Project ► PropertiesQGIS Server 탭에서 알려진(advertised) URL을 추가해야 할 수도 있습니다. 예를 들면 사용자 서버가 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: 컨테이너에 마운트될 로컬 데이터 디렉터리

  • -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 서버가 필요합니다. 이를 위해 단순한 엔진X 환경 설정 파일을 생성하고 엔진X 이미지를 시작해야 합니다.

현재 디렉터리에 다음 내용을 가진 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

케이퍼빌리티를 사용할 수 있는지 확인하려면, 브라우저에 http://localhost:8080/qgis-server/?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities 를 입력하십시오.

8.1.3. 제거(cleanup)

실행 중인 이미지를 제거하려면, 다음을 입력하십시오:

docker stop qgis-server nginx

8.2. 도커 스택

앞에서 설명한 방법은 스크립트로 작성할 수 있지만, 쉽게 패키지화할 수도, 표준화할 수도, 또는 관리할 수도 없습니다.

도커 이미지 집합을 작업하기 위해 조직자(orchestrator)가 관리하는 도커 스택을 사용하면 됩니다. 스택을 사용하면, 이미지가 동일한 사설 네트워크에서 작동하며, 사용자가 전체 스택을 실행/종료하거나 다른 작업자에세 스택을 배치할 수 있습니다. 조직자는 많이 있습니다 - 예를 들면 Swarm, Kubernetes 그리고 Mesos 같은 조직자들 말이죠.

다음 절부터 테스트 목적의 단순 환경 설정을 제시할 것입니다. 이 환경 설정은 실제 서버 운용에는 적합하지 않습니다.

8.2.1. 스웜/도커 구성

도커가 이제 고유 조직자 (도커 구성(docker-compose) 파일과 호환되는) 스웜을 가지고 있습니다. 사용자가 스웜을 활성화 해야 합니다. (맥 버전도 리눅스 방법으로 작동할 것입니다.)

스택 설명

이제 스웜을 작동시켰으니, 서비스 파일 (스웜으로 배포 참조) 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

스택을 배포(또는 업데이트)하려면, 다음을 입력하십시오:

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

replicas 열에 1/1 이 나올 때까지 스택 배포 상태를 확인하십시오:

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 를 입력하십시오.

제거(cleanup)

스택을 제거하려면, 다음을 입력하십시오:

docker stack rm qgis-stack

8.2.2. 쿠버네티스

설치

도커 데스크탑 을 설치한 경우, 쿠버네티스(별칭 k8s)를 사용하는 방법은 꽤 직관적입니다: k8s를 활성화 하십시오.

설치하지 않았다면, 미니큐브 튜토리얼 또는 우분투용 microk8s 를 따르십시오.

쿠버네티스를 설치하는 과정이 아주 까다로울 수 있기 때문에, 이 예시에서 사용할 면면에만 집중할 것입니다. 더 심화된 정보를 알고 싶다면, 공식 문서 를 확인해보세요.

microk8s

microk8s를 사용하려면 추가 단계를 거쳐야 합니다: 쿠버네티스가 생성된 이미지를 찾을 수 있게 하려면 레지스트리를 활성화하고 qgis-server 이미지를 태그해야 합니다.

먼저, 레지스트리를 활성화하십시오:

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 파일의 insecure-registries  필드 목록에 사용자 레지스트리 127.0.0.1:32000 이 들어가도록 /etc/docker/daemon.json 파일을 추가하거나 수정하십시오:

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

매니페스트 생성하기

쿠버네티스는 배포할 객체를 yaml 매니페스트(manifest) 서식으로 설명합니다. 수많은 서로 다른 유형의 서식이 있지만, 내부적 또는 외부적 목적으로 배포를 노출시키기 위한 (도커 이미지 같은 포드(pod)를 처리하는) 배포 서식 및 서비스 서식만 사용할 것입니다.

배포 매니페스트

다음 내용을 가진 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: 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
서비스 매니페스트

다음 내용을 가진 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

매니페스트 배포하기

쿠버네티스에서 이미지와 서비스를 배포하려면, 대시 보드(우상단에 있는 + 를 클릭) 또는 명령 줄을 사용하면 됩니다.

참고

microk8s에서 명령 줄을 사용할 경우 각 명령어 앞에 microk8s 접두어를 붙여야 할 것입니다.

사용자 매니페스트를 배포 또는 업데이트하려면, 다음을 입력하십시오:

kubectl apply -k ./

현재 배포되고 있는 것이 무엇인지 확인하려면 다음을 입력하십시오:

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 를 입력하십시오.

제거(cleanup)

매니페스트를 제거하려면, 다음을 입력하십시오:

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

8.3. 클라우드 배포

컨테이너화된 응용 프로그램의 배포를 처리하도록 사용자 고유의 서버 클러스터를 관리하는 것은 복잡한 일입니다. 하드웨어, 대여폭, 그리고 서로 다른 수준들의 보안 등 여러 문제를 동시에 처리해야 하니까요.

사용자가 인프라 관리에만 집중하고 싶지 않다면, 클라우드 배포 솔루션이 훌륭한 대안이 되어 줄 수 있습니다.

클라우드 배포는 상용 메커니즘을 사용할 수도 있지만, 앞에서 설명한(도커 이미지스택 관리) 단계와도 호환됩니다.

8.3.1. AWS 활용 사례

아마존 AWS를 사용하면, ECS(Elastic Container Service) 기능을 통해 도커 구성(docker-compose) 또는 쿠버네티스 호환 래퍼(wrapper)를 사용해서 사용자 스택을 관리할 수 있습니다. 사용자 정의 이미지를 받아들이게 하려면 이미지 레지스트리 를 생성해야 할 것입니다.

도커 구성과 비슷한 기능을 사용하려면, ecs-cli 클라이언트를 설치하고 적절한 권한 / 역할 을 가지고 있어야 합니다. 그러면, ecs-cli 구성 명령어의 도움으로 스택 설명 을 재사용할 수 있습니다.

쿠버네티스를 사용하려면, AWS 웹 콘솔 또는 명령 줄 도구 eksctl 를 사용해서 적절한 권한/역할을 가질 수 있습니다. 그 다음 잘 환경 설정된 kubectl 환경과 함께 쿠버네티스 매니페스트 를 재사용할 수 있습니다.