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

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

참고

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

힌트

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

참고

QGIS Debian-Ubuntu package downloads need a valid gpg authentication key. Please refer to the installation pages to update the following 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)를 사용해서 사용자 스택을 관리할 수 있습니다. 사용자 정의 이미지를 받아들이게 하려면 이미지 레지스트리 를 생성해야 할 것입니다.

To use docker-compose alike functionalities, you need to install the ecs-cli client and have proper permissions / roles. Then, with the help of the ecs-cli compose commands, you can reuse the stack description.

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