Running Foundry VTT with Docker

More fun with containers

I only recently came across Foundry VTT, and my quick look at it convinced me to try it further. This afternoon, I had it up and running in less than an hour, and you can too!


This assumes you have Docker installed and running, and are comfortable with some basic concepts. I also use traefik for basic routing/termination, but this is optional; it lets me access the service at a nicer looking URL like https://rpg.example.com, but it is accessible without. This also assumes you have access to the Foundry VTT software; if you don’t, go to the Patreon and get it already!

Basic Setup

All it takes to get Foundry VTT running are six simple steps:

  1. Create a new directory for Foundry on the host running Docker.
  2. Download the Dockerfile and docker-compose.yml
  3. Edit the Dockerfile and add the URL to the Foundry VTT zip file
    (NB if you already have the zip file, you can use a COPY statement as described in the Dockerfile)
  4. Create the directory for data persistence (if you are using a bind mount as described in docker-compose.yml) as ./foundryvtt-data
  5. run docker-compose build — this will create a minimal image with Node.js based on alpine, pull and extract the zip with the Foundry VTT software
  6. run docker-compose up — this will run the application in attached mode, you should see console lines like the following:
foundryvtt | FoundryVTT | 2020-04-10 09:56:27 | [info] Foundry Virtual Tabletop - Version 0.5.3
foundryvtt | FoundryVTT | 2020-04-10 09:56:27 | [info] Running on Node.js - Version 12.16.1
(...)
foundryvtt | FoundryVTT | 2020-04-10 09:56:27 | [warn] Software license requires signature.
foundryvtt | FoundryVTT | 2020-04-10 09:56:27 | [info] Requesting UPnP port forwarding to destination 30000
foundryvtt | FoundryVTT | 2020-04-10 09:56:28 | [info] Server started and listening on port 30000

And at this point you are good to go! Go to the docker host’s IP at port 30000 in your browser — if you are running locally this would be http://localhost:30000 — and you should see the Foundry VTT license page:

If instead you get the following odd errors in the console:

foundryvtt | (node:1) UnhandledPromiseRejectionWarning: TypeError: Cannot destructure property 'app' of '_0x1b0815' as it is undefined.
foundryvtt | at initialize (/home/foundry/app/resources/app/dist/init.js:1:3804)
foundryvtt | at Object. (/home/foundry/app/resources/app/main.js:153:16)
foundryvtt | at Module._compile (internal/modules/cjs/loader.js:1158:30)
foundryvtt | at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10)
foundryvtt | at Module.load (internal/modules/cjs/loader.js:1002:32)
foundryvtt | at Function.Module._load (internal/modules/cjs/loader.js:901:14)
foundryvtt | at Function.executeUserEntryPoint as runMain
foundryvtt | at internal/main/run_main_module.js:18:47
foundryvtt | (node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch b
lock, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=st rict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
foundryvtt | (node:1) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the
Node.js process with a non-zero exit code.

That arises from not creating the persistence data directory or it having the wrong permissions. (Re) create it and make sure it is owned and read-writeable by UID 1000.

From here you are good to go!

Further Configuration

I have TLS configured in traefik, so by adding labels to the service in the docker-compose.yml file, I can access it via domain, rather host and port.

For example:

labels:
  - "traefik.enable=true"
  - "traefik.http.routers.foundryvtt.rule=Host(`rpg.example.com`) && PathPrefix(`/foundry`)"
  - "traefik.http.services.foundryvtt.loadbalancer.server.port=30000"
  - "traefik.http.routers.foundryvtt.tls=true"
  - "traefik.http.routers.foundryvtt.tls.certresolver=myresolver"

WordPress’ preformatted block looks garbage, so see this gist instead with explanatory lines.

Note that this example serves Foundry VTT from https://rpg.example.com/foundry , which requires editing the application’s options.json file and setting "routePrefix": "foundry" (note no slashes!). I also set "hostname": "rpg.exmaple.com" (not strictly needed) and "upnp": false (since ports managed by Docker).

The above labels also set a loadbalancer port for Traefik, since I do not have a ports mapping in my docker-compose.yml.

In my own case I’m tying together Foundry with the other RPG-related services I mentioned recently (Wekan and Bookstack), but this isn’t necessary. I can’t wait to actually use Foundry!

Tell us what's on your mind