Kihagyás

Telepítési és üzemeltetési útmutató

1. Hardveres és szoftverek követelmények

1.1 Minimum hardveres követelmények (éles, UAT)

  • Load Balancer szerver - 1 darab VM.

    • Processzor: 2 vCPU
    • Memória: 2GB RAM
    • Tárhely: 20GB SSD
  • Alkalmazás szerverek - annyi darab VM ahány példányban szeretnénk futtatni az alkalmazásokat (az alábbi konfiguráció VM-enként értendő).

    • Processzor: 4 vCPU
    • Memória: 8GB RAM
    • Tárhely: 40GB SSD

1.2 Szoftveres követelmények

  • Operációs rendszer: Az aktuálisan legfrissebb verziójú LTS Ubuntu Server (Minden szerverre érvényes.)

2. Időzóna beállítása

Mielőtt végrehajtjuk a lenti lépéseket bizonyosodjunk meg arról, hogy minden VM ugyanabban az időzónában van.

Az időzóna beállítását root felhasználóként végezzük a szerveren.

A budapesti időzóna az alábbi paranccsal állítható be:

timedatectl set-timezone Europe/Budapest

Ezt minden szervernél ellenőrizzük és szükséges esetén állítsuk be.

3. Domain név regisztrálása

Az általunk használt domain kezelőben regisztráljuk be a domain nevet a load balancer szerver IP címéhez.

4. Load Balancer - HAProxy telepítése a Load Balancer szerveren

A HAProxy telepítését és konfigurálását root felhasználóként végezzük a szerveren.

4.1 HAProxy telepítése

A HAProxy-t a következő parancsokkal telepíthetjük:

sudo apt update
sudo apt install -y haproxy

4.2 HAProxy konfigurálása

A HAProxy konfigurációs fájljában (/etc/haproxy/haproxy.cfg) a következő szerepeljen:

global
    log         127.0.0.1 local2

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon

    stats socket /var/lib/haproxy/stats

    ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
    ssl-default-bind-options ssl-min-ver TLSv1.2
    tune.ssl.default-dh-param 2048

defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option                  log-health-checks
    option                  redispatch
    timeout connect         10s
    timeout client          1m
    timeout server          5m
    timeout tunnel          8h
    balance                 leastconn
    http-check expect string UP

frontend https
    option forwardfor
    bind *:80
    bind *:443 ssl crt /etc/ssl/${domain_név}/${domain_név}.pem
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    http-request redirect scheme https code 301 unless { ssl_fc }

    acl host_webcomponent hdr(host) -i ${webcomponent_app_domain_név}
    acl is-backend path_beg /public/api /api /websocket /WEB/hello /MBL/hello /microsite/WEB

    use_backend backend_service if is-backend
    use_backend webcomponent_spa if host_webcomponent

    http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains;"

backend backend_service
    acl is-path-actuator path -i -m beg /actuator
    http-request deny if is-path-actuator
    option httpchk GET /actuator/health
    server backend_service_1 ${APP_SERVER_1_IP}:8080 check fall 2
    server backend_service_2 ${APP_SERVER_2_IP}:8080 check fall 2

backend webcomponent_spa
    acl is-health-check path -i /health-check
    http-request deny if is-health-check
    option httpchk GET /health-check
    server webcomponen_spa_1 ${APP_SERVER_1_IP}:4204 check fall 2
    server webcomponen_spa_2 ${APP_SERVER_2_IP}:4204 check fall 2           
  • Az ${APP_SERVER_1_IP} és ${APP_SERVER_2_IP} értékeket értelemszerűen a clusterben szereplő alkalmazás szerverek IP-címével helyettesítsük. Egy alkalmazás szerver esetén csak az egyik sorra van szükség, minden további szerver esetén a mintának megfelelően újabb sorok felvételével tudjuk ezeket konfigurálni.

  • A ${domain_név} értéket értelemszerűn a saját domainünk nevével kell behelyettesíteni.

    A domain címekre kiállított tanúsítványokat a /etc/ssl mappába helyezzük, Pl.: Ha a doman név projectdomain.hu akkor az elvárt mappaszerkezet: /etc/ssl/projectdomain.hu/projectdomain.hu.pem.

    Eltérő útvonal vagy több tanúsítvány esetén a haproxy.cfg fájl frontend https szekciójában a bind *:443 ssl kezdetű sort módosítsuk, melynek értéke a következő minta szerint épül fel:

        bind *:443 ssl crt /etc/ssl/CERT_1 crt /etc/ssl/CERT_2 ... crt /etc/ssl/CERT_N
    

  • A HAProxy konfigurációban tetszőleges számú frontend alkalmazást konfigurálhatunk. Értelemszerűen a ${webcomponent_app_domain_név} értékét a megfelelő frontend alkalmazás domain nevével kell helyettesíteni.

4.3 HAProxy indítása

A konfigurációk elvégeztével indítsuk el a HAProxy szolgáltatást:

systemctl start haproxy
Illetve, hogy rebootot követően is elinduljon a HAProxy adjuk ki az alábbi parancsot is:
systemctl enable haproxy 

A HAProxy log fájlt: haproxy.log, a /var/log/ útvonalon érhetjük el.

5. Alkalmazás szerver

A következő lépéseket a clusterben lévő összes alkalmazás szerveren végezzük el.

5.1 Docker telepítése

A docker telepítését root felhasználóként végezzük a szerveren.

A Docker telepítésének egyik módja, hogy beállítjuk a docker repositoryjait és onnan telepítjük a Docker-t. Az egyéb telepítési módokról itt taláható információ.

A Docker repositoryk beállításához adjuk ki az alábbi parancsokat:

sudo apt-get update
sudo apt-get install \
  ca-certificates \
  curl \
  gnupg \
  lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

A Docker teleítéséhez adjuk ki az alábbi parancsokat:

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

A Docker compose telepítéséhez adjuk ki az alábbi parancsokat:

sudo apt-get update
sudo apt-get install docker-compose-plugin

A Docker sikeres telepítését az alábbi scripttel ellenőrizhetjük:

sudo docker run hello-world

A docker compose verzióját az alábbi paranncsal ellenőrizhetjük:

docker compose version

5.2 Docker network létrehozása

A docker network létrehozását root felhasználóként végezzük a szerveren.

Hozzunk létre egy docker network-öt az alábbi paranccsal:

docker network create infrastructure-network

5.3 User létrehozása

Az alkalmazásokat nem a root felhasználóval kell elindítani, ezért hozzunk létre egy dedikált felhasználót(appuser) aki az alkalmazásokat fogja kezelni.

Az appuser felhasználót root felhasználóként hozzuk létre a szerveren.

A felhasználó létrehozható például az alábbi parancsok segítségével:

adduser -m appuser

usermod -aG docker appuser
passwd appuser
su - appuser

5.4 Mappastruktúra létrehozása

A mappastruktúra létrehozását root felhasználóként végezzük a szerveren.

  1. Lépjünk be az opt könyvtárba az alábbi paranccsal:
    cd /opt 
    
  2. Hozzuk létre projekt a mappákat az alábbi parancsokkal:
    mkdir -p project/infrastructure/config/backend-service
    

mkdir -p project/infrastructure/logs
Az elvárt mappaszerkezet:
opt
 └ project
    └ infrastructure 
       ├ config
       │  └ backend-service 
       ├ models  
       └ logs  

  1. Végül adjuk át owner és group jogokat az alkalmazást futtató felhasználónak:
    chown -R appuser:appuser project
    

5.5 Alkalmazás konfiguráció

Az alkalmazás konfigurációval kapcsolatos lépéseket az appuser felhasználóval végezzük el a szerveren.

Az /opt/project/infrastructure könyvtárba helyezzük el a következő konfigurációs fájlt:

