🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
Advanced Docker Compose Configuration for MDriven
Created by Charles on 2024-11-11 · Last edited by Charles on 2026-04-11.

This guide explains the complete architecture and configuration of the advanced MDriven Docker Compose setup. Unlike a manual build process, this configuration leverages official pre-built MDriven images from Docker Hub, bundled together with a MySQL database, an Nginx reverse proxy, and a built-in web-based Code Server (SCM) for managing your files.

Start by installing Docker Desktop. Docker Desktop provides the environment and tools required for managing and running containers on your local machine.

1. Folder Structure

To ensure all the bindings in the compose file work correctly, your project root must contain the following file and folder structure. These files handle credentials, initialization scripts, and application overrides.

\---Apps (Project Root)

   |   compose.yaml                          - [The main orchestration file]
   \---databases
       \---mysql
           |   mysql.env                     - [Environment variables/passwords for MySQL]
           \---init                          - [Folder for .sql schema initialization scripts]
   \---settings
       |   nginx-proxy.conf                  - [Nginx routing configuration]
       \---mdriven-server
           |   CommandLineOverride.xml       - [Server startup overrides]
           |   DatabaseVistaDB.vdb6          - [Admin database for the Server]
           |   PwdReset.txt                  - [Optional: Create to reset User 'a' password]
       \---mdriven-turnkey
           |   CommandLineOverride.xml       - [Turnkey startup overrides]
           |   HardServerUrl.xml             - [Specifies the Turnkey URL]
           |   MDrivenServerOverride.xml     - [Settings for Turnkey to connect to Server]
           |   TurnkeySettingsOverride.xml   - [Additional Turnkey overrides]
       \---vscode                            - [Optional: Stricter permissions/settings for SCM]

Important Configuration Files Explained

