Skip to content

Repository files navigation

MT5 Docker — MetaTrader 5 in Docker with web VNC

English | Español

License: MIT Platform: linux/amd64 Base image: LinuxServer KasmVNC Wine: 11.0 stable

A Docker image for running MetaTrader 5 with remote access via web browser, based on KasmVNC and the LinuxServer base image.

Inspired by: gmag11/MetaTrader5-Docker-Image — this project starts from the same base idea but uses a different approach: a pre-configured WINEPREFIX (seed prefix) baked into the image instead of installing MT5, Mono, and Python at runtime.

Differences from the original project

Aspect Original This project
MT5 installation At runtime (download + installer) Pre-configured seed prefix at build
Wine Mono / Gecko Installed at runtime Disabled (WINEDLLOVERRIDES)
Python + mt5linux Included (port 8001) Removed — MQL5 only
VNC resolution Auto-detected (~1695x1038) Configurable, default 1920x1080
First-boot time 3-5 min (installation) Instant (seed copy)
Image size ~4 GB ~3.5 GB unpruned · ~2.5 GB pruned (see Seed prefix pruning)

Requirements

  • Docker installed
  • x86_64 / amd64 architecture
  • mt5-base-prefix must exist before building (see the Build section). If you already have a prefix generated on your host, you can migrate it with migrate-prefix-user.sh.

Quick start

docker run

docker run -d \
  --name mt5 \
  -p 3000:3000 \
  -v ./mt5_data:/config \
  --restart unless-stopped \
  mt5-docker:latest

Access MetaTrader 5 at http://localhost:3000.

docker compose

The repo includes a single docker-compose.yaml that covers both the single-account and multi-account cases. By default it starts one account on port 3000:

docker compose up -d

For multi-account, uncomment the mt5-account1, mt5-account2, ... services inside the compose file and start the ones you need:

docker compose up -d mt5-account1          # only account1 on :3001
docker compose up -d mt5 mt5-account1       # default + account1

Each service mounts its own volume (./mt5_data, ./mt5_accounts/N) and its own VNC port, so the accounts stay isolated. The repo's docker-compose.yaml ships with MT5_CLEAN_DEFAULT_ACCOUNT=1 by default so production is safe; set it to 0 if you want the demo account pre-connected for testing. See Default account sanitization on first boot.

The compose contents (summary):

x-common: &common
  image: mt5-docker:latest
  build: .
  restart: unless-stopped
  environment:
    DISPLAY_RESOLUTION: 1920x1080
    MT5_CLEAN_DEFAULT_ACCOUNT: "1"

services:
  mt5:
    <<: *common
    container_name: mt5
    volumes: [./mt5_data:/config]
    ports: ["3000:3000"]

  # Uncomment for multi-account:
  # mt5-account1:
  #   <<: *common
  #   container_name: mt5-account1
  #   volumes: [./mt5_accounts/account1:/config]
  #   ports: ["3001:3000"]

Access MetaTrader 5 at http://localhost:3000 (single account) or http://localhost:300N (account N in multi-account mode).

Bind mount vs named volume: the compose file uses relative bind mounts (./mt5_data:/config) so the data lives in a visible host path and you can inspect/copy EA configs directly. If you prefer Docker to manage the storage (useful when you don't need direct filesystem access), replace the bind mount with a named volume in the service and declare it at the end of the file:

services:
  mt5:
    volumes:
      - mt5-config:/config     # instead of ./mt5_data:/config
volumes:
  mt5-config:

This works the same on Linux and Windows.

Environment variables

Variable Default Description
DISPLAY_RESOLUTION 1920x1080 VNC resolution (e.g.: 1280x720, 1920x1080, 1920x1200)
MT5_CMD_OPTIONS (empty) Additional CLI arguments for MT5 (e.g.: /config:my_config.ini). Appended after /portable /skipupdate.
MT5_CLEAN_DEFAULT_ACCOUNT (empty) If it takes exactly the value 1, sanitizes the demo account inherited from the seed prefix on first boot. See Default account sanitization on first boot.

Wine Mono/Gecko install prompts

When initializing a new WINEPREFIX, Wine runs wineboot -u, which calls DllRegisterServer for mscoree. If the Mono runtime is not installed, Wine launches control.exe appwiz.cpl install_mono — a graphical dialog asking to install Wine Mono (and similarly Wine Gecko for mshtml). In an unattended deployment, this dialog blocks startup until the user manually dismisses it.

Why WINEDLLOVERRIDES in the environment is not enough

start.sh exports WINEDLLOVERRIDES="mscoree=;mshtml=" before launching MT5. But the processes that trigger the prompt (winedevice.exe, control.exe) are launched by wineserver during wineboot, before start.sh starts MT5, and they inherit the X session environment (openbox), not the environment of start.sh. That is why the environment variable does not propagate to those processes.

Solution: DllOverrides in the prefix registry

scripts/prune-prefix.sh persists the overrides in the seed prefix's user.reg, inside the [Software\\Wine\\DllOverrides] block:

"mscoree"=""
"mshtml"=""

An empty value suppresses the install prompt but keeps the DLLs available for any app that needs them in the future. This is the approach recommended by the Wine community (VasyaNovikov, SuperUser #1903388) when the goal is to silence the dialog without closing the door to Mono.

If you need .NET/Mono in the future: change the value to native,builtin and drop the Mono runtime into the container. The disabled value would block the prompt but break any .NET/HTML feature. The native,builtin value does not suppress the prompt — it only controls load order, and the prompt fires earlier, during prefix initialization.

The environment variable in start.sh remains as defense-in-depth for the processes that do inherit the start.sh environment.

MT5 automatic updates

MetaQuotes officially states that the auto-update system "cannot be disabled" — there is no checkbox in the UI or supported option for that. This image passes /skipupdate on the command line, but does not block updates at the filesystem level.

Mechanism 1: /skipupdate on the command line

start.sh passes this flag to terminal64.exe:

$wine_executable "$mt5file" /portable /skipupdate $MT5_CMD_OPTIONS &

/skipupdate prevents MT5 from checking for and downloading updates when connecting to the trading server.

Caveat: /skipupdate is not 100% reliable. MetaQuotes states that the update system cannot be disabled; the flag may be ignored in certain builds or by certain brokers, and the update prompt may still appear.

Why this image does not block updates at the filesystem level

This image does not block updates at the filesystem level. Previous attempts were ineffective:

  • Empty liveupdate file: on modern MT5 builds (4000+), MT5 deletes the empty file and recreates the directory.
  • chmod a-w on the hash dir: Wine rewrites the hash dir owner to the runtime user (abc, UID 911) on every boot, and abc can revert any chmod a-w applied at build time because it is the owner.

If automatic updates are a problem for your deployment, consider:

  • Blocking the MetaQuotes IP at the firewall level (container network or host).
  • Restoring the original .exe files after an update from the clean installer, regenerating the prefix with generate-prefix.sh.

What to do when you want to update deliberately

Updates should be a conscious decision, not something that happens in the background during a trading session. To update:

  1. Download the latest MT5 installer from mql5.com.
  2. Regenerate the prefix: ./scripts/generate-prefix.sh (uses the new installer).
  3. Rebuild the image: docker build -t mt5-trimmed:latest .
  4. Recreate the container with a fresh volume (or preserve the account configuration by copying MQL5/ and config/ from the previous volume).

Important: in an unattended multi-account deployment, an automatic update can break running EAs (MQL5 API changes), change terminal behavior without warning, or restart MT5 in the middle of an operation. Keeping updates under conscious control is the safe choice for production.

Sources

Build

Prerequisite: generate the seed prefix

The mt5-base-prefix is a pre-configured WINEPREFIX with MT5 installed, vcrun2019, and win10 mode. It is not included in the repo (1.5–3.0 GB depending on whether pruning is applied) and must be generated once.

This process is INTERACTIVE. The MT5 installer is a GUI application that cannot run unattended. The script launches a temporary container with KasmVNC (web-based VNC) and opens a browser window so you can click through the MT5 installer wizard. You need a desktop browser — you cannot run this on a headless server without port forwarding.

Why it must be generated inside a container

The LinuxServer base image (baseimage-kasmvnc:debianbookworm) uses the abc user (UID 911) at runtime. If you generate the prefix on your host with your local user (e.g.: guillermo, UID 1000), the prefix is configured for C:\users\guillermo\, but the container runs Wine as abc. This produces a dual profile: Wine creates C:\users\abc\ at runtime and the seed prefix has hardcoded paths to C:\users\guillermo\ in the registry.

To avoid this, the prefix must be generated inside a container that uses the same abc user as the runtime. The scripts/generate-prefix.sh script does this automatically.

Automated generation (recommended)

./scripts/generate-prefix.sh

The script follows the official MetaQuotes installation procedure and does the following:

  1. Launches a temporary container from baseimage-kasmvnc:debianbookworm with KasmVNC active on port 3000.
  2. Installs winehq-staging as root (NOT winehq-stable — Wine 11 stable triggers MT5's anti-debugger check, which blocks the installer with "A debugger has been found running in your system". The official MetaQuotes mt5linux.sh script uses winehq-staging, which has Wine 10.x available and does not trigger this check).
  3. Prepares the WINEPREFIX as user abc (the same user the container will use at runtime):
    • Pre-seeds user.reg with DllOverrides (mscoree="", mshtml="") to suppress future Wine Mono/Gecko install prompts.
    • Runs wineboot -u (initializes the prefix — requires the KasmVNC display to create the registry hives and user profile).
    • Sets win10 mode with reg add.
    • Installs vcrun2019 via winetricks.
    • Downloads the MT5 installer.
  4. Pauses and prompts you to open http://localhost:3000 in your browser. You click through the MT5 installer GUI (accept EULA → Install → Finish). When done, return to the terminal and press ENTER.
  5. Verifies that terminal64.exe exists and that the user profile is abc.
  6. Runs scripts/prune-prefix.sh automatically (optional reversible pruning, see Seed prefix pruning). Use --no-prune to skip it.
# Without pruning (full prefix, ~3.0 GB):
./scripts/generate-prefix.sh --no-prune

# With pruning (trimmed prefix, ~1.5 GB):
./scripts/generate-prefix.sh

The result is an mt5-base-prefix/ with profile C:\users\abc\, aligned with the container runtime.

Wine Mono/Gecko dialogs: During wineboot -u, two dialogs may appear requesting to install Wine Mono and Wine Gecko. Cancel both — MT5 needs neither. The pre-seeded DllOverrides suppress future prompts, but the first wineboot may still show them.

sudo required for pruning: The prefix files are owned by abc (UID 911), so prune-prefix.sh needs sudo to modify them: sudo ./scripts/prune-prefix.sh.

Manual generation (advanced)

If you prefer to do it step by step, the equivalent commands are below. Run them in this exact order — skipping steps produces an inconsistent prefix. This is an interactive process: step 4 requires a VNC display to run the MT5 installer GUI.

# 1. Launch a temporary container with KasmVNC active
docker run -d --name mt5-prefix-builder \
  -p 3000:3000 \
  -v $(pwd)/mt5-base-prefix:/config/.wine \
  -e VNC_PASSWORD=mt5builder \
  ghcr.io/linuxserver/baseimage-kasmvnc:debianbookworm

# 2. Fix /config ownership so abc can write
docker exec -u 0 mt5-prefix-builder bash -c '
  mkdir -p /config && chown abc:abc /config && chmod 755 /config
'

# 3. Install winehq-staging as root (NOT stable — Wine 11 stable triggers
#    MT5's anti-debugger check)
docker exec -u 0 mt5-prefix-builder bash -c '
  apt-get update
  apt-get install -y --no-install-recommends wget gnupg2 software-properties-common ca-certificates winetricks cabextract
  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 -y --install-recommends winehq-staging wine-mono
  apt-get clean && rm -rf /var/lib/apt/lists/*
'

# 4. Prepare the prefix as user abc (pre-seed DllOverrides, wineboot,
#    win10, vcrun2019, download MT5 installer)
docker exec -u abc mt5-prefix-builder bash -c '
  export WINEPREFIX=/config/.wine USER=abc USERNAME=abc
  export WINEDLLOVERRIDES="mscoree,mshtml=n,b" WINEDEBUG=-all
  export XDG_CACHE_HOME=/config/.cache XDG_DATA_HOME=/config/.local/share
  export XDG_RUNTIME_DIR=/config/.runtime
  mkdir -p $XDG_CACHE_HOME $XDG_DATA_HOME $XDG_RUNTIME_DIR
  chmod 700 $XDG_RUNTIME_DIR
  # Pre-seed user.reg with DllOverrides BEFORE wineboot
  mkdir -p $WINEPREFIX
  cat > $WINEPREFIX/user.reg <<EOF
WINE REGISTRY Version 2
;; All keys relative to \\User

[Software\\Wine\\DllOverrides]
"mscoree"=""
"mshtml"=""
EOF
  # wineboot may show Mono/Gecko dialogs — CANCEL both
  wineboot -u
  wineserver -w 2>/dev/null || true
  wine reg add "HKLM\\Software\\Wine" /v Version /t REG_SZ /d win10 /f
  winetricks -q vcrun2019
  wget -qO /tmp/mt5setup.exe https://download.mql5.com/cdn/web/metaquotes.software.corp/mt5/mt5setup.exe
'

# 5. Open http://localhost:3000 in your browser (VNC password: mt5builder)
#    Open a terminal in the VNC desktop and run:
#      export WINEPREFIX=/config/.wine USER=abc USERNAME=abc DISPLAY=:1
#      wine /tmp/mt5setup.exe
#    Click through the MT5 installer: Accept EULA → Install → Finish

# 6. Verify MT5 was installed
ls "mt5-base-prefix/drive_c/Program Files/MetaTrader 5/terminal64.exe"

# 7. Remove the temporary container
docker rm -f mt5-prefix-builder

# 8. (Optional) Prune the prefix (requires sudo — files are owned by abc UID 911)
sudo ./scripts/prune-prefix.sh

Note on Wine Mono/Gecko prompts

When running wineboot -u, Wine may display dialogs requesting to install Wine Mono and Wine Gecko. Cancel both — MT5 needs neither. MT5 is a native 64-bit application that does not require .NET or an HTML engine.

The generate-prefix.sh script pre-seeds user.reg with DllOverrides ("mscoree"="", "mshtml"="") before wineboot, which suppresses these prompts on future Wine invocations. However, the first wineboot may still show the dialogs because wineserver-launched processes (winedevice.exe, control.exe) run before the registry override takes full effect.

The same DllOverrides are persisted by prune-prefix.sh and loaded by start.sh at runtime, so the prompts do not reappear when the container boots.

The MT5 installer also downloads and installs Microsoft Edge WebView2 (~1.9 GB) as part of the process. It is not required to run MT5: it only feeds the embedded "Community/News" panel in the terminal. See the Seed prefix pruning section to remove it and save ~1 GB in the image and in every account volume.

Build the image

docker build -t mt5-docker:latest .

Seed prefix pruning (optional)

The MT5 installer pulled during prefix generation includes components that are not necessary for trading and consume space both in the image and in every account volume (they are copied on first boot). The following table summarizes what can be safely removed:

Path inside mt5-base-prefix/ Size Can be removed Notes
drive_c/Program Files (x86)/Microsoft/ ~1.9 GB ✅ Yes Microsoft Edge WebView2 + EdgeCore + duplicated installer. Only feeds the embedded "Community/News" panel. Without it, that tab is blank but the rest of the terminal works normally.
drive_c/Program Files/msedge_installer.log ~100 KB ✅ Yes Edge installer log. Orphan.
drive_c/ProgramData/MetaQuotes/ML/ ~216 MB ⚠️ Conditional ONNX engine (ML models). Only remove this if your EAs do not use OnnxRun or .onnx models. If you do algorithmic trading with ML, leave it.
drive_c/users/<user>/AppData/Roaming/MetaQuotes/WebInstall/ ~124 MB ✅ Yes LiveUpdate packages (the .png files are disguised compressed blobs). They are re-downloaded if MT5 needs to update.
drive_c/users/<user>/AppData/Roaming/MetaQuotes/Terminal/Help/ ~28 MB ✅ Yes Offline help (mt5terminal_spanish.help). You lose F1 inside MT5.

Safe total without touching ONNX: ~2.05 GB → 3.0 GB prefix becomes ~1.1 GB. Total with ONNX removed: ~2.27 GB → prefix becomes ~0.9 GB.

Registry cleanup after pruning

When removing Program Files (x86)/Microsoft/, the Edge registry keys in mt5-base-prefix/user.reg become orphaned. They do not break startup, but it is a good idea to clean them to avoid Wine warnings. The blocks to remove are:

  • [Software\\Microsoft\\Edge]
  • [Software\\Microsoft\\EdgeUpdate\\ClientState\\{F3017226-...}]
  • [Software\\Microsoft\\EdgeWebView] and all its subblocks (BLBeacon, PreferenceMACs, StabilityMetrics)
  • [Software\\Wine\\AppDefaults\\msedgewebview2.exe]

Each block includes its [...] header with timestamp and the #time=... line that follows it.

Automated pruning script

# From the repo root, with mt5-base-prefix/ generated:
./scripts/prune-prefix.sh

The script moves the removable components to .prefix-backup/ (reversible rollback) and cleans the user.reg registry keys. Verify the resulting size with:

du -sh mt5-base-prefix

Rollback

If MT5 does not start after pruning, restore the backup:

mv .prefix-backup/Microsoft.x86 "mt5-base-prefix/drive_c/Program Files (x86)/Microsoft"
git checkout -- mt5-base-prefix/user.reg   # if you were tracking the prefix
docker build -t mt5-docker:latest .

Migrating a host-generated prefix (optional)

If you generated the prefix on your host machine (with your local user, e.g.: guillermo) instead of inside a container (with the abc user), the prefix will have a dual user profile: C:\users\<your_user>\ in the registry and C:\users\abc\ created by Wine at runtime. This does not break MT5, but it is dirty state that can be confusing.

The scripts/migrate-prefix-user.sh script fixes this without needing to regenerate the prefix from scratch:

# See what the script would do (without modifying anything):
./scripts/migrate-prefix-user.sh --dry-run

# Apply the migration:
./scripts/migrate-prefix-user.sh

The script:

  1. Removes the non-abc user directories under drive_c/users/ (e.g.: users/guillermo/). In portable mode, the functional data (account, EAs, configs) lives in Program Files/MetaTrader 5/, not in the user profile — so nothing operational is lost.
  2. Replaces C:\users\<old_user> with C:\users\abc in the .reg files (system.reg, user.reg, userdef.reg) so Wine correctly resolves %AppData%, %TEMP%, etc. for the active user.
  3. Removes the PackagePath registry entry (it points to the host filesystem, e.g.: Z:\home\guillermo\Descargas\).

MT5 will recreate users/abc/AppData/Roaming/MetaQuotes/Terminal/D0E8.../ with portable.txt and origin.txt automatically on first boot, thanks to the /portable flag that start.sh passes to terminal64.exe.

Note: This migration is a fast alternative to generate-prefix.sh when you already have a working prefix generated on the host. If you generate the prefix from scratch with generate-prefix.sh, you do not need this step.

MT5 portable mode

MT5 has two data storage modes:

Mode Where it stores account data, configs, and EAs Activated by
Normal AppData/Roaming/MetaQuotes/Terminal/<hash>/ (Windows user profile) Default behavior on real Windows
Portable Next to the executable, in Program Files/MetaTrader 5/ /portable flag on the command line, or the existence of an empty portable.txt file in <hash>/

In this container, start.sh forces portable mode by passing /portable to terminal64.exe explicitly (see the next section).

In this container: MT5 starts in portable mode

Portable mode is forced explicitly in start.sh by passing the /portable flag to terminal64.exe:

$wine_executable "$mt5file" /portable $MT5_CMD_OPTIONS &

This guarantees that MT5 saves account data, configs, and EAs next to the executable in Program Files/MetaTrader 5/, regardless of whether a portable.txt file exists in the user profile. We do not depend on the MetaQuotes installer's automatic behavior (which may or may not create portable.txt under Wine depending on the version).

You can confirm it by inspecting the volume after the first boot:

ls mt5_data/.wine/drive_c/users/<user>/AppData/Roaming/MetaQuotes/Terminal/D0E8209F77C8CF37AD8BF550E51FF075/
# origin.txt      → contains the installation path (C:\Program Files\MetaTrader 5)
# portable.txt    → empty file, portable mode flag (pre-exists in the seed)
# liveupdate/     → directory created by MT5 at runtime (see MT5 automatic updates)

The hash D0E8209F77C8CF37AD8BF550E51FF075 is the identifier MT5 computes from the installation path (C:\Program Files\MetaTrader 5). It is stable across restarts of the same container (the path does not change) and across containers (the internal path is always the same).

Implications for multi-account deployment

In portable mode, account data (login, history, symbols, terminal configuration, loaded EAs) lives next to the executable in Program Files/MetaTrader 5/, not in AppData/Roaming/. Since each container mounts its own volume at /config, each account stays isolated:

/config/.wine/drive_c/Program Files/MetaTrader 5/
├── MQL5/
│   ├── Experts/          # EAs for this account
│   ├── Indicators/
│   ├── Scripts/
│   └── Libraries/
├── config/               # terminal configs for this account
├── logs/                 # logs for this account
├── Tester/               # strategy tester data
└── terminal64.exe        # binary (shared, immutable from the EA)

The AppData/Roaming/MetaQuotes/Terminal/<hash>/ folder still exists, but in portable mode it only stores installation metadata (origin.txt, portable.txt, liveupdate) — not the functional account data.

What this means for you

  • EAs and config per account: each container has its own MQL5/Experts/ folder. An EA loaded in one account is not visible in another.
  • No shared state between accounts: to share an EA between accounts, copy the .ex5 to each container (see the next section).
  • Persistence: when you stop and start the container (docker stop / docker start), the account, login, EAs, and configuration are preserved because they live in the /config volume, not inside the image.
  • When recreating the container (docker rm + docker run) with the same volume, the state is also preserved: the container is stateless, the volume is the source of truth.

Default account sanitization on first boot

The seed prefix (mt5-base-prefix) is generated with a MetaQuotes demo account logged in (Login=5053564303, Server=MetaQuotes-Demo). This is deliberate: it lets you start a new container, open VNC, and find MT5 already connected, without having to log in manually — very convenient for testing and development.

The problem is that, in portable mode, account data lives in Program Files/MetaTrader 5/Config/ (next to the executable), which is exactly where the seed prefix leaves it. Without sanitization, every new container would try to reconnect to the same MetaQuotes demo account on startup. MetaQuotes limits concurrent connections per account, so in a real multi-account deployment this produces temporary locks, disconnects, and never connects to the intended broker account.

MT5_CLEAN_DEFAULT_ACCOUNT

The MT5_CLEAN_DEFAULT_ACCOUNT environment variable controls sanitization. The gate is strict: only the exact value 1 activates it. Any other value (empty, 0, true, yes, false...) disables it and leaves the seed's demo account in place.

environment:
  - MT5_CLEAN_DEFAULT_ACCOUNT=1   # sanitization enabled
  - MT5_CLEAN_DEFAULT_ACCOUNT=0   # sanitization disabled (demo account stays)
  - MT5_CLEAN_DEFAULT_ACCOUNT=    # sanitization disabled

When active, start.sh — on the first boot, right after copying the seed prefix to the volume — deletes the cached accounts.dat and empties the Login= and Server= lines in common.ini. The result is an MT5 that starts clean, with no preconfigured account, ready for the user to enter their own.

Why it only runs on first boot

Sanitization lives inside the seeding branch of start.sh:

if [ ! -d "/config/.wine/drive_c" ]; then
    # First boot: copy seed prefix + optional sanitization
    ...
fi

Once the first boot creates /config/.wine/drive_c/, that branch does not run again — neither on restarts (docker stop/docker start), nor when recreating the container (docker rm + docker run) on the same volume. The account the user configures manually after sanitization is persisted in the volume and preserved across restarts.

Event Seeding? Sanitization?
First boot with MT5_CLEAN_DEFAULT_ACCOUNT=1 Yes Yes (once)
Later restarts No No
docker rm + docker run on the same volume No No
New volume with MT5_CLEAN_DEFAULT_ACCOUNT=1 Yes Yes (again, once)
New volume without the variable (or with =0, =) Yes No (current behavior, useful for testing)

Important: changing the value of MT5_CLEAN_DEFAULT_ACCOUNT between boots on the same volume has no effect — the seeding branch no longer runs. To sanitize again you must start with a fresh volume.

What exactly gets sanitized

File Action Why
Program Files/MetaTrader 5/Config/accounts.dat Deleted Contains the cached demo account session (obfuscated binary). MT5 recreates it empty on startup if it does not exist.
Program Files/MetaTrader 5/Config/common.ini Login= and Server= lines emptied It is UTF-16LE with BOM and CRLF; start.sh uses iconv for the byte-exact roundtrip and sed to empty only those two lines. The rest of the file (Environment, Proxy, Charts, Trades, Experts...) is preserved intact.

Verification

After the first boot with MT5_CLEAN_DEFAULT_ACCOUNT=1, you can confirm that sanitization was applied by inspecting the volume:

# common.ini should have empty Login= and Server=
iconv -f UTF-16 -t UTF-8 \
  "mt5_data/.wine/drive_c/Program Files/MetaTrader 5/Config/common.ini" \
  | grep -E "^(Login|Server)="
# Expected:
# Login=
# Server=

# accounts.dat should not exist
ls "mt5_data/.wine/drive_c/Program Files/MetaTrader 5/Config/accounts.dat" 2>&1
# Expected: No such file or directory

Recommendation per use case

  • Testing / development: leave MT5_CLEAN_DEFAULT_ACCOUNT unset (or set it to 0). You start with the demo connected and save the login.
  • Real multi-account deployment: set MT5_CLEAN_DEFAULT_ACCOUNT=1 in the production compose file. Each container starts clean and the user enters their broker login once; from then on it is persisted in the volume. The repo's docker-compose.yaml already ships MT5_CLEAN_DEFAULT_ACCOUNT=1 by default so the sanitized behavior is the safe one for production; remove it (or set it to 0) if you want the demo-connected behavior for testing.

Where to place EAs, indicators, and scripts

The MQL5 structure is at:

mt5_data/.wine/drive_c/Program Files/MetaTrader 5/MQL5/
├── Experts/       # Expert Advisors
├── Indicators/    # Custom indicators
├── Scripts/       # Scripts
└── Libraries/     # Libraries

You can copy files with docker cp:

docker cp my_ea.ex5 mt5:"/config/.wine/drive_c/Program Files/MetaTrader 5/MQL5/Experts/"

Or directly to the volume if you use a bind mount:

cp my_ea.ex5 "mt5_data/.wine/drive_c/Program Files/MetaTrader 5/MQL5/Experts/"

You do not need to restart the container — MT5 detects the changes when the Navigator is reloaded.

Architecture

┌─────────────────────────────────────────┐
│  Docker Container                       │
│  ┌──────────────┐  ┌─────────────────┐  │
│  │  KasmVNC     │  │  WineHQ 11.0    │  │
│  │  (port       │──│  + MT5 (win64)  │  │
│  │   3000)      │  │                 │  │
│  └──────────────┘  └─────────────────┘  │
│         │                  │            │
│         ▼                  ▼            │
│  ┌──────────────────────────────────┐   │
│  │  /config (VOLUME)                │   │
│  │  └── .wine/ (seeded on 1st boot) │   │
│  └──────────────────────────────────┘   │
└─────────────────────────────────────────┘

The seed prefix (/mt5-base-prefix) is copied to /config/.wine on the first boot if the volume is empty. This allows MT5 configuration, accounts, and EAs to persist across restarts.

License

MIT — see LICENSE.md.

KasmVNC is under GPLv2 and the LinuxServer base image under GPLv3.

About

Docker image for MetaTrader 5 with web VNC access (KasmVNC). Seed prefix approach — instant first boot, no runtime installation.

Topics

Resources

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages