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.