Konteneryzacja Buildów Unity WebGL/WebGPU

Praca nad projektami Unity wspierającymi WebGL/WebGPU szybko staje się wyzwaniem, jeśli chodzi o stworzenie spójnego środowiska do rozwoju, testowania i produkcji.

Docker rozwiązuje ten problem, dostarczając lekkie, powtarzalne kontenery, które łączą Twój build Unity Web z całym niezbędnym środowiskiem uruchomieniowym. Programiści mogą uruchamiać identyczne środowisko na lokalnym komputerze, serwerze testowym lub w produkcji – zapewniając spójne działanie w całym pipeline. Dzięki Dockerowi testowanie staje się bardziej niezawodne, wdrożenia są uproszczone, a skalowanie sprowadza się do uruchamiania większej liczby kontenerów. Dodatkowo przejście z usług chmurowych na własne serwery jest tak proste, jak wdrożenie klastra Kubernetes.

W tym artykule pokażę, jak hostować buildy Unity WebGL/WebGPU wewnątrz kontenera Dockera opartego na Nginx.

Cały kod, konfiguracje i pliki Dockerfile są dostępne w repozytorium GitHub: https://github.com/AndreiMaksimovich/Unity-Web-Build-Dockerization

Konfiguracja Nginx

Domyślnie Nginx nie obsługuje poprawnie plików WebAssembly (.wasm) skompresowanych za pomocą Brotli lub Gzip. Aby to naprawić, stworzymy własną konfigurację Nginx, która będzie potrafiła prawidłowo obsługiwać te pliki i dostarczać je do przeglądarki.

./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

Ten plik Dockerfile buduje obraz oparty na najnowszym wydaniu obrazu Nginx. Kopiuje zawartość folderu build do kontenera i wykorzystuje nasz własny szablon Nginx jako domyślną konfigurację witryny.

./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

Ten plik Docker Compose buduje obraz i kontener o nazwie unity_project_name z naszego pliku Dockerfile oraz mapuje wyjście kontenera na 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

Skrypty Pomocnicze

Uwaga: Skrypty zostały przygotowane dla macOS, ale powinny działać bez problemu również na Linuksie.

Run.sh

Skrypt przydatny do lokalnych testów – uruchamia kontener i automatycznie usuwa go po zatrzymaniu.

#!/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

Skrypt uruchamiający kontener.

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

Jak Używać

Wystarczy umieścić build Unity WebGL w folderze ./build, a następnie uruchomić dostarczone skrypty lub użyć Dockera ręcznie.

Co Dalej

To jest minimalny przykład, odpowiedni wyłącznie do celów testowych. W prawdziwym projekcie trzeba stworzyć własny pipeline CI/CD, aby:

  • Budować osobne obrazy dla testów, recenzji i produkcji, lub/i system do promocji obrazów.
  • Wdrożyć odpowiednie wersjonowanie obrazów.
  • Zautomatyzować publikowanie obrazów do repozytoriów kontenerów.
  • Zautomatyzować aktualizacje obrazów i kontenerów w klastrach Kubernetes, w tym ich bezpieczne opróżnianie z użytkowników (graceful user drainage).