From fb1a3d8581dd18cac129510459f3fd2537dfdff7 Mon Sep 17 00:00:00 2001 From: Bast Date: Tue, 3 Nov 2026 13:51:32 -0600 Subject: [PATCH] first commit --- .dockerignore | 9 + .env.example | 4 + .github/workflows/docker-publish.yml | 116 +++++++++++++ .gitignore | 4 + Dockerfile | 39 +++++ LICENSE.md | 22 +++ Metatrader/start.sh | 136 +++++++++++++++ README.md | 244 +++++++++++++++++++++++++++ charts/mt5/templates/_helpers.tpl | 32 ++++ charts/mt5/templates/deployment.yaml | 94 +++++++++++ charts/mt5/templates/ingress.yaml | 32 ++++ charts/mt5/templates/nano | 32 ++++ charts/mt5/templates/pvc.yaml | 20 +++ charts/mt5/templates/secret.yaml | 15 ++ charts/mt5/templates/service.yaml | 19 +++ docker-compose-windows.yaml | 14 ++ docker-compose.yaml | 13 ++ root/defaults/autostart | 1 + root/defaults/menu.xml | 7 + 19 files changed, 853 insertions(+) create mode 100644 .dockerignore create mode 100644 .env.example create mode 100644 .github/workflows/docker-publish.yml create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 LICENSE.md create mode 100644 Metatrader/start.sh create mode 100644 README.md create mode 100644 charts/mt5/templates/_helpers.tpl create mode 100644 charts/mt5/templates/deployment.yaml create mode 100644 charts/mt5/templates/ingress.yaml create mode 100644 charts/mt5/templates/nano create mode 100644 charts/mt5/templates/pvc.yaml create mode 100644 charts/mt5/templates/secret.yaml create mode 100644 charts/mt5/templates/service.yaml create mode 100644 docker-compose-windows.yaml create mode 100644 docker-compose.yaml create mode 100644 root/defaults/autostart create mode 100644 root/defaults/menu.xml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..aee85447 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +.devcontainer +.git +docker-compose.yaml +README.md +LICENSE.md +.gitignore +.env.example +.env +config diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..780834bc --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +UID=1000 +GID=1000 +CUSTOM_USER=username +PASSWORD=securepassword diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 00000000..a463a9bd --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,116 @@ +name: MT5 Helm GitOps Deploy + +on: + push: + branches: [ "main" ] + tags: [ "*" ] + workflow_dispatch: + +env: + # Gleicher Registry-Prefix wie im boday_tf-Projekt + REGISTRY: localhost:3005 + # Host-Header für Traefik-Ingress des Web-UI (leer = kein Ingress, kein Health-Check per HTTP) + INGRESS_HOST: mt5.local + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + container: catthehacker/ubuntu:act-latest + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + # HINWEIS: Terraform-Binary kommt wie bei boday_tf über das globale Runner-Volume (:ro) + + - name: Trust Local Nginx Certificate Inside Container + run: | + mkdir -p /usr/local/share/ca-certificates/ + cp nginx_ssl/nginx.crt /usr/local/share/ca-certificates/nginx-sandbox.crt 2>/dev/null || echo "Nutze Workspace-Zertifikat" + update-ca-certificates + + # Docker verlangt Image-Namen in Kleinbuchstaben – "MetaTrader5-Docker-Image" würde sonst scheitern + - name: Compute Image Name + run: | + IMAGE="${REGISTRY}/$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" + echo "IMAGE=${IMAGE}" >> "$GITHUB_ENV" + echo "Image: ${IMAGE}" + + - name: Log in to Local Registry + run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login ${REGISTRY} -u ${{ github.actor }} --password-stdin + + # Ein Build, zwei Tags (das Image ist ~4 GB – doppelt bauen kostet unnötig Zeit) + - name: Build MT5 Image + run: | + docker build --platform linux/amd64 \ + -t ${IMAGE}:${{ github.sha }} \ + -t ${IMAGE}:latest \ + . + + - name: Push MT5 Image + run: | + docker push ${IMAGE}:${{ github.sha }} + docker push ${IMAGE}:latest + + - name: Prepare Kubernetes Access + run: | + echo "${{ secrets.KUBECONFIG_DATA }}" > ./kind_kubeconfig + chmod 600 ./kind_kubeconfig + + # Erster Rollout kann bis 15 Min dauern (Wine + MT5 Installation nach /config) + - name: Terraform Deploy + env: + TF_VAR_vnc_password: ${{ secrets.MT5_VNC_PASSWORD }} + run: | + terraform --version + terraform init + terraform apply -auto-approve \ + -var="image_repository=${IMAGE}" \ + -var="app_version=${{ github.sha }}" \ + -var="vnc_user=${{ secrets.MT5_VNC_USER || 'trader' }}" \ + -var="ingress_host=${INGRESS_HOST}" + + # KasmVNC antwortet ohne Login mit 401 – daher mit Basic Auth prüfen und auf den Erststart warten + - name: Verify App Health + if: env.INGRESS_HOST != '' + env: + VNC_USER: ${{ secrets.MT5_VNC_USER || 'trader' }} + VNC_PASS: ${{ secrets.MT5_VNC_PASSWORD }} + run: | + for i in $(seq 1 40); do + CODE=$(curl -s -o /dev/null -w '%{http_code}' --connect-timeout 5 \ + -u "${VNC_USER}:${VNC_PASS}" -H "Host: ${INGRESS_HOST}" \ + http://local-k3s-platform:80/ || true) + echo "Versuch ${i}: HTTP ${CODE}" + if [ "${CODE}" = "200" ]; then + echo "Erfolg: MetaTrader 5 Web-UI läuft via Helm im GitOps-Standard!" + exit 0 + fi + sleep 15 + done + echo "MT5 Web-UI nach 10 Minuten nicht erreichbar" + exit 1 + + # Sensible Werte (VNC-Passwort) vor dem Upload aus dem State-JSON entfernen + - name: Publish Map to cloudmon Dashboard + run: | + terraform show -json \ + | jq 'del(.. | .set_sensitive?) | del(.. | .metadata? | select(type == "array") | .[]?.values?)' \ + > plan.json + + if grep -q "${{ secrets.MT5_VNC_PASSWORD }}" plan.json; then + echo "Abbruch: Passwort ist noch im JSON enthalten" + exit 1 + fi + + curl --fail -X POST \ + -H "Authorization: Bearer ${{ secrets.CLOUDMON_TOKEN }}" \ + -H "Content-Type: application/json" \ + -H "Host: cloudmon.local" \ + --data-binary @plan.json \ + "http://local-k3s-platform:80/api/v1/push/?repo=${{ github.repository }}" + + echo "Infrastruktur-Map erfolgreich an cloudmon übermittelt!" + + - name: Cleanup Kubeconfig + if: always() + run: rm -f ./kind_kubeconfig plan.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..a914e6c1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ + +.devcontainer/ +.env +config/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..3b5e79ed --- /dev/null +++ b/Dockerfile @@ -0,0 +1,39 @@ +FROM ghcr.io/linuxserver/baseimage-kasmvnc:debianbookworm + +# set version label +ARG BUILD_DATE +ARG VERSION +LABEL build_version="Metatrader Docker:- ${VERSION} Build-date:- ${BUILD_DATE}" +LABEL maintainer="gmartin" + +ENV TITLE=Metatrader5 +ENV WINEPREFIX="/config/.wine" +ENV WINEDEBUG=-all + +# Install all packages in a single layer to reduce image size +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + python3 \ + python3-pip \ + python3-venv \ + wget \ + curl \ + gnupg2 \ + software-properties-common \ + ca-certificates \ + && mkdir -pm755 /etc/apt/keyrings \ + && wget -O /etc/apt/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key \ + && wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/debian/dists/bookworm/winehq-bookworm.sources \ + && dpkg --add-architecture i386 \ + && apt-get update \ + && apt-get install --install-recommends -y winehq-stable \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /etc/apt/keyrings/winehq-archive.key + + +COPY /Metatrader /Metatrader +RUN chmod +x /Metatrader/start.sh +COPY /root / + +EXPOSE 3000 8001 +VOLUME /config diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000..7da4f585 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,22 @@ + +The MIT License (MIT) + +Copyright (c) 2023 Germán Martín + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Metatrader/start.sh b/Metatrader/start.sh new file mode 100644 index 00000000..77d77e38 --- /dev/null +++ b/Metatrader/start.sh @@ -0,0 +1,136 @@ +#!/bin/bash + +# Configuration variables +mt5file='/config/.wine/drive_c/Program Files/MetaTrader 5/terminal64.exe' +WINEPREFIX='/config/.wine' +WINEDEBUG='-all' +wine_executable="wine" +metatrader_version="5.0.36" +mt5server_port="8001" +MT5_CMD_OPTIONS="${MT5_CMD_OPTIONS:-}" +mono_url="https://dl.winehq.org/wine/wine-mono/10.3.0/wine-mono-10.3.0-x86.msi" +python_url="https://www.python.org/ftp/python/3.9.13/python-3.9.13.exe" +mt5setup_url="https://download.mql5.com/cdn/web/metaquotes.software.corp/mt5/mt5setup.exe" + +# Function to display a graphical message +show_message() { + echo $1 +} + +# Function to check if a dependency is installed +check_dependency() { + if ! command -v $1 &> /dev/null; then + echo "$1 is not installed. Please install it to continue." + exit 1 + fi +} + +# Function to check if a Python package is installed +is_python_package_installed() { + python3 -c "import pkg_resources; exit(not pkg_resources.require('$1'))" 2>/dev/null + return $? +} + +# Function to check if a Python package is installed in Wine +is_wine_python_package_installed() { + $wine_executable python -c "import pkg_resources; exit(not pkg_resources.require('$1'))" 2>/dev/null + return $? +} + +# Check for necessary dependencies +check_dependency "curl" +check_dependency "$wine_executable" + +# Install Mono if not present +if [ ! -e "/config/.wine/drive_c/windows/mono" ]; then + show_message "[1/7] Downloading and installing Mono..." + curl -o /config/.wine/drive_c/mono.msi $mono_url + WINEDLLOVERRIDES=mscoree=d $wine_executable msiexec /i /config/.wine/drive_c/mono.msi /qn + rm /config/.wine/drive_c/mono.msi + show_message "[1/7] Mono installed." +else + show_message "[1/7] Mono is already installed." +fi + +# Check if MetaTrader 5 is already installed +if [ -e "$mt5file" ]; then + show_message "[2/7] File $mt5file already exists." +else + show_message "[2/7] File $mt5file is not installed. Installing..." + + # Set Windows 10 mode in Wine and download and install MT5 + $wine_executable reg add "HKEY_CURRENT_USER\\Software\\Wine" /v Version /t REG_SZ /d "win10" /f + show_message "[3/7] Downloading MT5 installer..." + curl -o /config/.wine/drive_c/mt5setup.exe $mt5setup_url + show_message "[3/7] Installing MetaTrader 5..." + $wine_executable "/config/.wine/drive_c/mt5setup.exe" "/auto" & + wait + rm -f /config/.wine/drive_c/mt5setup.exe +fi + +# Recheck if MetaTrader 5 is installed +if [ -e "$mt5file" ]; then + show_message "[4/7] File $mt5file is installed. Running MT5..." + $wine_executable "$mt5file" $MT5_CMD_OPTIONS & +else + show_message "[4/7] File $mt5file is not installed. MT5 cannot be run." +fi + + +# Install Python in Wine if not present +if ! $wine_executable python --version 2>/dev/null; then + show_message "[5/7] Installing Python in Wine..." + curl -L $python_url -o /tmp/python-installer.exe + $wine_executable /tmp/python-installer.exe /quiet InstallAllUsers=1 PrependPath=1 + rm /tmp/python-installer.exe + show_message "[5/7] Python installed in Wine." +else + show_message "[5/7] Python is already installed in Wine." +fi + +# Upgrade pip and install required packages +show_message "[6/7] Installing Python libraries" +$wine_executable python -m pip install --upgrade --no-cache-dir pip +# Install MetaTrader5 library in Windows if not installed +show_message "[6/7] Installing MetaTrader5 library in Windows" +if ! is_wine_python_package_installed "MetaTrader5==$metatrader_version"; then + $wine_executable python -m pip install --no-cache-dir MetaTrader5==$metatrader_version +fi +# Install mt5linux library in Windows if not installed +show_message "[6/7] Checking and installing mt5linux library in Windows if necessary" +if ! is_wine_python_package_installed "mt5linux"; then + $wine_executable python -m pip install --no-cache-dir "mt5linux>=0.1.9" +fi + +# Install python-dateutil if needed (datetime is built-in, but dateutil adds features) +if ! is_wine_python_package_installed "python-dateutil"; then + show_message "[6/7] Installing python-dateutil library in Windows" + $wine_executable python -m pip install --no-cache-dir python-dateutil +fi + +# Install mt5linux library in Linux if not installed +show_message "[6/7] Checking and installing mt5linux library in Linux if necessary" +if ! is_python_package_installed "mt5linux"; then + pip install --break-system-packages --no-cache-dir --no-deps mt5linux && \ + pip install --break-system-packages --no-cache-dir rpyc plumbum numpy +fi + +# Install pyxdg library in Linux if not installed +show_message "[6/7] Checking and installing pyxdg library in Linux if necessary" +if ! is_python_package_installed "pyxdg"; then + pip install --break-system-packages --no-cache-dir pyxdg +fi + +# Start the MT5 server on Linux +show_message "[7/7] Starting the mt5linux server..." +python3 -m mt5linux --host 0.0.0.0 -p $mt5server_port -w $wine_executable python.exe & + +# Give the server some time to start +sleep 5 + +# Check if the server is running +if ss -tuln | grep ":$mt5server_port" > /dev/null; then + show_message "[7/7] The mt5linux server is running on port $mt5server_port." +else + show_message "[7/7] Failed to start the mt5linux server on port $mt5server_port." +fi diff --git a/README.md b/README.md new file mode 100644 index 00000000..6f1663e6 --- /dev/null +++ b/README.md @@ -0,0 +1,244 @@ +# MetaTrader5 Docker Image + +This project provides a Docker image for running MetaTrader5 with remote access via VNC, based on the [KasmVNC](https://github.com/kasmtech/KasmVNC) project and [KasmVNC Base Image from LinuxServer](https://github.com/linuxserver/docker-baseimage-kasmvnc). + +## Features + +- Run MetaTrader5 in an isolated environment. +- Remote access to MetaTrader5 interface via an integrated VNC client accessible through a web browser. +- Built on the reliable and secure [KasmVNC](https://github.com/kasmtech/KasmVNC) project. +- RPyC server for remote access to Python MetaTrader Library from Windows or Linux using + +![MetaTrader5 running inside container and controlled through web browser](https://imgur.com/v6Hm9pa.png) + +---------- + +**NOTICE:** +Due to some compatibility issued, version 2 has switched its base from Alpine to Debian Linux. This and adding Python environment makes that container size is considerably bigger from about 600 MB to 4 GB. + +If you just need to run Metatrader for running your MQL5 programs without any Python programming I recommend to go on using version 1.0. MetaTrader program is updated independently from image so you will always have latest MT5 version. + +---------- + +## Requirements + +- Docker installed on your machine. +- Only intelx86/amd64 host is supported + +## Usage from repository + +1. Clone this repository: + +```bash +git clone https://github.com/gmag11/MetaTrader5-Docker-Image +cd MetaTrader5-Docker-Image +``` + +2. Build the Docker image: + +```bash +docker build -t mt5 . +``` + +3. Run the Docker image: + +```bash +docker run -d -p 3000:3000 -p 8001:8001 -v config:/config mt5 +``` + +Now you can access MetaTrader5 via a web browser at localhost:3000. + +On first run it may take a few minutes to get everything installed and running. Normally it takes less than 5 minutes. You don't need to do anything. All installation process is automatic and you should end up with MetaTrader5 running in your web session. + +## Usage with docker compose with image form Docker Registry (preferred way) + +1. Create a folder in a path where you have permission. For instance in your home. + +```bash +mkdir MT5 +cd MT5 +``` + +2. Create `docker-compose.yaml` file. + +```bash +nano docker-compose.yaml +``` + +Use this content filling user and password with your own data. + +```yaml +version: '3' + +services: + mt5: + image: gmag11/metatrader5_vnc + container_name: mt5 + volumes: + - ./config:/config + ports: + - 3000:3000 + - 8001:8001 + environment: + - CUSTOM_USER= + - PASSWORD= +``` + +**Notice**: If you do not need to do remote python programming you can get a much smaller installation changing this line: + +```yaml +image: gmag11/metatrader5_vnc +``` + +by this one + +```yaml +image: gmag11/metatrader5_vnc:1.1 +``` + +---------- + +**Notice**: Due to Windows permission management, if you are using windows use Docker managed volume instead of bind mount. Use this compose file instead: + +```yaml +version: '3' +services: + mt5: + image: gmag11/metatrader5_vnc + container_name: mt5 + volumes: + - mt5_config:/config + ports: + - 3000:3000 + - 8001:8001 + environment: + - CUSTOM_USER= + - PASSWORD= + +volumes: + mt5_config: +``` + +---------- + +1. Start the container + +```bash +docker compose up -d +``` + +In some systems `docker compose` command does not exists. Try to use `docker-compose up -d` instead. + +4. Connect to web interface + +Start your browser pointing `http://:3000` + +On first run it may take a few minutes to get everything installed and running. Normally it takes less than 5 minutes. You don't need to do anything. All installation process is automatic and you should end up with MetaTrader5 running in your web session. + +## Where to place MQ5 and EX5 files + +In the case you want to run your own MQL5 bots inside the container you can find MQL5 folder structure in + +```bash +config/.wine/drive_c/Program Files/MetaTrader 5/MQL5 +``` + +All files that you place there can be accessed from your MetaTrader container without the need to restart anything. + +You can access MetaEditor program clicking in `IDE` button in MetaTrader5 interface. + +**Notice**: If you will run MQL5 only bots (without Python) you can run perfectly with gmag11/metatrader5_vnc:1.0 image as pointed before. Remember that **image version is not stuck to a specific MetaTrader 5 version**. + +**Metatrader will always be updated automatically to latest version as it does when it is nativelly installed in Windows.** + +## Python programming + +You need to install [mt5linux library](https://github.com/lucas-campagna/mt5linux) in your Python host. It may be in any OS, not only Linux. + +This is a simple snippet to run your Python script fron any host + +```python +from mt5linux import MetaTrader5 +mt5 = MetaTrader5(host='host running docker container',port=8001) +mt5.initialize() +print(mt5.version()) +``` + +Output should be something like this: + +```python +(mt5linux) linux:~/$ python3 +Python 3.10.13 (main, Dec 26 2023, 20:21:41) [GCC 13.2.0] on linux +Type "help", "copyright", "credits" or "license" for more information. +>>> from mt5linux import MetaTrader5 +>>> mt5 = MetaTrader5(host='192.168.1.10',port=8001) +>>> mt5.initialize() +True +>>> print(mt5.version()) +(500, 4120, '22 Dec 2023') +>>> +``` + +## Configuration + +The port configuration can be adjusted as per the instructions in the KasmVNC repository. + +### MetaTrader 5 Command Line Options + +You can pass command line options to MetaTrader 5 using the `MT5_CMD_OPTIONS` environment variable. This is useful for custom configurations, tester modes, or other MetaTrader command line parameters. + +Example using docker-compose: + +```yaml +version: '3' +services: + mt5: + image: gmag11/metatrader5_vnc + container_name: mt5 + volumes: + - mt5_config:/config + ports: + - 3000:3000 + - 8001:8001 + environment: + - CUSTOM_USER= + - PASSWORD= + - MT5_CMD_OPTIONS=/config:C:\\customized_for_tester_etc.ini + +volumes: + mt5_config: +``` + +Example using docker run: + +```bash +docker run -d -p 3000:3000 -p 8001:8001 \ + -e MT5_CMD_OPTIONS="/config:C:\\customized_for_tester_etc.ini" \ + -v mt5_config:/config \ + gmag11/metatrader5_vnc +``` + +Common MetaTrader 5 command line options: + +- `/config:` - Use a specific configuration file +- `/login:` - Automatically login to specified account + +For a complete list of available options, refer to the [MetaTrader 5 documentation](https://www.metatrader5.com/en/terminal/help/start_advanced/start). + +## Contributions + +Feel free to contribute to this project. All contributions are welcome. Open an issue or create a pull request. + +## License + +This project is licensed under the terms of the [MIT license](https://opensource.org/license/mit/). + +The [**KasmVNC**](https://github.com/kasmtech/KasmVNC) project is licensed under the [GNU General Public License v2.0 (GPLv2)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html). You can check the license details of KasmVNC [here](https://github.com/kasmtech/KasmVNC/blob/master/LICENSE.TXT). + +[**KasmVNC Base Image from LinuxServer**](https://github.com/linuxserver/docker-baseimage-kasmvnc) is licensed unther the GNU General Public License v3.0 (GPLv3). License is available [here](https://github.com/linuxserver/docker-baseimage-kasmvnc/blob/master/LICENSE) + +Please ensure to comply with the terms and conditions of the licenses while using or modifying this project. + +## Acknowledgments + +Acknowledgments to the [KasmVNC](https://github.com/kasmtech/KasmVNC) project, [KasmVNC Base Image from LinuxServer](https://github.com/linuxserver/docker-baseimage-kasmvnc/tree/master), [mt5linux library](https://github.com/lucas-campagna/mt5linux) and any other project or individual that contributed to the realization of this project. diff --git a/charts/mt5/templates/_helpers.tpl b/charts/mt5/templates/_helpers.tpl new file mode 100644 index 00000000..1e820386 --- /dev/null +++ b/charts/mt5/templates/_helpers.tpl @@ -0,0 +1,32 @@ +{{- define "mt5.fullname" -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "mt5.labels" -}} +app.kubernetes.io/name: mt5 +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/version: {{ .Values.image.tag | quote }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} +{{- end -}} + +{{- define "mt5.selectorLabels" -}} +app.kubernetes.io/name: mt5 +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{- define "mt5.secretName" -}} +{{- if .Values.auth.existingSecret -}} +{{ .Values.auth.existingSecret }} +{{- else -}} +{{ include "mt5.fullname" . }}-auth +{{- end -}} +{{- end -}} + +{{- define "mt5.claimName" -}} +{{- if .Values.persistence.existingClaim -}} +{{ .Values.persistence.existingClaim }} +{{- else -}} +{{ include "mt5.fullname" . }}-config +{{- end -}} +{{- end -}} diff --git a/charts/mt5/templates/deployment.yaml b/charts/mt5/templates/deployment.yaml new file mode 100644 index 00000000..9f93c8a2 --- /dev/null +++ b/charts/mt5/templates/deployment.yaml @@ -0,0 +1,94 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "mt5.fullname" . }} + labels: + {{- include "mt5.labels" . | nindent 4 }} +spec: + replicas: 1 + # RWO-Volume + Wine-Prefix: nie zwei Pods gleichzeitig + strategy: + type: Recreate + selector: + matchLabels: + {{- include "mt5.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "mt5.selectorLabels" . | nindent 8 }} + annotations: + checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} + spec: + # Pod ist lange beschäftigt beim Herunterfahren von Wine + terminationGracePeriodSeconds: 60 + containers: + - name: mt5 + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + envFrom: + - secretRef: + name: {{ include "mt5.secretName" . }} + env: + - name: TZ + value: {{ .Values.tz | quote }} + - name: PUID + value: {{ .Values.puid | quote }} + - name: PGID + value: {{ .Values.pgid | quote }} + {{- if .Values.mt5CmdOptions }} + - name: MT5_CMD_OPTIONS + value: {{ .Values.mt5CmdOptions | quote }} + {{- end }} + ports: + - name: web + containerPort: 3000 + protocol: TCP + - name: rpyc + containerPort: 8001 + protocol: TCP + # Erststart installiert Wine/MT5 (~5 Min) – bis 15 Min Zeit geben + startupProbe: + tcpSocket: + port: web + periodSeconds: 10 + failureThreshold: 90 + readinessProbe: + tcpSocket: + port: web + periodSeconds: 15 + livenessProbe: + tcpSocket: + port: web + periodSeconds: 30 + failureThreshold: 5 + volumeMounts: + - name: config + mountPath: /config + - name: dshm + mountPath: /dev/shm + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumes: + - name: config + {{- if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ include "mt5.claimName" . }} + {{- else }} + emptyDir: {} + {{- end }} + - name: dshm + emptyDir: + medium: Memory + sizeLimit: {{ .Values.shmSize }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/charts/mt5/templates/ingress.yaml b/charts/mt5/templates/ingress.yaml new file mode 100644 index 00000000..17b50e66 --- /dev/null +++ b/charts/mt5/templates/ingress.yaml @@ -0,0 +1,32 @@ +{{- if and .Values.ingress.enabled .Values.ingress.host }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "mt5.fullname" . }} + labels: + {{- include "mt5.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.className }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- with .Values.ingress.tls }} + tls: + {{- toYaml . | nindent 4 }} + {{- end }} + rules: + - host: {{ .Values.ingress.host | quote }} + http: + paths: + # Nur Web-UI (KasmVNC, inkl. WebSocket) – RPyC bleibt clusterintern + - path: / + pathType: Prefix + backend: + service: + name: {{ include "mt5.fullname" . }} + port: + name: web +{{- end }} diff --git a/charts/mt5/templates/nano b/charts/mt5/templates/nano new file mode 100644 index 00000000..17b50e66 --- /dev/null +++ b/charts/mt5/templates/nano @@ -0,0 +1,32 @@ +{{- if and .Values.ingress.enabled .Values.ingress.host }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "mt5.fullname" . }} + labels: + {{- include "mt5.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.className }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- with .Values.ingress.tls }} + tls: + {{- toYaml . | nindent 4 }} + {{- end }} + rules: + - host: {{ .Values.ingress.host | quote }} + http: + paths: + # Nur Web-UI (KasmVNC, inkl. WebSocket) – RPyC bleibt clusterintern + - path: / + pathType: Prefix + backend: + service: + name: {{ include "mt5.fullname" . }} + port: + name: web +{{- end }} diff --git a/charts/mt5/templates/pvc.yaml b/charts/mt5/templates/pvc.yaml new file mode 100644 index 00000000..e0feb089 --- /dev/null +++ b/charts/mt5/templates/pvc.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "mt5.claimName" . }} + labels: + {{- include "mt5.labels" . | nindent 4 }} + annotations: + # PVC bei helm uninstall behalten – sonst ist Wine-Prefix + Login weg + helm.sh/resource-policy: keep +spec: + accessModes: + - {{ .Values.persistence.accessMode }} + {{- if .Values.persistence.storageClass }} + storageClassName: {{ .Values.persistence.storageClass }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size }} +{{- end }} diff --git a/charts/mt5/templates/secret.yaml b/charts/mt5/templates/secret.yaml new file mode 100644 index 00000000..e279ecdc --- /dev/null +++ b/charts/mt5/templates/secret.yaml @@ -0,0 +1,15 @@ +{{- if not .Values.auth.existingSecret }} +{{- if not .Values.auth.password }} +{{- fail "auth.password muss gesetzt sein (oder auth.existingSecret verwenden)" }} +{{- end }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "mt5.secretName" . }} + labels: + {{- include "mt5.labels" . | nindent 4 }} +type: Opaque +stringData: + CUSTOM_USER: {{ .Values.auth.user | quote }} + PASSWORD: {{ .Values.auth.password | quote }} +{{- end }} diff --git a/charts/mt5/templates/service.yaml b/charts/mt5/templates/service.yaml new file mode 100644 index 00000000..c6c7939a --- /dev/null +++ b/charts/mt5/templates/service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mt5.fullname" . }} + labels: + {{- include "mt5.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + selector: + {{- include "mt5.selectorLabels" . | nindent 4 }} + ports: + - name: web + port: {{ .Values.service.webPort }} + targetPort: web + protocol: TCP + - name: rpyc + port: {{ .Values.service.rpycPort }} + targetPort: rpyc + protocol: TCP diff --git a/docker-compose-windows.yaml b/docker-compose-windows.yaml new file mode 100644 index 00000000..7b497a17 --- /dev/null +++ b/docker-compose-windows.yaml @@ -0,0 +1,14 @@ +services: + mt5: + build: . + image: gmag11/metatrader5_vnc + container_name: mt5 + volumes: + - mt5-config:/config + ports: + - 3000:3000 + - 8001:8001 + env_file: + - .env +volumes: + mt5-config: diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 00000000..00a0d427 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,13 @@ +services: + mt5: + build: . + image: gmag11/metatrader5_vnc + container_name: mt5 + volumes: + - ./config:/config + ports: + - 3000:3000 + - 8001:8001 + env_file: + - .env + diff --git a/root/defaults/autostart b/root/defaults/autostart new file mode 100644 index 00000000..0d5324ff --- /dev/null +++ b/root/defaults/autostart @@ -0,0 +1 @@ +/Metatrader/start.sh \ No newline at end of file diff --git a/root/defaults/menu.xml b/root/defaults/menu.xml new file mode 100644 index 00000000..69beb1dc --- /dev/null +++ b/root/defaults/menu.xml @@ -0,0 +1,7 @@ + + + +/usr/bin/xterm +/usr/bin/wine "/config/.wine/drive_c/Program Files/MetaTrader 5/terminal64.exe" + +