Hey Grinders!
One common hurdle when developing games with Godot Engine for the web platform (HTML5 export) is testing the build locally. Simply opening the index.html
file directly in your browser using a file://
path often doesn’t work correctly, especially with Godot 4. This is because modern web browsers require specific security headers (Cross-Origin-Embedder-Policy
and Cross-Origin-Opener-Policy
) for features like SharedArrayBuffer
to work, which Godot often relies on for performance (especially with threads).
Without these headers, you might encounter errors or find that your game doesn’t load at all. The solution is to serve the files using a proper web server. While there are many ways to do this, we’ve found using Docker Compose and a minimal Nginx configuration to be a clean, repeatable, and efficient method.
Here’s how you can set it up:
Prerequisites
- Docker & Docker Compose: Ensure you have both installed on your system. You can get them from the official Docker website.
- Godot Web Export: You need to have exported your Godot project for the Web platform.
The Setup
We’ll use two files: a docker-compose.yml
file to define our Nginx service and a simple Nginx configuration file.
1. Directory Structure:
Organize your files like this:
your-project-root/ ├── export/ │ └── web/ <— Your Godot web build files go here (index.html, etc.) └── infra/ ├── docker-compose.yml └── nginx/ └── default.conf <— Our Nginx configuration
Important: Make sure your Godot web export target directory matches the path specified in the docker-compose.yml
volume mount (in this example, ../export/web
relative to the docker-compose.yml
file). Adjust the path if your structure differs.
2. docker-compose.yml
:
Create this file in your project root (or wherever makes sense for your workflow). Its content defines the Nginx service.
services:
godot_webuild_server:
image: nginx:latest
container_name: godot_webuild_server
ports:
- "9090:80"
restart: unless-stopped
volumes:
# NOTE: Change the `./../export/web` path to where ever your Godot Webbuild is exported to!
- ./../export/web:/usr/share/nginx/html:ro
- ./nginx:/etc/nginx/conf.d
image: nginx:latest
: Uses the official Nginx image from Docker Hub.ports: - "9090:80"
: Maps port9090
on your local machine (host) to port80
inside the Nginx container (where Nginx listens by default). You can change9090
if it conflicts with another service.volumes
:- The first volume mounts your Godot web build directory (
./../export/web
in this example) into the default Nginx web root (/usr/share/nginx/html
) inside the container. The:ro
makes it read-only, which is good practice. Remember to adjust the host path (./../export/web
) to point correctly to your exported files relative to wheredocker-compose.yml
lives. - The second volume mounts our custom Nginx configuration (
./nginx
folder) into the Nginx configuration directory (/etc/nginx/conf.d
).
- The first volume mounts your Godot web build directory (
3. Nginx Configuration (nginx/default.conf
):
Create a file named default.conf
(or any .conf
name) inside the nginx
folder. This file tells Nginx how to serve your game files and adds the necessary headers.
server {
listen 80;
server_name localhost;
add_header Cross-Origin-Embedder-Policy 'require-corp';
add_header Cross-Origin-Opener-Policy 'same-origin';
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ =404;
types {
application/wasm wasm;
text/html html;
application/javascript js;
text/css css;
}
}
}
listen 80
: Tells Nginx to listen on port 80 within the container (which we mapped to9090
on the host).add_header ...
: These two lines add the essentialCOEP
andCOOP
headers required by browsers for Godot 4 web exports to function correctly. This is the main reason we need a custom server setup.root /usr/share/nginx/html
: Sets the document root to the directory where we mounted our game files.try_files
: Standard Nginx directive for handling requests.types { ... }
: Explicitly defines MIME types, especially important for.wasm
files, ensuring the browser interprets them correctly.
Running Your Web Build Locally
- Export your Godot project to the
export/web
directory (or whichever directory you specified indocker-compose.yml
). - Open your terminal and navigate to the directory containing your
docker-compose.yml
file. - Run the server:
# The `-d` flag runs the container in detached mode (in the background).
docker compose up -d
- Open your web browser and go to:
http://localhost:9090
- Your Godot web build should now load and run correctly!
Stopping the Server
When you’re done testing, navigate back to the directory with docker-compose.yml
in your terminal and run:
docker compose down
This will stop and remove the container defined in the Compose file.
That’s it! With this simple Docker Compose and Nginx setup, you can easily spin up a local web server that correctly serves your Godot web exports with the necessary headers, making local testing much smoother. It keeps your main system clean and provides a consistent testing environment.
Happy developing!