# docker-drawio **Repository Path**: mirrors_jgraph/docker-drawio ## Basic Information - **Project Name**: docker-drawio - **Description**: Dockerized draw.io based on whichever is the most secure image at the time. - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: dev - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-08-09 - **Last Updated**: 2026-09-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README [![Build Status](https://github.com/jgraph/docker-drawio/workflows/Docker%20Image%20CI/badge.svg)](https://github.com/jgraph/docker-drawio/actions) ## Introduction [draw.io](https://github.com/jgraph/drawio) is a whiteboarding / diagramming software application. This project packages draw.io for Docker: * `jgraph/drawio`, a draw.io docker image that is always up-to-date with draw.io releases * a [docker-compose](docker-compose.yml) to run draw.io with the Google Drive, Microsoft OneDrive and GitLab integrations * a [docker-compose](nextcloud/) to run draw.io integrated within Nextcloud The separate export server image (`jgraph/export-server`) has reached end of life and is no longer built or configured by this project, see [Removed variables](#removed-variables). ## Description The Dockerfile builds from `tomcat:9.0-jdk11-temurin` (see ) **Note: Starting from version 16.5.3, alpine and debian images are no longer maintained. We changed to a single image that uses the tomcat image with the least security vulnerabilities.** Forked from [fjudith/draw.io](https://github.com/fjudith/docker-draw.io) ## Features * Based on Tomcat so it can be used directly or behind a reverse-proxy * Self-Signed certificate autogen * Let's encrypt certificate autogen * Support SSL Keystore mount to `/user/local/tomcat/.keystore` ## Quick Start Run the container. ```bash docker run -it --rm --name="draw" -p 8080:8080 -p 8443:8443 jgraph/drawio ``` Start a web browser session to or If you're running `Docker Toolbox` then start a web browser session to or > `?offline=1` is a security feature that disables support of cloud storage. ## Docker Compose [`docker-compose.yml`](docker-compose.yml) runs the same image and passes every `DRAWIO_*` variable listed under [Environment variables](#environment-variables) through from the environment, so the configuration lives in a `.env` file next to it: ``` DRAWIO_SERVER_URL=https://drawio.example.com/ DRAWIO_GITLAB_ID=... DRAWIO_GITLAB_SECRET=... DRAWIO_GITLAB_URL=https://gitlab.example.com ``` ```bash docker compose up -d ``` Variables you leave unset are passed through empty, which the image treats as unset. ### AWS ECS The compose file can be deployed to AWS ECS by following this [tutorial](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-cli-tutorial-ec2.html) (we recommend EC2 deployment). Change the port mapping to 80 and 443 in `docker-compose.yml` to support the standard HTTP and HTTPS ports, allow access to these ports in the security group inbound rules, and set `DRAWIO_SERVER_URL` to your public deployment URL. ## Running as a non-root user The image already runs as a dedicated non-root user by default — `tomcat` (UID `1001`, GID `999`) — so nothing needs to be configured just to avoid root. [Users have reported](https://github.com/jgraph/docker-drawio/issues/210) it working with [rootless] Podman, but we haven't tested ourselves. To run under a *different* UID (a compose `user:` override, Kubernetes `runAsUser`, or OpenShift's arbitrary UIDs), the user must carry the **root group (GID `0`)**. Configuration is applied at startup by rewriting files inside the container ([`main/docker-entrypoint.sh`](main/docker-entrypoint.sh)), and the image grants GID `0` owner-equivalent permissions on those paths, following the OpenShift image guidelines. Membership of group `0` grants no other privileges — it is not root. ```bash docker run -it --rm -p 8080:8080 --user 1234:0 jgraph/drawio ``` docker-compose — either set group `0` directly or keep your own GID and add it as a supplementary group: ```yaml services: drawio: image: jgraph/drawio user: "1234:1234" group_add: - "0" ``` Kubernetes: ```yaml securityContext: runAsNonRoot: true runAsUser: 1234 runAsGroup: 0 # or keep your own runAsGroup and add supplementalGroups: [0] ``` On OpenShift, restricted SCCs already run pods with an arbitrary UID and GID `0`, so the image works there without any extra configuration. Without GID `0` the container still starts, but the entrypoint logs a warning and skips all runtime configuration (`DRAWIO_*` variables, SSL, context path). > `readOnlyRootFilesystem: true` is not currently supported, since configuration is written into the webapp at startup. ## Environment variables All container behaviour is controlled by environment variables, processed by [`main/docker-entrypoint.sh`](main/docker-entrypoint.sh) at startup and written into `PreConfig.js` / `PostConfig.js` inside the deployed webapp. ### Certificate and SSL | Variable | Default | Description | | ---------------------- | -------------------------- | -------------------------------------------------------- | | `LETS_ENCRYPT_ENABLED` | `false` | Enables Let's Encrypt certificate instead of self-signed | | `PUBLIC_DNS` | `draw.example.com` | DNS domain to be used as certificate "CN" record | | `ORGANISATION_UNIT` | `Cloud Native Application` | Organisation unit to be used as certificate "OU" record | | `ORGANISATION` | `example inc` | Organisation name to be used as certificate "O" record | | `CITY` | `Paris` | City name to be used as certificate "L" record | | `STATE` | `Paris` | State name to be used as certificate "ST" record | | `COUNTRY_CODE` | `FR` | Country code to be used as certificate "C" record | | `KEYSTORE_PASS` | `V3ry1nS3cur3P4ssw0rd` | `.keystore` / `.jks` store password | | `KEY_PASS` | same as `KEYSTORE_PASS` | Private key password | ### Deployment URL * **DRAWIO_SERVER_URL**: Public deployment URL **with a trailing slash**, e.g. `https://drawio.example.com/`, or `https://www.example.com/drawio/` if deployed into a sub-path. When a sub-path is present the entrypoint also updates the Tomcat context path automatically. Default unset (the webapp is served at `/`). * **DRAWIO_BASE_URL**: (Optional, backwards-compat) Same URL **without** a trailing slash, used by the viewer/lightbox/embed code paths. Only needed if `DRAWIO_SERVER_URL` is not set; the entrypoint derives whichever one is missing. If both are set, both pass through unchanged. * **DRAWIO_VIEWER_URL**: Optional URL of a hosted viewer JS bundle, e.g. `https://drawio.example.com/js/viewer.min.js`. * **DRAWIO_LIGHTBOX_URL**: Optional lightbox URL, e.g. `https://drawio.example.com`. * **DRAWIO_USE_HTTP**: (Optional and INSECURE) If your setup uses http only and you understand the risks (for example, sending OAuth tokens over http), set `DRAWIO_USE_HTTP=1`. **Caution: Use at your own risk**. ### Editor configuration * **DRAWIO_CONFIG**: JSON configuration object for the diagram editor — written verbatim into `window.DRAWIO_CONFIG`. See . Must be valid JSON, not arbitrary JavaScript, and must be the JSON itself, not the path of a file (see `DRAWIO_CONFIG_FILE`). The entrypoint logs a warning at startup when the value does not parse as JSON. In a compose file use the map syntax, `DRAWIO_CONFIG: '{"defaultFonts":["Helvetica"]}'` — with the list syntax (`- DRAWIO_CONFIG='{...}'`) the quotes become part of the value and the editor ignores it (the entrypoint strips a matching pair of single quotes and logs a notice). * **DRAWIO_CONFIG_FILE**: Path inside the container of a file holding that same JSON object, for a bind mount or a Kubernetes ConfigMap. Takes precedence over `DRAWIO_CONFIG` when both are set. For example: ```bash docker run -p 8080:8080 -v ./drawio-config.json:/config/drawio-config.json:ro -e DRAWIO_CONFIG_FILE=/config/drawio-config.json jgraph/drawio ``` * **DRAWIO_LANG**: Default language of the editor UI as a draw.io language code, e.g. `es`, `de` or `pt-br` (the codes behind the editor's *Language* menu). Used when the URL has no `lang` parameter and the user has not picked a language in the editor; both of those still win. Unset = browser language. There is no language key in `DRAWIO_CONFIG`. * **DRAWIO_CSP_HEADER**: Override the default Content-Security-Policy `` injected into the page. Defaults to a hard-coded policy in [`docker-entrypoint.sh`](main/docker-entrypoint.sh) — start from that policy when customising. * **ENABLE_DRAWIO_PROXY**: Set to `1` to enable the `/proxy` endpoint (ProxyServlet) which allows embedding images from external URLs; default disabled. **Enabling AI diagram generation:** the AI options (`enableAi`, `gptApiKey`, `geminiApiKey`, `claudeApiKey`, `aiModels`, `aiConfigs`, ...) are editor configuration settings, not standalone environment variables — there is no `DRAWIO_ENABLE_AI`. Set them inside `DRAWIO_CONFIG`, for example: ```bash DRAWIO_CONFIG={"enableAi":true,"claudeApiKey":"sk-ant-...","aiModels":[{"name":"Claude 4.5 Sonnet","model":"claude-sonnet-4-5","config":"claude"}]} ``` `enableAi` defaults to `true` only on app.diagrams.net, and the custom AI actions only appear once an API key and model are configured, so a self-hosted deployment needs both `enableAi: true` **and** a key. See [Customise LLM backends for diagram generation](https://www.drawio.com/doc/faq/configure-ai-options) for the full list of options. ### Custom fonts The editor renders text in the user's browser, which can only use fonts installed on the viewer's device or loaded over HTTP(S) — mounting font files into this container does **not** make them appear in the editor. Make a web font selectable in the font picker with `defaultFonts` (or `customFonts`, which prepends to the list) inside `DRAWIO_CONFIG`: ```bash DRAWIO_CONFIG={"defaultFonts":["Helvetica",{"fontFamily":"My Font","fontUrl":"https://drawio.example.com/fonts/MyFont.woff2"}]} ``` Plain string entries must be installed on every viewer's device; entries with `fontFamily` + `fontUrl` (a direct font file or a Google-Fonts-style CSS URL) are downloaded by the browser, and the URL is stored in the diagram so other viewers and exports can resolve it — use an absolute URL reachable from every browser that will open the diagram. To serve font files from this container, mount them into the webapp: `-v ./fonts:/usr/local/tomcat/webapps/draw/fonts` serves them at `https://your-host/fonts/…`. `fontCss` (also inside `DRAWIO_CONFIG`) injects raw `@font-face` rules; it makes text using that family render, but does **not** add anything to the font picker — combine it with a plain font name in `defaultFonts`/`customFonts`, or just use a `fontUrl` entry instead. The default CSP allows fonts from any origin (`font-src *`); if you override **DRAWIO_CSP_HEADER**, keep your font host allowed there. See the draw.io documentation on [external fonts](https://www.drawio.com/docs/manual/text/external-fonts/) for how fonts behave in the editor itself. ### Google Drive integration Create a project at the [Google API Console](https://console.developers.google.com/apis) and create [Credentials](https://console.developers.google.com/apis/credentials) of type "Create OAuth client ID" -> Web Application. This option is disabled until you create the "OAuth consent screen" from the link in the warning message bar; there, enter the "Application name" and "Authorized domains". In the "Create OAuth client ID" configuration, set "Authorized redirect URIs" to `[your-draw.io-hostname]/google` and "Authorized JavaScript origins" to your hostname. For example, if you host draw.io at `https://drawio.example.com`, the redirect URI is `https://drawio.example.com/google` and the JavaScript origin is `https://drawio.example.com`. * **DRAWIO_GOOGLE_CLIENT_ID**: OAuth client ID. Unset = Google Drive integration disabled. * **DRAWIO_GOOGLE_CLIENT_SECRET**: OAuth client secret. * **DRAWIO_GOOGLE_APP_ID**: Google project number (the numeric prefix of the client ID, before the first `-`). For example, if the client ID is `123456789-abc...`, the app ID is `123456789`. * **DRAWIO_GOOGLE_VIEWER_CLIENT_ID** / **DRAWIO_GOOGLE_VIEWER_CLIENT_SECRET** / **DRAWIO_GOOGLE_VIEWER_APP_ID**: Optional separate read-only credentials for a viewer deployment. If you also host a draw.io viewer, create another client ID for it; the viewer has read-only access to Drive files. ### Microsoft OneDrive integration Register an application to use the MS Graph APIs, see [how to register your app](https://docs.microsoft.com/en-us/graph/auth-register-app-v2) and [how to use the APIs](https://docs.microsoft.com/en-us/graph/use-the-api). In the Azure portal select the new app, then "Authentication", and add two redirect URIs: `[your-draw.io-hostname]/microsoft` and `[your-draw.io-hostname]/onedrive3.html`. For example, if you host draw.io at `https://drawio.example.com`, the redirect URIs are `https://drawio.example.com/microsoft` and `https://drawio.example.com/onedrive3.html`. In "Advanced settings" on the same page, enable the "Access tokens" and "ID tokens" check boxes. Create the client secret under "Certificates & secrets" ("+ New client secret"); the "Application (client) ID" is on the "Overview" page. * **DRAWIO_MSGRAPH_CLIENT_ID**: Azure app client ID. Unset = OneDrive integration disabled. * **DRAWIO_MSGRAPH_CLIENT_SECRET**: Azure app client secret. * **DRAWIO_MSGRAPH_TENANT_ID**: Tenant ID for single-tenant Azure apps. ### GitLab integration Create a new OAuth app in GitLab (Settings -> Applications). Set the "Redirect URI" to `[your-draw.io-hostname]/gitlab`, e.g. `https://drawio.example.com/gitlab`, and the "Scopes" to `api`, `read_repository` and `write_repository`. * **DRAWIO_GITLAB_ID**: OAuth application ID. Unset = GitLab integration disabled. * **DRAWIO_GITLAB_SECRET**: OAuth application secret. * **DRAWIO_GITLAB_URL**: GitLab base URL **without** any path, e.g. `https://gitlab.com` or `https://gitlab.example.com`. The entrypoint appends `/oauth/token` itself for server-side auth, and uses this value as the base of the client-side `/oauth/authorize` URL — adding a path here breaks both. When this is set to anything other than `https://gitlab.com` the entrypoint also writes `Editor.enableCustomGitLabUrl = true;` into `PostConfig.js`, which is required by the client to allow self-hosted instances; without it the OAuth flow fails with an "access denied" dialog before any request is made. ### Removed variables * **EXPORT_URL** and **DRAWIO_SELF_CONTAINED** no longer have any effect. They pointed the editor at the separate `jgraph/export-server` image, which has reached end of life and is no longer built from this repository. The entrypoint writes `window.EXPORT_URL = null` into `PreConfig.js` instead, which tells the editor that no export service exists: *Export as > PDF* uses the browser's print dialog (so the *Include a copy of my diagram* option is not offered for PDF) and the server-rendered PNG/JPEG export is hidden. PNG, JPEG and SVG export rendered in the browser are unaffected. ## HTTPS SSL Certificate via Let's Encrypt ### Prerequisites: 1. A Linux machine connected to the Internet with ports 443 and 80 open 1. A domain/subdomain name pointing to this machine's IP address. (e.g., drawio.example.com) ### Method: 1. Create a directory to store the letsencrypt data. (e.g., /opt/docker/drawiodata/letsencrypt-log, /opt/docker/drawiodata/letsencrypt-etc, /opt/docker/drawiodata/letsencrypt-lib) 2. Using jgraph/drawio docker image, run the following command ```bash docker run -it -m1g -v "/opt/docker/drawiodata/letsencrypt-log:/var/log/letsencrypt/" -v "/opt/docker/drawiodata/letsencrypt-etc:/etc/letsencrypt/" -v "/opt/docker/drawiodata/letsencrypt-lib:/var/lib/letsencrypt" -e LETS_ENCRYPT_ENABLED=true -e PUBLIC_DNS=drawio.example.com --rm --name="draw" -p 80:80 -p 443:8443 jgraph/drawio ``` Notice that mapping port 80 to container's port 80 allows certbot to work in stand-alone mode. Mapping port 443 to container's port 8443 allows the container tomcat to serve https requests directly. ## Reference *