To understand exactly what settings and variables go into these XML files, please refer to their dedicated documentation pages:

  • CommandLineOverride.xml: Used by both the MDriven Server and Turnkey to inject startup arguments (for example, defining a subdirectory path like pathtoapp=/__MDrivenServer, specifying host name and port).
  • HardServerUrl.xml: Specifies the exact URL (and port) that will be used to access the Turnkey application externally.
  • MDrivenServerOverride.xml: Configures how the Turnkey application connects to the MDriven Server. It holds the internal routing URL (e.g., http://server-core:5010) and the credentials for User 'a'.
  • TurnkeySettingsOverride.xml: Used for overriding Turnkey behaviour and enabling or disabling Turnkey Features.

2. Understanding the Services

The compose file orchestrates five distinct services working together seamlessly:

  1. mysql: Runs MySQL 8.0. It maps a local ./mysql-data folder for data persistence and uses an init folder to run initialization scripts. It includes a strict health check to ensure the database is fully responsive before dependent services start.
  2. server-core: The core MDriven Server running the ubuntu-amd64 image. It mounts your configurations and the VistaDB admin file directly into the container. It runs as a limited user (PUID=1000) for security and relies on the MySQL service being healthy before starting.
  3. turnkey-core: The MDriven Turnkey application. It mounts its specific XML overrides and connects to the MDriven Server. Like the server, it runs with limited privileges and includes a robust health check.
  4. scm (Code Server): A very powerful addition. This runs a web-based version of Visual Studio Code (lscr.io/linuxserver/code-server). By mapping the MDSData and MDTData volumes into its workspace, it allows developers to edit server and turnkey files, as well as easily view application logs directly from their browser on port 8080!
  5. nginx: An Alpine-based Nginx proxy. It acts as the gatekeeper, relying on a custom nginx-proxy.conf file to route traffic efficiently. It exposes ports 5011, 5012, and 8080.

3. The Complete Docker Compose File

Here is the complete compose.yaml configuration. Place this in the root of your project directory.

name: MDriven

services:
  
  mysql: # MDriven Server Connection String  --- Server=mysql;port=3306;Database=mdriven_db;Uid=mdriven;Pwd=123456;
    image: mysql:8.0
    restart: on-failure:5
    
    env_file:
      - ${PROJECT_ROOT:-.}/databases/mysql/mysql.env

    volumes:
      - ./mysql-data:/var/lib/mysql
      - ${PROJECT_ROOT:-.}/databases/mysql/init:/docker-entrypoint-initdb.d:ro

    healthcheck:
      test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -u root -p $MYSQL_ROOT_PASSWORD || exit 1"]
      interval: 10s
      timeout: 20s
      retries: 5
      start_period: 30s

  server-core:
    platform: linux/amd64
    image: mdriven/mdriven-server:ubuntu-amd64
    
    volumes:
      - type: volume
        source: MDSData
        target: /app

      ## Uncomment to reset User 'a' password
      # - type: bind
      #   source: ${PROJECT_ROOT:-.}/settings/mdriven-server/PwdReset.txt
      #   target: /pwdreset/PwdReset.txt

      - type: bind
        source: ${PROJECT_ROOT:-.}/settings/mdriven-server/CommandLineOverride.xml
        target: /app/App_Data/CommandLineOverride.xml
      
      - type: bind
        source: ${PROJECT_ROOT:-.}/settings/mdriven-server/DatabaseVistaDB.vdb6
        target: /app/App_Data/DatabaseVistaDB.vdb6

    depends_on:
      mysql:
        condition: service_healthy
        restart: true
    
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5011/"]
      interval: 10s
      timeout: 10s
      retries: 5
      start_period: 30s

    environment:
      - PUID=1000
      - PGID=1000
      # - UPDATE_APP=true # set true for latest version or yyyymmdd for specific version

    restart: on-failure:5

    entrypoint: ["/bin/sh","/usr/local/bin/entrypoint.sh"]

    command: ["dotnet", "AppCompleteGenericCore.dll"]

  turnkey-core:
    platform: linux/amd64
    image: mdriven/mdriven-turnkey:ubuntu-amd64
    
    volumes:
      - type: volume
        source: MDTData
        target: /app

      - type: bind
        source: ${PROJECT_ROOT:-.}/settings/mdriven-turnkey/CommandLineOverride.xml
        target: /app/App_Data/CommandLineOverride.xml
      
      - type: bind
        source: ${PROJECT_ROOT:-.}/settings/mdriven-turnkey/HardServerUrl.xml
        target: /app/App_Data/HardServerUrl.xml
      
      - type: bind
        source: ${PROJECT_ROOT:-.}/settings/mdriven-turnkey/MDrivenServerOverride.xml
        target: /app/App_Data/MDrivenServerOverride.xml
      
      - type: bind
        source: ${PROJECT_ROOT:-.}/settings/mdriven-turnkey/TurnkeySettingsOverride.xml
        target: /app/App_Data/TurnkeySettingsOverride.xml
    
    depends_on:
      server-core:
        condition: service_healthy
        restart: true

    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5012/"]
      interval: 10s
      timeout: 10s
      retries: 5
      start_period: 30s
    
    environment:
      - PUID=1000
      - PGID=1000
      # - UPDATE_APP=true # set true for latest version or yyyymmdd for specific version

    restart: on-failure:5

    entrypoint: ["/bin/sh","/usr/local/bin/entrypoint.sh"]

    command: ["dotnet", "StreaminAppCoreWebApp.dll"]
  
  scm:
    image: lscr.io/linuxserver/code-server:4.109.2-ls317

    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
      - PASSWORD=123456
      - DEFAULT_WORKSPACE=/config/workspace
      - PWA_APPNAME=mdriven-server
      - PORT=8080
    
    volumes:
      - type: volume
        source: MDSData
        target: /config/workspace/MDrivenServer
        read_only: false

      - type: volume
        source: MDTData
        target: /config/workspace/MDrivenTurnkey
        read_only: false
      
      ## Uncomment for stricter file manager and terminal permissions
      # - type: bind
      #   source: ${PROJECT_ROOT:-.}/settings/vscode/.config
      #   target: /config/.config
      #   read_only: true
      
      # - type: bind
      #   source: ${PROJECT_ROOT:-.}/settings/vscode/data/User/settings.json
      #   target: /config/data/User/settings.json
      #   read_only: true

      # - type: bind
      #   source: ${PROJECT_ROOT:-.}/settings/vscode/extensions/extensions.json
      #   target: /config/extensions/extensions.json
      #   read_only: true
    
  nginx:
    image: nginx:alpine
    
    volumes:
      - type: bind
        source: ${PROJECT_ROOT:-.}/settings/nginx-proxy.conf
        target: /etc/nginx/conf.d/default.conf

    depends_on:
      scm:
        condition: service_started
      turnkey-core:
        condition: service_healthy
        restart: true
    
    ports:
      - 5011:5011
      - 5012:5012
      - 8080:8080

volumes:
  MDSData:
  MDTData:

4. Key Advanced Features

Dependency Chains & Health Checks

The depends_on clauses in this file use condition: service_healthy. This is a crucial safety measure. It ensures that Turnkey won't even attempt to boot until the MDriven Server responds successfully to a curl request, and the Server won't boot until MySQL successfully executes a ping command.

Dynamic Paths

The file heavily utilizes the ${PROJECT_ROOT:-.} variable. This ensures that the mounts will correctly map to the current directory (.)

Configuration Settings

You can easily customize your production setup—such as updating the app versions, lowering container permissions, or resetting the administrator password—by adjusting environment variables and bindings within your compose.yaml file.

Please refer to the Docker Compose Configuration Settings section on the Docker Overview Page for detailed instructions on using UPDATE_APP, PUID/PGID, and the PwdReset.txt file.

5. How To Run The Setup

Once your file structure is correctly populated, simply open your terminal, navigate to your /Apps folder, and run:

docker compose up -d

Because of the robust dependency chaining, you can expect the containers to start in strict order: MySQL -> Server -> Turnkey/SCM -> Nginx.

  • To manage files and view app logs: Navigate to http://localhost:8080 (password: 123456) to access the web-based VS Code environment, where you can browse application files and review live logs in the integrated terminal/workspace.

6. Behind the Scenes: The Dockerfiles

For users looking to deeply customize their containers, here is a look at the actual source Dockerfiles used to generate the official MDriven images referenced in the compose.yaml above.

MDriven Server Dockerfile

This file uses an Ubuntu Noble base image and fetches the latest version of the Server Core dynamically via the MDriven Release API.

# syntax=docker/dockerfile:1
FROM [mcr.microsoft.com/dotnet/sdk:8.0-noble-amd64](https://mcr.microsoft.com/dotnet/sdk:8.0-noble-amd64)

RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        curl \
        unzip \
        jq \
    && rm -rf /var/lib/apt/lists/* WORKDIR /app

RUN mkdir -p /app_temp

RUN API_ENDPOINT="[https://mdriven.net/Rest/ProductRelease/Get?vProduct=ServerCore&platform=linux](https://mdriven.net/Rest/ProductRelease/Get?vProduct=ServerCore&platform=linux)" \
    && DOWNLOAD_URL=$(curl -sL "$API_ENDPOINT" | jq -r '.Releases[0]') \
    && curl -L -o release.zip "$DOWNLOAD_URL" \
    && unzip release.zip -d /app_temp \
    && rm release.zip

RUN dotnet nuget add source /mnt/c/capableobjectswush/Xternal/VistaDB --name XternatVistaDB 

COPY ./entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/entrypoint.sh

MDriven Turnkey Dockerfile

This file is similar but importantly includes locale generation which is required for correct Turnkey date and language formatting.

# syntax=docker/dockerfile:1
FROM [mcr.microsoft.com/dotnet/sdk:8.0-noble-amd64](https://mcr.microsoft.com/dotnet/sdk:8.0-noble-amd64)

RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        curl \
        unzip \
        jq \
        locales \
    && sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \
    && dpkg-reconfigure --frontend=noninteractive locales \
    && rm -rf /var/lib/apt/lists/* ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8

WORKDIR /app

RUN mkdir -p /app_temp

RUN API_ENDPOINT="[https://mdriven.net/Rest/ProductRelease/Get?vProduct=TurnkeyCore&platform=linux](https://mdriven.net/Rest/ProductRelease/Get?vProduct=TurnkeyCore&platform=linux)" \
    && DOWNLOAD_URL=$(curl -sL "$API_ENDPOINT" | jq -r '.Releases[0]') \
    && curl -L -o release.zip "$DOWNLOAD_URL" \
    && unzip release.zip -d /app_temp \
    && rm release.zip

COPY ./entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/entrypoint.sh


Theentrypoint.sh vs Standard Entry Points

You might notice that the standard entry points for MDriven applications are:

  • Server: dotnet AppCompleteGenericCore.dll
  • Turnkey: dotnet StreaminAppCoreWebApp.dll

However, the official MDriven setups utilize a custom script (COPY ./entrypoint.sh /usr/local/bin/) before launching those .dll files.

This entrypoint.sh file adds essential advanced features, including:

  1. Password Resets: The ability to dynamically reset User 'a's password via the mounted PwdReset.txt file.
  2. Version Control: Mechanisms for upgrading or downgrading MDriven Turnkey and Server using the UPDATE_APP environment variable.
  3. Security: Lowering application privileges using PUID and PGID to prevent the apps from running as root.

Recommendation: If you want these robust features, we highly recommend utilizing the standard Docker Compose setups provided by MDriven rather than writing custom .dll entry points from scratch!

See also: