diff options
| -rw-r--r-- | .github/workflows/create_release.yml | 56 | ||||
| -rw-r--r-- | .github/workflows/validate.yml | 45 | ||||
| -rw-r--r-- | CHANGELOG.md | 1 | ||||
| -rw-r--r-- | docker/Dockerfile | 55 | ||||
| -rw-r--r-- | docker/empty/.gitkeep | 0 | ||||
| -rw-r--r-- | scripts/docker.lua | 88 | ||||
| -rw-r--r-- | xmake.lua | 17 |
7 files changed, 262 insertions, 0 deletions
diff --git a/.github/workflows/create_release.yml b/.github/workflows/create_release.yml index 3345573c0..6d6a15bfc 100644 --- a/.github/workflows/create_release.yml +++ b/.github/workflows/create_release.yml @@ -127,6 +127,62 @@ jobs: name: zenserver-macos path: build/zenserver-macos.zip + docker-build: + name: Build Docker Images + runs-on: [linux, x64, zen] + timeout-minutes: 15 + needs: [bundle-linux, bundle-windows] + + steps: + - uses: actions/checkout@v4 + + - name: Read VERSION.txt + id: read_version + uses: ue-foundation/[email protected] + with: + path: "./VERSION.txt" + + - name: Download Linux bundle + uses: actions/download-artifact@v1 + with: + name: zenserver-linux + path: artifacts/linux + + - name: Download Windows bundle + uses: actions/download-artifact@v1 + with: + name: zenserver-win64 + path: artifacts/win64 + + - name: Extract binaries + run: | + mkdir -p build/linux/x86_64/release + unzip artifacts/linux/zenserver-linux.zip -d artifacts/linux-extracted + cp artifacts/linux-extracted/zenserver build/linux/x86_64/release/ + mkdir -p build/win-binary-staging + unzip artifacts/win64/zenserver-win64.zip -d artifacts/win-extracted + cp artifacts/win-extracted/zenserver.exe build/win-binary-staging/ + + - name: Build Docker image (with Wine + Windows binary) + run: | + docker build \ + -t zenserver-compute:${{ steps.read_version.outputs.content }} \ + --build-arg WIN_BINARY_DIR=build/win-binary-staging \ + -f docker/Dockerfile . + + - name: Build Docker image (Linux only, no Wine) + run: | + docker build \ + -t zenserver-compute-linux:${{ steps.read_version.outputs.content }} \ + --build-arg INSTALL_WINE=false \ + -f docker/Dockerfile . + + # TODO: Push images to container registry + # - name: Push images + # run: | + # docker push zenserver-compute:${{ steps.read_version.outputs.content }} + # docker push zenserver-compute-linux:${{ steps.read_version.outputs.content }} + create-release: runs-on: [linux, x64, zen] timeout-minutes: 5 diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index d96645ac9..dfdb9677d 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -247,3 +247,48 @@ jobs: with: name: zenserver-macos path: build/zenserver-macos.zip + + docker-build: + name: Build Docker Images + if: github.ref_name == 'main' + runs-on: [linux, x64, zen] + timeout-minutes: 15 + needs: [linux-build, windows-build] + + steps: + - uses: actions/checkout@v4 + + - name: Download Linux bundle + uses: actions/download-artifact@v1 + with: + name: zenserver-linux + path: artifacts/linux + + - name: Download Windows bundle + uses: actions/download-artifact@v1 + with: + name: zenserver-win64 + path: artifacts/win64 + + - name: Extract binaries + run: | + mkdir -p build/linux/x86_64/release + unzip artifacts/linux/zenserver-linux.zip -d artifacts/linux-extracted + cp artifacts/linux-extracted/zenserver build/linux/x86_64/release/ + mkdir -p build/win-binary-staging + unzip artifacts/win64/zenserver-win64.zip -d artifacts/win-extracted + cp artifacts/win-extracted/zenserver.exe build/win-binary-staging/ + + - name: Build Docker image (with Wine + Windows binary) + run: | + docker build \ + -t zenserver-compute:latest \ + --build-arg WIN_BINARY_DIR=build/win-binary-staging \ + -f docker/Dockerfile . + + - name: Build Docker image (Linux only, no Wine) + run: | + docker build \ + -t zenserver-compute-linux:latest \ + --build-arg INSTALL_WINE=false \ + -f docker/Dockerfile . diff --git a/CHANGELOG.md b/CHANGELOG.md index cd0f85c98..930b9938c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Feature: Added `zen down --all` flag to shut down all running zenserver instances - Feature: Added `xmake kill` task to terminate all running zenserver instances - Feature: Support `ZEN_MALLOC` environment variable for default allocator selection; default allocator switched to rpmalloc +- Feature: Added Dockerfile and extended GHA workflows to produce zenserver Docker images, primarily intended for compute nodes - Improvement: Added support for CoW block-cloning (used by build download) on Linux (tested with: btrfs/ XFS) - Improvement: Added full-file CoW copying on macOS (APFS) - Improvement: Updated asio to 1.38.0 diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 000000000..060042d85 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,55 @@ +# Copyright Epic Games, Inc. All Rights Reserved. +# +# Runtime image for zenserver compute workers. +# +# Build variants: +# With Wine (for running Windows worker executables via WineProcessRunner): +# docker build -t zenserver-compute -f docker/Dockerfile . +# +# Without Wine (Linux-only workers, smaller image): +# docker build -t zenserver-compute --build-arg INSTALL_WINE=false -f docker/Dockerfile . +# +# The build context must contain the pre-built Linux zenserver binary at: +# build/linux/x86_64/release/zenserver + +FROM ubuntu:24.04 + +# Avoid interactive prompts during package installation +ENV DEBIAN_FRONTEND=noninteractive + +# Set to "false" to skip Wine installation and produce a smaller image +ARG INSTALL_WINE=true + +# Install WineHQ (only when INSTALL_WINE=true) +# Enables i386 architecture required for Wine32 support +RUN if [ "$INSTALL_WINE" = "true" ]; then \ + dpkg --add-architecture i386 \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + ca-certificates \ + gnupg \ + wget \ + && wget -qO- https://dl.winehq.org/wine-builds/winehq.key \ + | gpg --dearmor -o /usr/share/keyrings/winehq-archive.key \ + && echo "deb [signed-by=/usr/share/keyrings/winehq-archive.key] https://dl.winehq.org/wine-builds/ubuntu/ noble main" \ + > /etc/apt/sources.list.d/winehq.list \ + && apt-get update \ + && apt-get install -y --no-install-recommends winehq-stable \ + && apt-get remove -y gnupg wget \ + && apt-get autoremove -y \ + && rm -rf /var/lib/apt/lists/* ; \ + fi + +# Copy the pre-built zenserver binary +COPY build/linux/x86_64/release/zenserver /opt/zenserver/zenserver +RUN chmod +x /opt/zenserver/zenserver + +# Optional: Windows zenserver binary for Wine-based compute workers. +# Set WIN_BINARY_DIR to a directory containing zenserver.exe to include it. +# Defaults to docker/empty (an empty placeholder) so the COPY is a no-op. +ARG WIN_BINARY_DIR=docker/empty +COPY ${WIN_BINARY_DIR}/ /opt/zenserver/ + +EXPOSE 8558 + +ENTRYPOINT ["/opt/zenserver/zenserver"] diff --git a/docker/empty/.gitkeep b/docker/empty/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/docker/empty/.gitkeep diff --git a/scripts/docker.lua b/scripts/docker.lua new file mode 100644 index 000000000..f66f8db86 --- /dev/null +++ b/scripts/docker.lua @@ -0,0 +1,88 @@ +-- Copyright Epic Games, Inc. All Rights Reserved. + +import("core.base.option") + +-------------------------------------------------------------------------------- +local function _get_version() + local version_file = path.join(os.projectdir(), "VERSION.txt") + local version = io.readfile(version_file) + if version then + version = version:trim() + end + if not version or version == "" then + raise("Failed to read version from VERSION.txt") + end + return version +end + +-------------------------------------------------------------------------------- +function main() + local registry = option.get("registry") + local tag = option.get("tag") + local push = option.get("push") + local no_wine = option.get("no-wine") + local win_binary = option.get("win-binary") + + if not tag then + tag = _get_version() + end + + local image_name = no_wine and "zenserver-compute-linux" or "zenserver-compute" + if registry then + image_name = registry .. "/" .. image_name + end + + local full_tag = image_name .. ":" .. tag + + -- Verify the zenserver binary exists + local binary_path = path.join(os.projectdir(), "build/linux/x86_64/release/zenserver") + if not os.isfile(binary_path) then + raise("zenserver binary not found at %s\nBuild it first with: xmake config -y -m release -a x64 && xmake build -y zenserver", binary_path) + end + + -- Stage Windows binary if provided + local win_staging_dir = nil + if win_binary then + if not os.isfile(win_binary) then + raise("Windows binary not found at %s", win_binary) + end + win_staging_dir = path.join(os.projectdir(), "build/win-binary-staging") + os.mkdir(win_staging_dir) + os.cp(win_binary, path.join(win_staging_dir, "zenserver.exe")) + print("-- Including Windows binary: %s", win_binary) + end + + -- Build the Docker image + local dockerfile = path.join(os.projectdir(), "docker/Dockerfile") + print("-- Building Docker image: %s", full_tag) + local args = {"build", "-t", full_tag, "-f", dockerfile} + if no_wine then + table.insert(args, "--build-arg") + table.insert(args, "INSTALL_WINE=false") + end + if win_staging_dir then + table.insert(args, "--build-arg") + table.insert(args, "WIN_BINARY_DIR=build/win-binary-staging") + end + table.insert(args, os.projectdir()) + local ret = os.execv("docker", args) + if ret > 0 then + raise("Docker build failed") + end + + -- Clean up staging directory + if win_staging_dir then + os.rmdir(win_staging_dir) + end + + print("-- Built image: %s", full_tag) + + if push then + print("-- Pushing image: %s", full_tag) + ret = os.execv("docker", {"push", full_tag}) + if ret > 0 then + raise("Docker push failed") + end + print("-- Pushed image: %s", full_tag) + end +end @@ -382,6 +382,23 @@ task("bundle") bundle() end) +task("docker") + set_menu { + usage = "xmake docker [--push] [--no-wine] [--win-binary PATH] [--tag TAG] [--registry REGISTRY]", + description = "Build Docker image for zenserver compute workers", + options = { + {nil, "push", "k", nil, "Push the image after building"}, + {nil, "no-wine", "k", nil, "Build without Wine (smaller image, Linux-only workers)"}, + {nil, "win-binary", "v", nil, "Path to Windows zenserver.exe to include in image"}, + {nil, "tag", "v", nil, "Override image tag (default: version from VERSION.txt)"}, + {nil, "registry", "v", nil, "Registry prefix (e.g. ghcr.io/epicgames)"}, + } + } + on_run(function () + import("scripts.docker") + docker() + end) + task("kill") set_menu { usage = "xmake kill", |