/opt/project/infrastructure/.env:

# Env config
PROJECT_ENVIRONMENT=PRODUCTION

# Version config
APP_VERSION=
BACKEND_SERVICE_VERSION=${APP_VERSION}
WEBCOMPONENT_SPA_VERSION=${APP_VERSION}
PYTHON_SERVICE_VERSION=${APP_VERSION}

# OpenAI Key config
OPENAI_API_KEY=

# Domains config
BASE_DOMAIN=
PROJECT_BASE_URLS_HOST=
PROJECT_BASE_URLS_API_BASE_URL=https://backend.${BASE_DOMAIN}
PROJECT_BASE_URLS_WEBSOCKET_BASE_URL=wss://backend.${BASE_DOMAIN}
PROJECT_BASE_URLS_APPLICATION_TYPE_BASE_URLS_WEBCOMPONENT=https://webcomponent.${BASE_DOMAIN}
PROJECT_BASE_URLS_PYTHON_SERVICE_BASE_URL=http://python-service:8000

# Db Config
DB_SCHEMA=develop
DB_TYPE=postgresql
DB_HOST=db
DB_PORT=5432
DB_USER=
DB_NAME=
DB_PASSWORD=

# Cors Config
CORS_ALLOWED_CORS_ORIGINS=${PROJECT_BASE_URLS_APPLICATION_TYPE_BASE_URLS_WEBCOMPONENT},${PROJECT_BASE_URLS_API_BASE_URL},${PROJECT_BASE_URLS_HOST}
CORS_ALLOWED_CORS_ORIGINS_PATTERN=${PROJECT_BASE_URLS_APPLICATION_TYPE_BASE_URLS_WEBCOMPONENT}|${PROJECT_BASE_URLS_API_BASE_URL}|${PROJECT_BASE_URLS_HOST}


# Backend Service
JDK_JAVA_OPTIONS="--add-modules java.se --add-exports java.base/jdk.internal.ref=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.management/sun.management=ALL-UNNAMED --add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED"
JAVA_TOOL_OPTIONS="-Xms1g -Xmx2g"

LOGGING_CONFIG=file:./infrastructure/config/backend-service/logback-spring.xml

# Disable Redis configuration as it is not currently used by the application. However, it may be needed in the future, in which case this line can be removed.
SPRING_AUTOCONFIGURE_EXCLUDE=org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration

SPRING_PROFILES_ACTIVE=default
SPRING_DATASOURCE_URL=jdbc:${DB_TYPE}://${DB_HOST}:${DB_PORT}/${DB_NAME}?currentSchema=${DB_SCHEMA}
SPRING_DATASOURCE_PASSWORD=${DB_PASSWORD}

PROJECT_OPENAI_ACCESS_TOKEN=${OPENAI_API_KEY}

PROJECT_TECHCORE_CACHE_ENABLED=false
PROJECT_TECHCORE_ANTIVIRUES_ENABLED=false
PROJECT_TECHCORE_NOTIFICATION_PUSH_ENABLED=false

# Python Service
PYTHON_SERVICE_LOGGING__LEVEL=INFO
PYTHON_SERVICE_OPENAI__API_KEY=${OPENAI_API_KEY}
PYTHON_SERVICE_POSTGRES__HOST=${DB_HOST}
PYTHON_SERVICE_POSTGRES__PORT=${DB_PORT}
PYTHON_SERVICE_POSTGRES__USER=${DB_USER}
PYTHON_SERVICE_POSTGRES__PASSWORD=${DB_PASSWORD}
PYTHON_SERVICE_POSTGRES__DATABASE=${DB_NAME}
PYTHON_SERVICE_POSTGRES__DB_SCHEMA=${DB_SCHEMA}

# Web Component SPA
PROJECT_CSP="default-src 'self'; frame-src 'self' blob:; script-src 'unsafe-inline' 'self' 'unsafe-eval'; form-action 'self'; font-src 'self'; style-src 'unsafe-inline' 'self'; img-src 'self' https://intuitech.studio data:; object-src 'none'; connect-src 'self' ${PROJECT_BASE_URLS_APPLICATION_TYPE_BASE_URLS_WEBCOMPONENT} ${PROJECT_BASE_URLS_API_BASE_URL};"

PROJECT_CORS_ALLOWED_CORS_ORIGINS=${CORS_ALLOWED_CORS_ORIGINS}
PROJECT_CORS_ALLOWED_CORS_ORIGINS_PATTERN=${CORS_ALLOWED_CORS_ORIGINS_PATTERN}

PROJECT_GOOGLE_ANALYTICS_ENABLED=false

Az alábbi placeholdereket cseréljük le a környezetspecifikus értékekre:

  • ${DB_TYPE} : Az adatbázis típusa pl.: postgresql.
  • ${DB_HOST} : Az adatbázis szerver host neve vagy IP címe.
  • ${DB_NAME} : Az adatbázis neve.
  • ${DB_USER} : Az alkalmazás szerver DB felhasználójának neve.
  • ${DB_PASSWORD} : Az alkalmazás szerver DB felhasználójának jelszava.
  • ${DB_SCHEMA} : Az alkalmazás szerver DB sémájának neve.
  • ${OPENAI_API_KEY} : Az OpenAI által kibocsájtott API kulcs.
  • ${PROJECT_BASE_URLS_PYTHON_SERVICE_BASE_URL} : A python service URL-je.
  • ${CORS_ALLOWED_CORS_ORIGINS} : CORS origin domain nevek listája.
  • ${BASE_DOMAIN} : A backend alkalmazás publikus URL-je.
  • ${PROJECT_BASE_URLS_HOST} : A frontend alkalmazás publikus URL-je.

  • Értelemszerűen a ${webcomponent_app_domain_név} értékét a megfelelő frontend alkalmazás domain nevével kell helyettesíteni.

  • A JAVA_TOOL_OPTIONS változóban az Xms és Xmx JVM paraméterek esetén az -Xms1g és -Xmx2g értékek 4GB memóriával rendelkező alkalmazás szerverek esetén érvényesek.
    Amennyiben 8GB memóriával rendelkező alkalmazás szervereink vannak, úgy az -Xms1g és -Xmx4g értékeket használjuk:

    - "JAVA_TOOL_OPTIONS=-Xms1g -Xmx4g"
    
    Fontos továbbá, hogy az itt ajánlott Xmx érték a minimálisan megadandó maximum heap size értéket jelenti. Ideális esetben az Xmx értéke közlítőleg legyen a gép rendelkezésre álló memória mennyisége, minusz a gépen futó egyéb alkalmazások, rendszerszoftverek, infrastruktúrális komponensek memóriaigénye.

  • A PROJECT_ENVIRONMENT változó értéke befolyásolja, hogy megjelenjen-e a kliens alkalmazások láblécében az alkalmazás verzió mellett a fejlesztés technikai azonosítója is. A production környezeten ennek a változónak az értéke minden esetben PRODUCTION kell legyen, hogy ez a technikai verzió ne jelenjen meg. Minden más érték pl.: UAT esetén meg fog jelenni a technikai azonosító is a láblécben.

Az /opt/project/infrastructure/config/backend-service könyvtárba helyezzük el a következő konfigurációs fájlokat:

/opt/project/infrastructure/config/backend-service/logback-spring.xml:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="io.gbsolutions.project.techcore.log.PatternMaskingLayout">
                <maskPattern>\"password\"\s*:\s*\"(.*?)\"</maskPattern>
                <maskPattern>password\s*:\s*(.*)</maskPattern>
                <maskPattern>\"newPassword\"\s*:\s*\"(.*?)\"</maskPattern>
                <maskPattern>newPassword\s*:\s*(.*)</maskPattern>
                <maskPattern>\"currentPassword\"\s*:\s*\"(.*?)\"</maskPattern>
                <maskPattern>currentPassword\s*:\s*(.*)</maskPattern>
                <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX} %green(%-5level) %magenta(${PID:- }) %yellow(%X{traceId:-}) --- %red(%X{remoteAddress}) %yellow(%X{userSessionIdentifier}) [%14thread]  %cyan(%-40.40logger{39}) : %replace(%replace(%replace(%replace(%replace(%replace(%msg){'[\s\n\r]+',' '}){'[&lt;]','%3C'}){'[&gt;]','%3E'}){'[&quot;]','%22'}){'[\&apos;]','%27'}){'[&amp;]','%26'}%n
                </pattern>
            </layout>
        </encoder>
    </appender>

    <appender name="SAVE-TO-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>/infrastructure/logs/backend-service.log</file>
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="io.gbsolutions.project.techcore.log.PatternMaskingLayout">
                <maskPattern>\"password\"\s*:\s*\"(.*?)\"</maskPattern>
                <maskPattern>password\s*:\s*(.*)</maskPattern>
                <maskPattern>\"newPassword\"\s*:\s*\"(.*?)\"</maskPattern>
                <maskPattern>newPassword\s*:\s*(.*)</maskPattern>
                <maskPattern>\"currentPassword\"\s*:\s*\"(.*?)\"</maskPattern>
                <maskPattern>currentPassword\s*:\s*(.*)</maskPattern>
                <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX} %-5level ${PID:- } %X{traceId:-} --- %X{remoteAddress} %yellow(%X{userSessionIdentifier}) [%14thread] %-40.40logger{39} :%replace(%replace(%replace(%replace(%replace(%replace(%msg){'[\s\n\r]+',' '}){'[&lt;]','%3C'}){'[&gt;]','%3E'}){'[&quot;]','%22'}){'[\&apos;]','%27'}){'[&amp;]','%26'}%n
                </pattern>
            </layout>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>/infrastructure/logs/backend-service-%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
            <maxFileSize>50MB</maxFileSize>
            <maxHistory>30</maxHistory>
            <totalSizeCap>10GB</totalSizeCap>
        </rollingPolicy>
    </appender>

    <logger name="io.gbsolutions" level="info" additivity="false">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="SAVE-TO-FILE"/>
    </logger>

    <logger name="liquibase" level="info" additivity="false">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="SAVE-TO-FILE"/>
    </logger>

    <logger name="org.apache.http" level="error" additivity="false">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="SAVE-TO-FILE"/>
    </logger>

    <logger name="org.springframework.ws.client.MessageTracing.sent" level="trace" additivity="false">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="SAVE-TO-FILE"/>
    </logger>

    <logger name="org.springframework.ws.server.MessageTracing.sent" level="trace" additivity="false">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="SAVE-TO-FILE"/>
    </logger>

    <logger name="org.springframework.ws.client.MessageTracing.received" level="trace" additivity="false">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="SAVE-TO-FILE"/>
    </logger>

    <logger name="org.springframework.ws.server.MessageTracing.received" level="trace" additivity="false">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="SAVE-TO-FILE"/>
    </logger>

    <logger name="org.apache.hc.client5.http.headers" level="debug" additivity="false">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="SAVE-TO-FILE"/>
    </logger>

    <logger name="org.apache.hc.client5.http.wire" level="debug" additivity="false">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="SAVE-TO-FILE"/>
    </logger>

    <root level="error" additivity="false">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="SAVE-TO-FILE"/>
    </root>
</configuration>

A fenti maxFileSize konfigurációs paraméter definiálja, hogy maximum 50MB méretű lehet egy log fájl.

A fenti maxHistory konfigurációs paraméter definiálja, hogy maximum 30 napig őrizzük meg a logfájlokat.

A fenti totalSizeCap konfigurációs paraméter definiálja, hogy összesen maximum 10GB-nyi logot őrzünk meg.

Amennyiben bármelyik értéket növelni/csökkenteni szeretnénk értelemszerűen a megfelelő konfigurációs paraméter értékét kell növelni/csökkenteni.

Például ha szeretnénk hogy 100MB méretű logfájljaink legyenek, amiket 60 napig őrzünk meg, de maximum 20GB-nyi logot tároljunk összesen, akkor a konfigurációs paraméterek értékének az alábbiakra kell módosulnia:

            <maxFileSize>100MB</maxFileSize>
            <maxHistory>60</maxHistory>
            <totalSizeCap>20GB</totalSizeCap>

Fontos, hogy az alapértelmezetten konfigurált 30 napnál régebbi logok megőrzésére az is megoldást ad, ha megfelelő időközönként a logfájlok egy külön tárhelyre archiválásra kerülnek.

Ezzel azt is elkerülhetjük, hogy túl sok helyet foglaljanak a logok az alkalmazás szerver számítógépén. Azonban szükség esetén mégis elérhetőek maradjanak a régebbi logfájlok.

5.6 Image fájlok

  1. Másoljuk fel az alkalmazás image fájlokat az alkalmazás szerverre.

  2. Lépjünk be az alkalmazásokat futtató felhasználóval. (Az 5.3-as pontban létrehozott felhasználóval.)

  3. Majd az alábbi parancsokkal töltsük be az image-eket a container storage-ba:

    docker load -i backend-service_1.0.0.tar
    docker load -i python-service_1.0.0.tar
    docker load -i webcomponent-spa_1.0.0.tar
    

5.7 Alkalmazások indítása

Az alkalmazás indításával kapcsolatos lépéseket az appuser felhasználóval végezzük el a szerveren.

Az itt található lépéseket az alkalmazást futtatni jogosult (az 5.3-as pontban létrehozott) felhasználóval végezzük el.

Az alkalmazások elindítása előtt módosítsuk a hozzuk létre az alábbi fájt. Ez a fájl megkönnyíti a jövőbeli telepítéseket is.

Hozzuk létre a docker-compose-services.yml fájlt az /opt/project/infrastructure/ mappába az alábbi parancsokkal:

cd /opt/project/infrastructure/

vim docker-compose-services.yml
A docker-compose-services.yml tartalma az alábbi legyen:
version: '3.1'

x-infrastructure-timezone-volume: &infrastructure-timezone-volume
  volumes:
    - infrastructure:/infrastructure
    - "/etc/timezone:/etc/timezone:ro"
    - "/etc/localtime:/etc/localtime:ro"  

x-timezone-volume: &timezone-volume
  volumes:
    - "/etc/timezone:/etc/timezone:ro"
    - "/etc/localtime:/etc/localtime:ro"

services:
  backend-service:
    image: 'registry.gitlab.com/gbsolutions/granit-bank/virtualis-asszisztens/backend/backend-service:${BACKEND_SERVICE_VERSION}'
    container_name: backend-service
    restart: always
    stop_grace_period: 30s
    ports:
      - 8080:8080
      - 5701:5701
    <<: *infrastructure-timezone-volume
    env_file:
      - .env
  webcomponent-spa:
    image: 'registry.gitlab.com/gbsolutions/granit-bank/virtualis-asszisztens/backend/webcomponent-spa:${CLIENT_SPA_VERSION}'
    container_name: webcomponent-spa
    restart: always
    ports:
      - 4204:4200
    <<: *timezone-volume
    env_file:
      - .env
  python-service:
    image: 'registry.gitlab.com/gbsolutions/granit-bank/virtualis-asszisztens/backend/python-service:${PYTHON_SERVICE_VERSION}'
    container_name: python-service
    restart: always
    ports:
      - 8000:8000
    env_file:
      - .env
    volumes:
      - "./logs:/app/infrastructure/logs"
      - "./models:/app/infrastructure/resources/models/dynamic"
      - "/etc/timezone:/etc/timezone:ro"
      - "/etc/localtime:/etc/localtime:ro"

volumes:
  infrastructure:
    driver: local
    driver_opts:
      device: $PWD # Wont work on Windows, set absolute path to the infrastructure folder
      o: bind
      type: none

networks:
  default:
    name: infrastructure-network
    external: true

Az alkalmazások az alábbi paranccsal indíthatóak el:

docker compose -f docker-compose-services.yml up -d

Az alkalmazások az alábbi paranccsal állíthatóak le:

docker compose -f docker-compose-services.yml down

5.8 Az APM használata

Az APM konfigurációjával kapcsolatos lépéseket az appuser felhasználóval végezzük el a szerveren.

Amennyiben szeretnénk monitorozni az alkalmazás performanciáját, akkor ez az APM segítségével könnyen megtehető.

Ehhez először is szükség lesz egy elasticsearch, kibana és agent-server telepítésére az alkalmazás szerverektől független másik gép(ek)re.

5.8.1 APM agent elhelyezése az alkalmazás szerver gépen

Az /opt/project/infrastructure mappába helyezzük el az elastic-apm-agent-1.38.0.jar-t.

5.8.2 APM bekötése a backend-service-be

Az APM bekötéséhez a /opt/project/infrastructure/.env fájlt szükséges módosítani:

A JAVA_TOOL_OPTIONS változót egészítsük ki az alábbi konfigurációkkal:

-javaagent:/infrastructure/elastic-apm-agent-1.38.0.jar -Delastic.apm.environment=${környezet} -Delastic.apm.service_name=${project-név} -Delastic.apm.service_node_name=backend-service-1 -Delastic.apm.server_urls=http://${IP}:${PORT} -Delastic.apm.application_packages=io.gbsolutions.project

A módosítás után így kell kinéznie a JAVA_TOOL_OPTIONS szekciónak:

JAVA_TOOL_OPTIONS="-Xms1g -Xmx2g -javaagent:/infrastructure/elastic-apm-agent-1.38.0.jar -Delastic.apm.environment=${környezet} -Delastic.apm.service_name=${project-név} -Delastic.apm.service_node_name=backend-service-1 -Delastic.apm.server_urls=http://${APM_IP}:${APM_PORT} -Delastic.apm.application_packages=io.gbsolutions.project"

Fontos, hogy a JAVA_TOOL_OPTIONS sorban ne módosítsuk az Xms és Xmx JVM paraméterek korábban megadott értékeit. (Értelemszerűen a 8GB memóriával rendelkező alkalmazás szerverek esetén az alábbi értékek fognak szerepelni: -Xms1g -Xmx4g.)

  • Ha több gépre is telepítve van a monitorozni kívánt alkalmazás, akkor a -Delastic.apm.service_node_name értékében található számlálót növeljük, hogy alkalmazáspéldányonként külön is tudjuk majd szűrni az adatokat.

  • Az ${APM_IP} és ${APM_PORT} placeholderek helyére annak a gépnek kell az IP címét és port számát megadni, amelyre az elasticsearch-t, kibana-t és agent-server-t telepítettük.

  • Az ${környezet} placeholder helyére az aktuális környezet azonosítóját kell behelyettesíteni (UAT, PROD). Pl.: éles környezet esetén: PROD.
  • Az ${projekt-név} placeholder helyére az alkalmazás nevét kell beírni.

6. Adatbázis

Az adatbázis üzemeltetése során kiemelt fontosságú a rendszeres backup-ok készítése, hogy katasztrófális hiba esetén a korábbi adatbázis állapotok visszaállíthatóak legyenek. Ezeket a backup fájlokat javasolt fizikailag is legalább két külön tárhelyen is megőrizni.

Ezen felül fontos, hogy rendelkezzünk forgatókönyvvel is az ilyen esetekre, mely forgatókönyvnek tartalmaznia kell az adatbázis rollback, vagy a backup visszatöltésének lépéseit.