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

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

참고

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

힌트

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

18.2.5.1. 단순 도커 이미지

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

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

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 \
    && wget -O - https://qgis.org/downloads/qgis-2019.gpg.key | gpg --import \
    && gpg --export --armor 8D5A5B203548E5004487DD1951F523511C7028C3 | 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 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 ./

18.2.5.1.1. 첫 번째 시도

서버를 실행하려면 QGIS 프로젝트 파일이 필요할 것입니다. 사용자 프로젝트 가운데 하나를 사용해도 되고, 또는 이 예시 프로젝트 를 선택해도 됩니다.

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

이제 다음 명령어로 서버를 실행할 수 있습니다:

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

18.2.5.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

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

18.2.5.1.3. 제거(cleanup)

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

docker stop qgis-server nginx

18.2.5.2. 도커 스택

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

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

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

18.2.5.2.1. 스웜/도커 구성

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

18.2.5.2.1.1. 스택 설명

이제 스웜을 작동시켰으니, 서비스 파일 (스웜 배포 참조) 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 를 입력하십시오.

18.2.5.2.1.2. 제거(cleanup)

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

docker stack rm qgis-stack

18.2.5.2.2. 쿠버네티스

18.2.5.2.2.1. 설치

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

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

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

18.2.5.2.2.1.1. 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"]
}

18.2.5.2.2.2. 매니페스트 생성하기

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

18.2.5.2.2.2.1. 배포 매니페스트

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

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

18.2.5.2.2.3. 매니페스트 배포하기

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

참고

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

18.2.5.2.2.4. 제거(cleanup)

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

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

18.2.5.3. 클라우드 배포

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

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

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

18.2.5.3.1. AWS 활용 사례

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

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

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