Containerizing Unity WebGL/WebGPU builds: Host Your Game with Docker and Nginx

When working with Unity projects supporting WebGL/WebGPU, setting up a consistent environment for development, testing, and production can quickly become a challenge.

Docker solves this problem by providing lightweight, reproducible containers that bundle your Unity Web build with everything it needs to run. Developers can spin up an identical environment on their local machine, a staging server, or in production – ensuring consistent behavior across the entire pipeline. With Docker, testing is more reliable, deployment is streamlined, and scaling becomes as simple as running more containers, and moving from a cloud provider to your own servers is as simple as deploying your Kubernetes cluster.

In this article, I’ll show you how to host Unity WebGL/WebGPU builds inside an Nginx-based Docker container, and using this example configurations you can adapt for your own projects.

All source code, configurations, and Dockerfiles are available in the GitHub repository: https://github.com/AndreiMaksimovich/Unity-Web-Build-Dockerization

Nginx Configuration

Out of the box, Nginx won’t correctly serve WebAssembly (.wasm) files that are compressed with Brotli or Gzip. To fix this, we’ll create a custom Nginx configuration that knows how to handle these files and deliver them to the browser properly.

./nginx/default.conf.template

server {
    listen       ${NGINX_PORT};
    listen  [::]:${NGINX_PORT};
    server_name  localhost;
    
    access_log  off;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;

        add_header Access-Control-Allow-Origin *;

        location ~  \.br$ {
            gzip off;
            add_header Content-Encoding br;
            location ~ .+\.(data|symbols\.json)\.br$ { default_type application/octet-stream; }
            location ~ \.wasm\.br$ { default_type application/wasm; }
            location ~ \.js\.br$ { default_type application/javascript; }
        }

        location ~  \.gz$ {
            gzip off;
            add_header Content-Encoding gzip;
            location ~ .+\.(data|symbols\.json)\.gz$ { default_type application/octet-stream; }
            location ~ \.wasm\.gz$ { default_type application/wasm; }
            location ~ \.js\.gz$ { default_type application/javascript; }
        }

    }
}

Docker File

This Dockerfile builds an image based on the latest Nginx image release. It copies the contents of the build folder into the container and uses our custom Nginx template as the default site configuration.

./Dockerfile

FROM nginx:latest

COPY ./build /usr/share/nginx/html

RUN chown -R nginx:nginx /usr/share/nginx/html

COPY ./nginx/default.conf.template /etc/nginx/templates/default.conf.template

DockerCompose File

This Docker Compose file builds an image and container named unity_project_name from our Dockerfile, and maps the container’s output to port 80.

./DockerCompose.yaml

services:
  unity-webgl-nginx:
    container_name: "unity_project_name"
    build:
      context: ./
      dockerfile: ./Dockerfile
    image: "unity_project_name"
    ports:
      - "80:80"
    environment:
      - NGINX_PORT=80

Helper Scripts

Note: The scripts are created for macOS, but they should run without issues on Linux.

./Run.sh

Script useful for local testing that runs the container and automatically removes it once it stops.

#!/bin/bash
cd "$(dirname "$0")"
set -eux
cleanup() {
    docker compose -f DockerCompose.yaml rm -fsv
}
trap cleanup EXIT
docker compose -f DockerCompose.yaml up –build

./Start.sh

Script that launches the container.

#!/bin/bash
cd "$(dirname "$0")"
docker compose -f DockerCompose.yaml up --build –detach

How to Use

Just place your Unity WebGL build into the ./build folder, then run the provided scripts or use Docker manually.

What Next

This is a minimal example, suitable for testing purposes only. In a real project, you would typically set up a CI/CD pipeline to:

  • Build separate images for testing, review, and production, or/and system for image promotion.
  • Implement proper image versioning.
  • Automate pushing images to container repositories.
  • Automate image and container updates in Kubernetes clusters, including graceful user drainage.