From 7e178506d0fdef4152625aa601527b54d9e98f81 Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Tue, 9 Jun 2026 20:07:51 +0800 Subject: [PATCH 01/16] add selkies --- .github/workflows/build-docker.yml | 55 ++++++++++++--------- docker_casdoor/work/script-setup-casdoor.sh | 4 +- docker_gui/gui_linux.Dockerfile | 34 +++++++++++++ docker_gui/work/docker-entrypoint.sh | 26 ++++++++++ docker_gui/work/install_list_selkies.apt | 22 +++++++++ docker_gui/work/script-setup-gui.sh | 27 ++++++++++ 6 files changed, 144 insertions(+), 24 deletions(-) create mode 100644 docker_gui/gui_linux.Dockerfile create mode 100644 docker_gui/work/docker-entrypoint.sh create mode 100644 docker_gui/work/install_list_selkies.apt create mode 100644 docker_gui/work/script-setup-gui.sh diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml index fde4f6c..2b5f69b 100644 --- a/.github/workflows/build-docker.yml +++ b/.github/workflows/build-docker.yml @@ -29,29 +29,39 @@ env: jobs: ## Clash - docker_clash: + job-clash: name: "app-clash" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - run: | source ./tool.sh && build_image app-clash latest docker_clash/clash.Dockerfile && push_image clash + ## Selkies + job-gui-linux: + name: "gui-linux" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - run: | + source ./tool.sh && build_image gui-linux latest docker_gui/gui_linux.Dockerfile && push_image gui + + ## Casdoor - docker_casdoor: + job-casdoor: name: "casdoor" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - run: | source ./tool.sh && build_image casdoor latest docker_casdoor/casdoor.Dockerfile && push_image casdoor ## Keycloak - docker_keycloak: + job-keycloak: name: "keycloak" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - run: | source ./tool.sh && build_image keycloak latest docker_keycloak/keycloak.Dockerfile && push_image keycloak @@ -60,7 +70,7 @@ jobs: name: "dev-hub" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - run: | source ./tool.sh build_image dev-hub latest docker_devbox/hub.Dockerfile \ @@ -72,7 +82,7 @@ jobs: name: "dev-hub-traefik" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - run: | source ./tool.sh build_image dev-hub-traefik latest docker_devbox/hub.Dockerfile \ @@ -86,7 +96,7 @@ jobs: name: "openresty" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - run: | source ./tool.sh && build_image openresty latest docker_openresty/openresty.Dockerfile && push_image openresty @@ -95,7 +105,7 @@ jobs: name: "searxng" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - run: | source ./tool.sh && build_image searxng latest docker_searxng/searxng.Dockerfile && push_image searxng @@ -104,7 +114,7 @@ jobs: name: "storebox" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - run: | source ./tool.sh build_image storebox latest docker_storebox/storebox.Dockerfile && push_image storebox @@ -114,7 +124,7 @@ jobs: name: "logent" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - run: | source ./tool.sh build_image logent latest docker_logent/logent.Dockerfile && push_image logent @@ -124,7 +134,7 @@ jobs: name: "nocobase" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - run: | source ./tool.sh build_image nocobase latest docker_nocobase/nocobase.Dockerfile && push_image nocobase @@ -134,7 +144,7 @@ jobs: name: "openclaw" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - run: | source ./tool.sh build_image openclaw latest docker_openclaw/openclaw.Dockerfile && push_image openclaw @@ -144,7 +154,7 @@ jobs: name: "developer,base-dev" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - run: | source ./tool.sh && free_diskspace build_image base-dev latest docker_devbox/dev.Dockerfile \ @@ -158,7 +168,7 @@ jobs: name: "data-science-dev" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - run: | source ./tool.sh && free_diskspace build_image data-science-dev latest docker_devbox/dev.Dockerfile \ @@ -173,7 +183,7 @@ jobs: name: "full-stack-dev" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - run: | source ./tool.sh && free_diskspace build_image full-stack-dev latest docker_devbox/dev.Dockerfile \ @@ -188,7 +198,7 @@ jobs: name: "full-cuda,cuda-dev" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - run: | source ./tool.sh && free_diskspace build_image cuda-dev latest docker_devbox/dev.Dockerfile \ @@ -212,13 +222,14 @@ jobs: "job-searxng", "job-openresty", "job-dev-hub", - "docker_keycloak", - "docker_casdoor", - "docker_clash", + "job-keycloak", + "job-casdoor", + "job-clash", + "job-gui-linux" ] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - env: AUTH_FILE_CONTENT: ${{ secrets.AUTH_FILE_CONTENT }} DOCKER_MIRROR_REGISTRY: ${{ vars.DOCKER_MIRROR_REGISTRY }} diff --git a/docker_casdoor/work/script-setup-casdoor.sh b/docker_casdoor/work/script-setup-casdoor.sh index a9557c5..6c2dedc 100644 --- a/docker_casdoor/work/script-setup-casdoor.sh +++ b/docker_casdoor/work/script-setup-casdoor.sh @@ -13,8 +13,8 @@ setup_casdoor() { && mkdir -pv /opt/casdoor/web/build /opt/casdoor/conf echo "--> Building Backend..." \ - && cd /tmp/casdoor && echo "${VER_CASDOOR}" > /tmp/casdoor/version_info.txt \ - && CGO_ENABLED=0 GOOS=linux GOARCH=${ARCH} go build -ldflags="-w -s -X 'github.com/casdoor/casdoor/util.Version=${VER_CASDOOR}'" -o "server_linux_${ARCH}" . \ + && cd /tmp/casdoor && echo "v${VER_CASDOOR}" > /tmp/casdoor/version_info.txt \ + && CGO_ENABLED=0 GOOS=linux GOARCH=${ARCH} go build -ldflags="-w -s -X 'github.com/casdoor/casdoor/util.Version=v${VER_CASDOOR}'" -o "server_linux_${ARCH}" . \ && mv "./server_linux_${ARCH}" ./swagger ./docker-entrypoint.sh ./version_info.txt /opt/casdoor/ \ && cat ./conf/app.conf | sort > /opt/casdoor/conf/app.conf \ && ln -sf "/opt/casdoor/server_linux_${ARCH}" /opt/casdoor/server ; diff --git a/docker_gui/gui_linux.Dockerfile b/docker_gui/gui_linux.Dockerfile new file mode 100644 index 0000000..26d6421 --- /dev/null +++ b/docker_gui/gui_linux.Dockerfile @@ -0,0 +1,34 @@ +# Distributed under the terms of the Modified BSD License. + +ARG BASE_NAMESPACE +ARG BASE_IMG="node" + +FROM ${BASE_NAMESPACE:+$BASE_NAMESPACE/}${BASE_IMG} + +LABEL maintainer="postmaster@labnow.ai" + +COPY work /opt/utils/ + +RUN set -eux && source /opt/utils/script-utils.sh \ + && chmod +x /opt/utils/*.sh \ + ## ----------------------------- Install selkies + && source /opt/utils/script-setup-gui.sh && setup_selkies_dependencies && setup_selkies \ + && mv /opt/utils/docker-entrypoint.sh /opt/selkies/docker-entrypoint.sh \ + && rm -rf /opt/utils/entrypoint \ + && chmod +x /opt/selkies/docker-entrypoint.sh \ + ## Clean up and display components version information... + && list_installed_packages && install__clean + +ENV PATH=/opt/selkies:${PATH} + +EXPOSE 8080 +WORKDIR /opt/selkies + +# '-c' option make bash commands are read from string. +# If there are arguments after the string, they are assigned to the positional parameters, starting with $0. +# '-o pipefail' prevents errors in a pipeline from being masked. +# If any command in a pipeline fails, that return code will be used as the return code of the whole pipeline. +# '--login': make bash first reads and executes commands from the file /etc/profile, if that file exists. +# After that, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. +SHELL ["/bin/bash", "--login", "-o", "pipefail", "-c"] +ENTRYPOINT ["/opt/selkies/docker-entrypoint.sh"] diff --git a/docker_gui/work/docker-entrypoint.sh b/docker_gui/work/docker-entrypoint.sh new file mode 100644 index 0000000..09efe84 --- /dev/null +++ b/docker_gui/work/docker-entrypoint.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +set -euo pipefail + +export DISPLAY="${DISPLAY:-:99}" +export PIPEWIRE_LATENCY="${PIPEWIRE_LATENCY:-128/48000}" +export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/tmp}" +export PIPEWIRE_RUNTIME_DIR="${PIPEWIRE_RUNTIME_DIR:-${XDG_RUNTIME_DIR}}" +export PULSE_RUNTIME_PATH="${PULSE_RUNTIME_PATH:-${XDG_RUNTIME_DIR}/pulse}" +export PULSE_SERVER="${PULSE_SERVER:-unix:${PULSE_RUNTIME_PATH}/native}" + +if [ "$#" -eq 0 ]; then + set -- \ + --addr="${SELKIES_ADDR:-0.0.0.0}" \ + --port="${SELKIES_PORT:-8080}" \ + --enable_https="${SELKIES_ENABLE_HTTPS:-false}" \ + --https_cert="${SELKIES_HTTPS_CERT:-/etc/ssl/certs/ssl-cert-snakeoil.pem}" \ + --https_key="${SELKIES_HTTPS_KEY:-/etc/ssl/private/ssl-cert-snakeoil.key}" \ + --basic_auth_user="${SELKIES_BASIC_AUTH_USER:-user}" \ + --basic_auth_password="${SELKIES_BASIC_AUTH_PASSWORD:-mypasswd}" \ + --encoder="${SELKIES_ENCODER:-x264enc}" \ + --enable_resize="${SELKIES_ENABLE_RESIZE:-false}" +elif [[ "$1" != "-"* ]]; then + exec "$@" +fi + +exec /opt/selkies/selkies-gstreamer-run "$@" diff --git a/docker_gui/work/install_list_selkies.apt b/docker_gui/work/install_list_selkies.apt new file mode 100644 index 0000000..e58a8b6 --- /dev/null +++ b/docker_gui/work/install_list_selkies.apt @@ -0,0 +1,22 @@ +jq +tar +gzip +ca-certificates +curl +libpulse0 +wayland-protocols +libwayland-dev +libwayland-egl1 +x11-utils +x11-xkb-utils +x11-xserver-utils +xserver-xorg-core +libx11-xcb1 +libxcb-dri3-0 +libxkbcommon0 +libxdamage1 +libxfixes3 +libxv1 +libxtst6 +libxext6 +xvfb diff --git a/docker_gui/work/script-setup-gui.sh b/docker_gui/work/script-setup-gui.sh new file mode 100644 index 0000000..9839033 --- /dev/null +++ b/docker_gui/work/script-setup-gui.sh @@ -0,0 +1,27 @@ +source /opt/utils/script-utils.sh + +setup_selkies_dependencies() { + install_apt /opt/utils/install_list_selkies.apt ; +} + +setup_selkies() { + # ref: https://selkies-project.github.io/selkies/start/#quick-start + # ref: https://github.com/linuxserver/docker-baseimage-selkies/blob/master/Dockerfile + [ "$(dpkg --print-architecture)" = "amd64" ] || { + echo "Unsupported architecture for Selkies portable distribution: $(dpkg --print-architecture)" && return 1 ; + } + + VER_SELKIES="$(curl -fsSL "https://api.github.com/repos/selkies-project/selkies/releases/latest" | jq -r '.tag_name' | sed 's/[^0-9.\-]*//g')" \ + && URL_SELKIES="https://github.com/selkies-project/selkies/releases/download/v${VER_SELKIES}/selkies-gstreamer-portable-v${VER_SELKIES}_amd64.tar.gz" \ + && echo "Downloading Selkies-GStreamer ${VER_SELKIES} from: ${URL_SELKIES}" \ + && rm -rf /opt/selkies /tmp/selkies-install \ + && mkdir -pv /tmp/selkies-install \ + && curl -fsSL "${URL_SELKIES}" | tar -xzf - -C /tmp/selkies-install \ + && mv /tmp/selkies-install/selkies-gstreamer /opt/selkies \ + && chmod +x /opt/selkies/selkies-gstreamer* \ + && ln -sf /opt/selkies/selkies-gstreamer-run /usr/local/bin/selkies-gstreamer-run \ + && echo "${VER_SELKIES}" > /opt/selkies/version_info.txt \ + && rm -rf /tmp/selkies-install ; + + [ -x /opt/selkies/selkies-gstreamer-run ] && echo "@ Version of Selkies-GStreamer $(cat /opt/selkies/version_info.txt)" || return 1 ; +} From 889744f2db75bacaec381e2b6f82bcff75f419f8 Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Tue, 9 Jun 2026 20:42:47 +0800 Subject: [PATCH 02/16] update gui img --- .github/workflows/build-docker.yml | 4 +- docker_clash/README.md | 6 +- docker_clash/clash.Dockerfile | 2 +- docker_clash/demo/docker-compose.yml | 2 +- docker_gui/README.md | 94 +++++++++++++++++++ docker_gui/gui_linux.Dockerfile | 2 +- docker_gui/work/docker-entrypoint.sh | 14 ++- docker_gui/work/script-setup-gui.sh | 2 +- .../docker-compose.searxng-with-proxy.yml | 2 +- docker_searxng/demo/searxng/settings.yml | 4 +- 10 files changed, 118 insertions(+), 14 deletions(-) create mode 100644 docker_gui/README.md diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml index 2b5f69b..3fb2e10 100644 --- a/.github/workflows/build-docker.yml +++ b/.github/workflows/build-docker.yml @@ -30,12 +30,12 @@ env: jobs: ## Clash job-clash: - name: "app-clash" + name: "clash" runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - run: | - source ./tool.sh && build_image app-clash latest docker_clash/clash.Dockerfile && push_image clash + source ./tool.sh && build_image clash latest docker_clash/clash.Dockerfile && push_image clash ## Selkies job-gui-linux: diff --git a/docker_clash/README.md b/docker_clash/README.md index a69ddbf..9f27156 100644 --- a/docker_clash/README.md +++ b/docker_clash/README.md @@ -9,10 +9,10 @@ ```shell docker run -d \ - --name=app-clash \ + --name=svc-clash \ -p 7890:7890 -p 9090:9090 \ - -e PROXY_PROVIDER="https://subs.zeabur.app/clash" \ - labnow/app-clash + -e PROXY_PROVIDER="https://raw.githubusercontent.com/snakem982/proxypool/main/source/clash-meta.yaml" \ + labnow/clash ``` After the container starts, visit this page to manage proxy: http://localhost:9090/ui/ui-zashboard/ diff --git a/docker_clash/clash.Dockerfile b/docker_clash/clash.Dockerfile index 545f8fb..f71ebce 100644 --- a/docker_clash/clash.Dockerfile +++ b/docker_clash/clash.Dockerfile @@ -26,5 +26,5 @@ RUN set -eux \ && echo 'export PATH=${PATH}:/opt/clash' >> /etc/profile.d/path-clash.sh \ && ln -sf /opt/clash/clash /usr/local/bin/ -ENV PROXY_PROVIDER="https://subs.zeabur.app/clash" +ENV PROXY_PROVIDER="https://raw.githubusercontent.com/snakem982/proxypool/main/source/clash-meta.yaml" CMD ["/opt/clash/start-clash.sh"] diff --git a/docker_clash/demo/docker-compose.yml b/docker_clash/demo/docker-compose.yml index 014b7a8..10bd3f9 100644 --- a/docker_clash/demo/docker-compose.yml +++ b/docker_clash/demo/docker-compose.yml @@ -1,6 +1,6 @@ services: svc-clash: - image: docker.io/labnow/app-clash + image: docker.io/labnow/clash container_name: svc-clash hostname: svc-clash restart: unless-stopped diff --git a/docker_gui/README.md b/docker_gui/README.md new file mode 100644 index 0000000..83cdbd3 --- /dev/null +++ b/docker_gui/README.md @@ -0,0 +1,94 @@ +# docker_gui + +这个镜像用于打包 Selkies-GStreamer,把容器内的 Linux GUI 会话通过浏览器访问。 +镜像只负责 GUI 串流层,默认关闭 Selkies 内置 Basic Auth,认证和鉴权建议放在上游网关、反向代理或平台侧处理。 + +## 构建 + +```bash +docker build -f docker_gui/gui_linux.Dockerfile -t labnow/gui:selkies docker_gui +``` + +基础镜像假设满足以下条件: + +- 基于 Ubuntu。 +- 已包含 Node.js 最新 LTS。 +- 已包含 Python >= 3.13。 + +构建过程会安装 Selkies portable 版本所需的系统依赖,下载 Selkies 最新 release,并安装到 `/opt/selkies`。 + +## 启动 + +```bash +docker run --rm -p 8080:8080 labnow/gui:selkies +``` + +浏览器访问: + +```text +http://localhost:8080 +``` + +默认不需要输入用户名和密码。如果确实需要启用 Selkies 内置 Basic Auth,可以显式传入: + +```bash +docker run --rm -p 8080:8080 \ + -e SELKIES_ENABLE_BASIC_AUTH=true \ + -e SELKIES_BASIC_AUTH_USER=user \ + -e SELKIES_BASIC_AUTH_PASSWORD=mypasswd \ + labnow/gui:selkies +``` + +## 常用环境变量 + +| 变量 | 默认值 | 说明 | +| --- | --- | --- | +| `SELKIES_ADDR` | `0.0.0.0` | HTTP/WebSocket 监听地址。 | +| `SELKIES_PORT` | `8080` | HTTP/WebSocket 监听端口。 | +| `SELKIES_ENABLE_BASIC_AUTH` | `false` | 是否启用 Selkies 内置 Basic Auth。 | +| `SELKIES_BASIC_AUTH_USER` | 空 | Basic Auth 用户名。 | +| `SELKIES_BASIC_AUTH_PASSWORD` | 空 | Basic Auth 密码。 | +| `SELKIES_ENCODER` | `x264enc` | 视频编码器。 | +| `SELKIES_ENABLE_RESIZE` | `false` | 是否允许 Selkies 按浏览器窗口调整分辨率。 | +| `SELKIES_STUN_HOST` | `stun.l.google.com` | STUN 服务器地址。 | +| `SELKIES_STUN_PORT` | `19302` | STUN 服务器端口。 | +| `SELKIES_TURN_HOST` | 空 | TURN 服务器地址。Docker bridge、NAT 或代理场景通常需要配置。 | +| `SELKIES_TURN_PORT` | `3478` | TURN 服务器端口。 | +| `SELKIES_TURN_PROTOCOL` | `udp` | TURN 传输协议。 | +| `SELKIES_TURN_TLS` | `false` | TURN 是否启用 TLS。 | +| `SELKIES_TURN_USERNAME` | 空 | TURN 用户名。 | +| `SELKIES_TURN_PASSWORD` | 空 | TURN 密码。 | +| `SELKIES_TURN_SHARED_SECRET` | 空 | TURN shared secret,用于 HMAC 临时凭证。 | + +也可以直接传递 `selkies-gstreamer-run` 参数: + +```bash +docker run --rm -p 8080:8080 labnow/gui:selkies --encoder=vp8enc --enable_resize=true +``` + +## 关于 Connection failed + +`8080` 端口只承载 Web UI 和 signaling WebSocket。Selkies 的画面、音频、输入等媒体流走 WebRTC,WebRTC 会通过 ICE 协商额外的 UDP/TCP candidate。 + +因此,只做 `-p 8080:8080` 时,页面可以打开,但媒体流不一定能连通。如果浏览器提示 `Connection failed`,通常不是 HTTP 端口映射失败,而是 ICE/WebRTC 连接失败。 + +常见处理方式: + +- 本地 Linux 开发时,优先使用 `--network=host`,让浏览器能直接访问容器产生的 ICE candidate。 +- Docker bridge、跨主机、NAT、反向代理、只允许暴露一个 HTTP 端口的部署,建议配置外部 TURN 服务。 +- 如果不使用 TURN,需要额外开放 WebRTC 实际使用的 UDP/TCP 端口范围,并确保浏览器能路由到日志里的 candidate 地址。 + +外部 TURN 示例: + +```bash +docker run --rm -p 8080:8080 \ + -e SELKIES_TURN_HOST=turn.example.com \ + -e SELKIES_TURN_PORT=443 \ + -e SELKIES_TURN_PROTOCOL=tcp \ + -e SELKIES_TURN_TLS=true \ + -e SELKIES_TURN_USERNAME="$TURN_USERNAME" \ + -e SELKIES_TURN_PASSWORD="$TURN_PASSWORD" \ + labnow/gui:selkies +``` + +日志中出现 `Listening on http://0.0.0.0:8080` 表示 HTTP 服务已经启动。若随后反复出现 session 建立、ICE candidate 交换、peer cleanup,通常应优先检查 TURN、网络模式或 UDP/TCP candidate 可达性。 diff --git a/docker_gui/gui_linux.Dockerfile b/docker_gui/gui_linux.Dockerfile index 26d6421..826e5cb 100644 --- a/docker_gui/gui_linux.Dockerfile +++ b/docker_gui/gui_linux.Dockerfile @@ -14,7 +14,6 @@ RUN set -eux && source /opt/utils/script-utils.sh \ ## ----------------------------- Install selkies && source /opt/utils/script-setup-gui.sh && setup_selkies_dependencies && setup_selkies \ && mv /opt/utils/docker-entrypoint.sh /opt/selkies/docker-entrypoint.sh \ - && rm -rf /opt/utils/entrypoint \ && chmod +x /opt/selkies/docker-entrypoint.sh \ ## Clean up and display components version information... && list_installed_packages && install__clean @@ -32,3 +31,4 @@ WORKDIR /opt/selkies # After that, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. SHELL ["/bin/bash", "--login", "-o", "pipefail", "-c"] ENTRYPOINT ["/opt/selkies/docker-entrypoint.sh"] +CMD [] diff --git a/docker_gui/work/docker-entrypoint.sh b/docker_gui/work/docker-entrypoint.sh index 09efe84..ae9c89f 100644 --- a/docker_gui/work/docker-entrypoint.sh +++ b/docker_gui/work/docker-entrypoint.sh @@ -15,8 +15,18 @@ if [ "$#" -eq 0 ]; then --enable_https="${SELKIES_ENABLE_HTTPS:-false}" \ --https_cert="${SELKIES_HTTPS_CERT:-/etc/ssl/certs/ssl-cert-snakeoil.pem}" \ --https_key="${SELKIES_HTTPS_KEY:-/etc/ssl/private/ssl-cert-snakeoil.key}" \ - --basic_auth_user="${SELKIES_BASIC_AUTH_USER:-user}" \ - --basic_auth_password="${SELKIES_BASIC_AUTH_PASSWORD:-mypasswd}" \ + --enable_basic_auth="${SELKIES_ENABLE_BASIC_AUTH:-false}" \ + --basic_auth_user="${SELKIES_BASIC_AUTH_USER:-}" \ + --basic_auth_password="${SELKIES_BASIC_AUTH_PASSWORD:-}" \ + --stun_host="${SELKIES_STUN_HOST:-stun.l.google.com}" \ + --stun_port="${SELKIES_STUN_PORT:-19302}" \ + --turn_host="${SELKIES_TURN_HOST:-}" \ + --turn_port="${SELKIES_TURN_PORT:-3478}" \ + --turn_protocol="${SELKIES_TURN_PROTOCOL:-udp}" \ + --turn_tls="${SELKIES_TURN_TLS:-false}" \ + --turn_username="${SELKIES_TURN_USERNAME:-}" \ + --turn_password="${SELKIES_TURN_PASSWORD:-}" \ + --turn_shared_secret="${SELKIES_TURN_SHARED_SECRET:-}" \ --encoder="${SELKIES_ENCODER:-x264enc}" \ --enable_resize="${SELKIES_ENABLE_RESIZE:-false}" elif [[ "$1" != "-"* ]]; then diff --git a/docker_gui/work/script-setup-gui.sh b/docker_gui/work/script-setup-gui.sh index 9839033..4901300 100644 --- a/docker_gui/work/script-setup-gui.sh +++ b/docker_gui/work/script-setup-gui.sh @@ -21,7 +21,7 @@ setup_selkies() { && chmod +x /opt/selkies/selkies-gstreamer* \ && ln -sf /opt/selkies/selkies-gstreamer-run /usr/local/bin/selkies-gstreamer-run \ && echo "${VER_SELKIES}" > /opt/selkies/version_info.txt \ - && rm -rf /tmp/selkies-install ; + && rm -rf /tmp/selkies-install /opt/selkies/docs ; [ -x /opt/selkies/selkies-gstreamer-run ] && echo "@ Version of Selkies-GStreamer $(cat /opt/selkies/version_info.txt)" || return 1 ; } diff --git a/docker_searxng/demo/docker-compose.searxng-with-proxy.yml b/docker_searxng/demo/docker-compose.searxng-with-proxy.yml index ef04347..03814ea 100644 --- a/docker_searxng/demo/docker-compose.searxng-with-proxy.yml +++ b/docker_searxng/demo/docker-compose.searxng-with-proxy.yml @@ -33,7 +33,7 @@ services: max-file: "1" svc-clash: - image: docker.io/labnow/app-clash + image: docker.io/labnow/clash container_name: svc-clash hostname: svc-clash restart: unless-stopped diff --git a/docker_searxng/demo/searxng/settings.yml b/docker_searxng/demo/searxng/settings.yml index 3c42c58..f5033a8 100644 --- a/docker_searxng/demo/searxng/settings.yml +++ b/docker_searxng/demo/searxng/settings.yml @@ -34,5 +34,5 @@ engines: outgoing: proxies: all://: - # need to make sure the containers of app-clash and searxng can communicate with each other - - http://app-clash:7890 + # need to make sure the containers of svc-clash and searxng can communicate with each other + - http://svc-clash:7890 From ca81d55582505ab7051b43ca845fffd43ff684f8 Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Tue, 9 Jun 2026 20:58:18 +0800 Subject: [PATCH 03/16] update README --- docker_gui/README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docker_gui/README.md b/docker_gui/README.md index 83cdbd3..637badc 100644 --- a/docker_gui/README.md +++ b/docker_gui/README.md @@ -81,14 +81,16 @@ docker run --rm -p 8080:8080 labnow/gui:selkies --encoder=vp8enc --enable_resize 外部 TURN 示例: ```bash -docker run --rm -p 8080:8080 \ - -e SELKIES_TURN_HOST=turn.example.com \ - -e SELKIES_TURN_PORT=443 \ +docker run --rm -it -p 8080:8080 \ + quay.io/labnow0dev/gui-linux bash + +# optional env: -e SELKIES_TURN_PROTOCOL=tcp \ -e SELKIES_TURN_TLS=true \ + -e SELKIES_TURN_HOST=turn.example.com \ + -e SELKIES_TURN_PORT=443 \ -e SELKIES_TURN_USERNAME="$TURN_USERNAME" \ -e SELKIES_TURN_PASSWORD="$TURN_PASSWORD" \ - labnow/gui:selkies ``` 日志中出现 `Listening on http://0.0.0.0:8080` 表示 HTTP 服务已经启动。若随后反复出现 session 建立、ICE candidate 交换、peer cleanup,通常应优先检查 TURN、网络模式或 UDP/TCP candidate 可达性。 From 96ccfc865b6c26008477d5eac28285d9c2ed3919 Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Tue, 9 Jun 2026 21:30:13 +0800 Subject: [PATCH 04/16] debug selkies src install --- docker_gui/README.md | 11 ++- docker_gui/gui_linux.Dockerfile | 11 ++- docker_gui/work/docker-entrypoint.sh | 1 + docker_gui/work/install_list_selkies.apt | 12 +++ .../work/install_list_selkies_build.apt | 9 ++ docker_gui/work/script-setup-gui.sh | 97 ++++++++++++++++++- 6 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 docker_gui/work/install_list_selkies_build.apt diff --git a/docker_gui/README.md b/docker_gui/README.md index 637badc..394ea54 100644 --- a/docker_gui/README.md +++ b/docker_gui/README.md @@ -15,7 +15,16 @@ docker build -f docker_gui/gui_linux.Dockerfile -t labnow/gui:selkies docker_gui - 已包含 Node.js 最新 LTS。 - 已包含 Python >= 3.13。 -构建过程会安装 Selkies portable 版本所需的系统依赖,下载 Selkies 最新 release,并安装到 `/opt/selkies`。 +构建过程会安装 Selkies 运行期系统依赖,克隆 Selkies 最新 release 对应的源码,并安装到 `/opt/selkies`。 +默认使用源码构建方式,只保留运行期需要的 Python venv、web dashboard 产物和少量 addon 产物,构建依赖会在同一层内清理。 + +如需回退到官方 portable release 包,可以使用: + +```bash +docker build -f docker_gui/gui_linux.Dockerfile \ + --build-arg ARG_SELKIES_INSTALL_METHOD=release \ + -t labnow/gui:selkies-release docker_gui +``` ## 启动 diff --git a/docker_gui/gui_linux.Dockerfile b/docker_gui/gui_linux.Dockerfile index 826e5cb..86e47ee 100644 --- a/docker_gui/gui_linux.Dockerfile +++ b/docker_gui/gui_linux.Dockerfile @@ -2,9 +2,12 @@ ARG BASE_NAMESPACE ARG BASE_IMG="node" +ARG ARG_SELKIES_INSTALL_METHOD=source FROM ${BASE_NAMESPACE:+$BASE_NAMESPACE/}${BASE_IMG} +ARG ARG_SELKIES_INSTALL_METHOD=source + LABEL maintainer="postmaster@labnow.ai" COPY work /opt/utils/ @@ -12,7 +15,13 @@ COPY work /opt/utils/ RUN set -eux && source /opt/utils/script-utils.sh \ && chmod +x /opt/utils/*.sh \ ## ----------------------------- Install selkies - && source /opt/utils/script-setup-gui.sh && setup_selkies_dependencies && setup_selkies \ + && source /opt/utils/script-setup-gui.sh \ + && setup_selkies_dependencies \ + && if [ "${ARG_SELKIES_INSTALL_METHOD}" = "release" ] ; then \ + setup_selkies_from_release ; \ + else \ + setup_selkies_build_dependencies && setup_selkies_from_source ; \ + fi \ && mv /opt/utils/docker-entrypoint.sh /opt/selkies/docker-entrypoint.sh \ && chmod +x /opt/selkies/docker-entrypoint.sh \ ## Clean up and display components version information... diff --git a/docker_gui/work/docker-entrypoint.sh b/docker_gui/work/docker-entrypoint.sh index ae9c89f..d976a03 100644 --- a/docker_gui/work/docker-entrypoint.sh +++ b/docker_gui/work/docker-entrypoint.sh @@ -12,6 +12,7 @@ if [ "$#" -eq 0 ]; then set -- \ --addr="${SELKIES_ADDR:-0.0.0.0}" \ --port="${SELKIES_PORT:-8080}" \ + --web_root="${SELKIES_WEB_ROOT:-/opt/selkies/share/selkies-web}" \ --enable_https="${SELKIES_ENABLE_HTTPS:-false}" \ --https_cert="${SELKIES_HTTPS_CERT:-/etc/ssl/certs/ssl-cert-snakeoil.pem}" \ --https_key="${SELKIES_HTTPS_KEY:-/etc/ssl/private/ssl-cert-snakeoil.key}" \ diff --git a/docker_gui/work/install_list_selkies.apt b/docker_gui/work/install_list_selkies.apt index e58a8b6..d03dd8f 100644 --- a/docker_gui/work/install_list_selkies.apt +++ b/docker_gui/work/install_list_selkies.apt @@ -3,7 +3,19 @@ tar gzip ca-certificates curl +gstreamer1.0-alsa +gstreamer1.0-gl +gstreamer1.0-libav +gstreamer1.0-plugins-bad +gstreamer1.0-plugins-base +gstreamer1.0-plugins-good +gstreamer1.0-plugins-ugly +gstreamer1.0-pulseaudio +gstreamer1.0-tools +gstreamer1.0-x libpulse0 +python3-gi +python3-gst-1.0 wayland-protocols libwayland-dev libwayland-egl1 diff --git a/docker_gui/work/install_list_selkies_build.apt b/docker_gui/work/install_list_selkies_build.apt new file mode 100644 index 0000000..01fc676 --- /dev/null +++ b/docker_gui/work/install_list_selkies_build.apt @@ -0,0 +1,9 @@ +build-essential +cmake +g++ +gcc +git +make +pkg-config +python3-dev +python3-venv diff --git a/docker_gui/work/script-setup-gui.sh b/docker_gui/work/script-setup-gui.sh index 4901300..d2a18b6 100644 --- a/docker_gui/work/script-setup-gui.sh +++ b/docker_gui/work/script-setup-gui.sh @@ -4,7 +4,11 @@ setup_selkies_dependencies() { install_apt /opt/utils/install_list_selkies.apt ; } -setup_selkies() { +setup_selkies_build_dependencies() { + install_apt /opt/utils/install_list_selkies_build.apt ; +} + +setup_selkies_from_release() { # ref: https://selkies-project.github.io/selkies/start/#quick-start # ref: https://github.com/linuxserver/docker-baseimage-selkies/blob/master/Dockerfile [ "$(dpkg --print-architecture)" = "amd64" ] || { @@ -25,3 +29,94 @@ setup_selkies() { [ -x /opt/selkies/selkies-gstreamer-run ] && echo "@ Version of Selkies-GStreamer $(cat /opt/selkies/version_info.txt)" || return 1 ; } + +setup_selkies_web_from_source() { + local src_dir="${1:-/tmp/selkies-src}" + local web_dir="${2:-/opt/selkies/share/selkies-web}" + + echo "--> Building Selkies web dashboard..." \ + && cd "${src_dir}/addons/selkies-web-core" \ + && npm install \ + && npm run build \ + && cd "${src_dir}/addons/selkies-dashboard" \ + && cp ../selkies-web-core/dist/selkies-core.js src/ \ + && npm install \ + && npm run build \ + && mkdir -pv "${web_dir}/src" "${web_dir}/nginx" \ + && cp -arf dist/* "${web_dir}/" \ + && cp -f ../selkies-web-core/dist/selkies-core.js "${web_dir}/src/" \ + && cp -f ../universal-touch-gamepad/universalTouchGamepad.js "${web_dir}/src/" \ + && cp -arf ../selkies-web-core/dist/jsdb "${web_dir}/" \ + && cp -arf ../selkies-web-core/nginx/* "${web_dir}/nginx/" \ + && rm -rf "${src_dir}"/addons/*/node_modules /root/.npm /tmp/npm-* ; +} + +setup_selkies_python_from_source() { + local src_dir="${1:-/tmp/selkies-src}" + + echo "--> Installing Selkies Python package..." \ + && python3 -m venv --system-site-packages /opt/selkies/venv \ + && /opt/selkies/venv/bin/pip install --no-cache-dir --upgrade pip setuptools wheel \ + && /opt/selkies/venv/bin/pip install --no-cache-dir "${src_dir}" ; +} + +setup_selkies_addons_from_source() { + local src_dir="${1:-/tmp/selkies-src}" + + if [ -f "${src_dir}/addons/js-interposer/joystick_interposer.c" ]; then + echo "--> Building Selkies joystick interposer..." \ + && gcc -shared -fPIC -ldl -o /usr/lib/selkies_joystick_interposer.so \ + "${src_dir}/addons/js-interposer/joystick_interposer.c" ; + fi + + if [ -f "${src_dir}/addons/fake-udev/Makefile" ]; then + echo "--> Building Selkies fake udev..." \ + && make -C "${src_dir}/addons/fake-udev" \ + && mkdir -pv /opt/lib \ + && mv "${src_dir}/addons/fake-udev/libudev.so.1.0.0-fake" /opt/lib/ ; + fi +} + +setup_selkies_runtime_wrapper() { + cat > /opt/selkies/selkies-gstreamer-run <<'EOF' +#!/usr/bin/env bash +set -euo pipefail +if [ -x /opt/selkies/venv/bin/selkies-gstreamer ]; then + exec /opt/selkies/venv/bin/selkies-gstreamer "$@" +fi +exec /opt/selkies/venv/bin/selkies "$@" +EOF + chmod +x /opt/selkies/selkies-gstreamer-run \ + && ln -sf /opt/selkies/selkies-gstreamer-run /usr/local/bin/selkies-gstreamer-run ; +} + +cleanup_selkies_build_dependencies() { + apt-get purge -y --auto-remove \ + build-essential cmake g++ gcc git make pkg-config python3-dev \ + python3-venv \ + && rm -rf /tmp/selkies-src /root/.cache /root/.npm /var/tmp/* ; +} + +setup_selkies_from_source() { + # ref: https://github.com/linuxserver/docker-baseimage-selkies/blob/master/Dockerfile + local tag="${VER_SELKIES:-}" + local src_dir="/tmp/selkies-src" + + [ -n "${tag}" ] || tag="$(curl -fsSL "https://api.github.com/repos/selkies-project/selkies/releases/latest" | jq -r '.tag_name')" \ + && echo "Cloning Selkies source at ${tag}" \ + && rm -rf /opt/selkies "${src_dir}" \ + && mkdir -pv /opt/selkies/share \ + && git clone --depth 1 --branch "${tag}" https://github.com/selkies-project/selkies.git "${src_dir}" \ + && setup_selkies_web_from_source "${src_dir}" /opt/selkies/share/selkies-web \ + && setup_selkies_python_from_source "${src_dir}" \ + && setup_selkies_addons_from_source "${src_dir}" \ + && setup_selkies_runtime_wrapper \ + && echo "${tag}" > /opt/selkies/version_info.txt \ + && cleanup_selkies_build_dependencies ; + + [ -x /opt/selkies/selkies-gstreamer-run ] && echo "@ Version of Selkies-GStreamer $(cat /opt/selkies/version_info.txt)" || return 1 ; +} + +setup_selkies() { + setup_selkies_from_source ; +} From 6443730ce633ddaa090e1998d103dba5d8a1ff23 Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Tue, 9 Jun 2026 21:45:20 +0800 Subject: [PATCH 05/16] debug build --- docker_gui/README.md | 10 ++++++- docker_gui/gui_linux.Dockerfile | 3 ++ .../work/install_list_selkies_build.apt | 9 ------ docker_gui/work/script-setup-gui.sh | 30 ++++++++++++------- 4 files changed, 32 insertions(+), 20 deletions(-) delete mode 100644 docker_gui/work/install_list_selkies_build.apt diff --git a/docker_gui/README.md b/docker_gui/README.md index 394ea54..bd7322e 100644 --- a/docker_gui/README.md +++ b/docker_gui/README.md @@ -15,9 +15,17 @@ docker build -f docker_gui/gui_linux.Dockerfile -t labnow/gui:selkies docker_gui - 已包含 Node.js 最新 LTS。 - 已包含 Python >= 3.13。 -构建过程会安装 Selkies 运行期系统依赖,克隆 Selkies 最新 release 对应的源码,并安装到 `/opt/selkies`。 +构建过程会安装 Selkies 运行期系统依赖,默认克隆 Selkies `main` 分支最新源码,并安装到 `/opt/selkies`。 默认使用源码构建方式,只保留运行期需要的 Python venv、web dashboard 产物和少量 addon 产物,构建依赖会在同一层内清理。 +如需固定某个 branch、tag 或 commit,可以使用: + +```bash +docker build -f docker_gui/gui_linux.Dockerfile \ + --build-arg ARG_SELKIES_REF=main \ + -t labnow/gui:selkies docker_gui +``` + 如需回退到官方 portable release 包,可以使用: ```bash diff --git a/docker_gui/gui_linux.Dockerfile b/docker_gui/gui_linux.Dockerfile index 86e47ee..56fecc2 100644 --- a/docker_gui/gui_linux.Dockerfile +++ b/docker_gui/gui_linux.Dockerfile @@ -3,10 +3,12 @@ ARG BASE_NAMESPACE ARG BASE_IMG="node" ARG ARG_SELKIES_INSTALL_METHOD=source +ARG ARG_SELKIES_REF=main FROM ${BASE_NAMESPACE:+$BASE_NAMESPACE/}${BASE_IMG} ARG ARG_SELKIES_INSTALL_METHOD=source +ARG ARG_SELKIES_REF=main LABEL maintainer="postmaster@labnow.ai" @@ -20,6 +22,7 @@ RUN set -eux && source /opt/utils/script-utils.sh \ && if [ "${ARG_SELKIES_INSTALL_METHOD}" = "release" ] ; then \ setup_selkies_from_release ; \ else \ + export VER_SELKIES_REF="${ARG_SELKIES_REF}" ; \ setup_selkies_build_dependencies && setup_selkies_from_source ; \ fi \ && mv /opt/utils/docker-entrypoint.sh /opt/selkies/docker-entrypoint.sh \ diff --git a/docker_gui/work/install_list_selkies_build.apt b/docker_gui/work/install_list_selkies_build.apt deleted file mode 100644 index 01fc676..0000000 --- a/docker_gui/work/install_list_selkies_build.apt +++ /dev/null @@ -1,9 +0,0 @@ -build-essential -cmake -g++ -gcc -git -make -pkg-config -python3-dev -python3-venv diff --git a/docker_gui/work/script-setup-gui.sh b/docker_gui/work/script-setup-gui.sh index d2a18b6..ae4e348 100644 --- a/docker_gui/work/script-setup-gui.sh +++ b/docker_gui/work/script-setup-gui.sh @@ -5,7 +5,8 @@ setup_selkies_dependencies() { } setup_selkies_build_dependencies() { - install_apt /opt/utils/install_list_selkies_build.apt ; + apt-get -qq update -yq --fix-missing && apt-get -qq install -yq --no-install-recommends \ + build-essential cmake g++ gcc git make pkg-config python3-dev python3-venv ; } setup_selkies_from_release() { @@ -97,26 +98,35 @@ cleanup_selkies_build_dependencies() { && rm -rf /tmp/selkies-src /root/.cache /root/.npm /var/tmp/* ; } +checkout_selkies_source() { + local ref="${1:-main}" + local src_dir="${2:-/tmp/selkies-src}" + local repo="https://github.com/selkies-project/selkies.git" + + if git ls-remote --exit-code --heads --tags "${repo}" "${ref}" >/dev/null 2>&1; then + git clone --depth 1 --branch "${ref}" "${repo}" "${src_dir}" ; + else + git clone --filter=blob:none --no-checkout "${repo}" "${src_dir}" \ + && git -C "${src_dir}" fetch --depth 1 origin "${ref}" \ + && git -C "${src_dir}" checkout FETCH_HEAD ; + fi +} + setup_selkies_from_source() { # ref: https://github.com/linuxserver/docker-baseimage-selkies/blob/master/Dockerfile - local tag="${VER_SELKIES:-}" + local ref="${VER_SELKIES_REF:-${VER_SELKIES:-main}}" local src_dir="/tmp/selkies-src" - [ -n "${tag}" ] || tag="$(curl -fsSL "https://api.github.com/repos/selkies-project/selkies/releases/latest" | jq -r '.tag_name')" \ - && echo "Cloning Selkies source at ${tag}" \ + echo "Cloning Selkies source at ${ref}" \ && rm -rf /opt/selkies "${src_dir}" \ && mkdir -pv /opt/selkies/share \ - && git clone --depth 1 --branch "${tag}" https://github.com/selkies-project/selkies.git "${src_dir}" \ + && checkout_selkies_source "${ref}" "${src_dir}" \ && setup_selkies_web_from_source "${src_dir}" /opt/selkies/share/selkies-web \ && setup_selkies_python_from_source "${src_dir}" \ && setup_selkies_addons_from_source "${src_dir}" \ && setup_selkies_runtime_wrapper \ - && echo "${tag}" > /opt/selkies/version_info.txt \ + && git -C "${src_dir}" rev-parse HEAD > /opt/selkies/version_info.txt \ && cleanup_selkies_build_dependencies ; [ -x /opt/selkies/selkies-gstreamer-run ] && echo "@ Version of Selkies-GStreamer $(cat /opt/selkies/version_info.txt)" || return 1 ; } - -setup_selkies() { - setup_selkies_from_source ; -} From 635bf9c3e62e25966927b3cc2f0ba4021ee31d4e Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Tue, 9 Jun 2026 21:51:10 +0800 Subject: [PATCH 06/16] debug build --- docker_gui/work/script-setup-gui.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker_gui/work/script-setup-gui.sh b/docker_gui/work/script-setup-gui.sh index ae4e348..4825ebb 100644 --- a/docker_gui/work/script-setup-gui.sh +++ b/docker_gui/work/script-setup-gui.sh @@ -6,7 +6,7 @@ setup_selkies_dependencies() { setup_selkies_build_dependencies() { apt-get -qq update -yq --fix-missing && apt-get -qq install -yq --no-install-recommends \ - build-essential cmake g++ gcc git make pkg-config python3-dev python3-venv ; + build-essential cmake g++ gcc git libxkbcommon-dev make pkg-config python3-dev python3-venv ; } setup_selkies_from_release() { @@ -93,7 +93,7 @@ EOF cleanup_selkies_build_dependencies() { apt-get purge -y --auto-remove \ - build-essential cmake g++ gcc git make pkg-config python3-dev \ + build-essential cmake g++ gcc git libxkbcommon-dev make pkg-config python3-dev \ python3-venv \ && rm -rf /tmp/selkies-src /root/.cache /root/.npm /var/tmp/* ; } From 8ff9865718ac6a5068977dbb69b94d92da985f8d Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Tue, 9 Jun 2026 22:02:17 +0800 Subject: [PATCH 07/16] fix apt dep --- docker_gui/work/install_list_selkies.apt | 69 ++++++++++++------------ 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/docker_gui/work/install_list_selkies.apt b/docker_gui/work/install_list_selkies.apt index d03dd8f..42c8485 100644 --- a/docker_gui/work/install_list_selkies.apt +++ b/docker_gui/work/install_list_selkies.apt @@ -1,34 +1,35 @@ -jq -tar -gzip -ca-certificates -curl -gstreamer1.0-alsa -gstreamer1.0-gl -gstreamer1.0-libav -gstreamer1.0-plugins-bad -gstreamer1.0-plugins-base -gstreamer1.0-plugins-good -gstreamer1.0-plugins-ugly -gstreamer1.0-pulseaudio -gstreamer1.0-tools -gstreamer1.0-x -libpulse0 -python3-gi -python3-gst-1.0 -wayland-protocols -libwayland-dev -libwayland-egl1 -x11-utils -x11-xkb-utils -x11-xserver-utils -xserver-xorg-core -libx11-xcb1 -libxcb-dri3-0 -libxkbcommon0 -libxdamage1 -libxfixes3 -libxv1 -libxtst6 -libxext6 -xvfb +jq % 解析 GitHub API 返回的 JSON,读取 Selkies release 或元数据。 +tar % 解包 Selkies 下载包和构建产物。 +gzip % 处理 gzip 压缩文件流,配合 tar/curl 下载包使用。 +ca-certificates % 提供 TLS 证书链,确保 curl 能安全访问 GitHub 和外部服务。 +curl % 下载 Selkies release、GitHub API 数据以及运行期需要的远程资源。 +libatomic1 % Node.js 运行时依赖,避免清理阶段触发 npm 时缺少 libatomic.so.1。 +gstreamer1.0-alsa % GStreamer ALSA 音频输入输出插件,支持本地音频管线。 +gstreamer1.0-gl % GStreamer GL 渲染相关插件,支撑浏览器画面渲染链路。 +gstreamer1.0-libav % 提供 FFmpeg 编解码支持,补齐常见媒体格式能力。 +gstreamer1.0-plugins-bad % 一组额外 GStreamer 插件,Selkies 某些媒体功能会用到。 +gstreamer1.0-plugins-base % GStreamer 基础插件集,提供最基本的音视频管线能力。 +gstreamer1.0-plugins-good % 稳定常用的 GStreamer 插件,支撑编码、传输和处理。 +gstreamer1.0-plugins-ugly % 提供部分专有或受限编码器插件,补齐可用编码选项。 +gstreamer1.0-pulseaudio % GStreamer PulseAudio 插件,支持音频采集和播放。 +gstreamer1.0-tools % GStreamer 命令行工具,便于调试和检查运行时管线。 +gstreamer1.0-x % GStreamer X11 相关插件,支持 X11 显示和窗口采集链路。 +libpulse0 % PulseAudio 客户端库,Selkies 音频子系统运行时需要。 +python3-gi % Python 的 GObject Introspection 绑定,Selkies Python 代码会调用。 +python3-gst-1.0 % Python 的 GStreamer 绑定,Selkies Python 层需要操作 GStreamer。 +wayland-protocols % Wayland 协议定义,支持 Wayland/X11 混合桌面环境。 +libwayland-dev % Wayland 开发头文件,供构建或运行时绑定加载使用。 +libwayland-egl1 % Wayland EGL 运行库,支撑图形渲染和显示输出。 +x11-utils % X11 基础工具,便于检查和驱动 X 会话。 +x11-xkb-utils % XKB 键盘布局工具,支持键盘输入和布局处理。 +x11-xserver-utils % X11 服务器辅助工具,支持屏幕配置和输入管理。 +xserver-xorg-core % X.Org 核心服务器,Selkies 需要它提供虚拟 X 显示。 +libx11-xcb1 % X11 与 XCB 桥接库,支持 X 客户端和底层事件通信。 +libxcb-dri3-0 % XCB DRI3 扩展库,图形加速和显示管线常会用到。 +libxkbcommon0 % 键盘布局与按键映射运行库,支持输入事件转换。 +libxdamage1 % XDamage 扩展库,帮助检测和推送屏幕内容变化。 +libxfixes3 % XFixes 扩展库,支持光标和屏幕修补相关功能。 +libxv1 % XVideo 运行库,供旧式视频/X11 输出链路使用。 +libxtst6 % XTest 运行库,支持注入键鼠事件,Selkies 输入控制会用到。 +libxext6 % X11 扩展库集合,提供多种必需的 X 扩展支持。 +xvfb % 虚拟 X 服务器,在容器里提供无头显示环境。 From 8bec7b20f6731f29427e5e827e0ad223710b83be Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Tue, 9 Jun 2026 22:26:45 +0800 Subject: [PATCH 08/16] debug working dir --- docker_gui/gui_linux.Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker_gui/gui_linux.Dockerfile b/docker_gui/gui_linux.Dockerfile index 56fecc2..ebeb855 100644 --- a/docker_gui/gui_linux.Dockerfile +++ b/docker_gui/gui_linux.Dockerfile @@ -28,7 +28,9 @@ RUN set -eux && source /opt/utils/script-utils.sh \ && mv /opt/utils/docker-entrypoint.sh /opt/selkies/docker-entrypoint.sh \ && chmod +x /opt/selkies/docker-entrypoint.sh \ ## Clean up and display components version information... - && list_installed_packages && install__clean + && cd /opt/selkies \ + && list_installed_packages \ + && install__clean ENV PATH=/opt/selkies:${PATH} From 431197203d676424f13b5400541b80f4fda47949 Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Tue, 9 Jun 2026 23:30:07 +0800 Subject: [PATCH 09/16] multi-stage build --- docker_gui/gui_linux.Dockerfile | 24 ++++++++++++++++++------ docker_gui/work/script-setup-gui.sh | 24 +++++++++++++++--------- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/docker_gui/gui_linux.Dockerfile b/docker_gui/gui_linux.Dockerfile index ebeb855..66cce26 100644 --- a/docker_gui/gui_linux.Dockerfile +++ b/docker_gui/gui_linux.Dockerfile @@ -1,22 +1,22 @@ # Distributed under the terms of the Modified BSD License. ARG BASE_NAMESPACE +ARG BASE_IMG_BUILD="node" ARG BASE_IMG="node" ARG ARG_SELKIES_INSTALL_METHOD=source ARG ARG_SELKIES_REF=main -FROM ${BASE_NAMESPACE:+$BASE_NAMESPACE/}${BASE_IMG} + +# Stage 1: build selkies from source +FROM ${BASE_NAMESPACE:+$BASE_NAMESPACE/}${BASE_IMG_BUILD} as builder ARG ARG_SELKIES_INSTALL_METHOD=source ARG ARG_SELKIES_REF=main -LABEL maintainer="postmaster@labnow.ai" - COPY work /opt/utils/ RUN set -eux && source /opt/utils/script-utils.sh \ && chmod +x /opt/utils/*.sh \ - ## ----------------------------- Install selkies && source /opt/utils/script-setup-gui.sh \ && setup_selkies_dependencies \ && if [ "${ARG_SELKIES_INSTALL_METHOD}" = "release" ] ; then \ @@ -26,9 +26,21 @@ RUN set -eux && source /opt/utils/script-utils.sh \ setup_selkies_build_dependencies && setup_selkies_from_source ; \ fi \ && mv /opt/utils/docker-entrypoint.sh /opt/selkies/docker-entrypoint.sh \ - && chmod +x /opt/selkies/docker-entrypoint.sh \ - ## Clean up and display components version information... + && mv /opt/utils/install_list_selkies.apt /opt/selkies/ \ + && chmod +x /opt/selkies/docker-entrypoint.sh + + +# Stage 2: runtime image +FROM ${BASE_NAMESPACE:+$BASE_NAMESPACE/}${BASE_IMG} + +LABEL maintainer="postmaster@labnow.ai" + +COPY --from=builder /opt/selkies /opt/selkies + +RUN set -eux && source /opt/utils/script-utils.sh \ + && install_apt /opt/selkies/install_list_selkies.apt \ && cd /opt/selkies \ + && pip install --no-cache-dir ./*.whl \ && list_installed_packages \ && install__clean diff --git a/docker_gui/work/script-setup-gui.sh b/docker_gui/work/script-setup-gui.sh index 4825ebb..ad2b236 100644 --- a/docker_gui/work/script-setup-gui.sh +++ b/docker_gui/work/script-setup-gui.sh @@ -54,11 +54,17 @@ setup_selkies_web_from_source() { setup_selkies_python_from_source() { local src_dir="${1:-/tmp/selkies-src}" - - echo "--> Installing Selkies Python package..." \ - && python3 -m venv --system-site-packages /opt/selkies/venv \ - && /opt/selkies/venv/bin/pip install --no-cache-dir --upgrade pip setuptools wheel \ - && /opt/selkies/venv/bin/pip install --no-cache-dir "${src_dir}" ; + local dist_dir="/tmp/selkies-dist" + + echo "--> Building Selkies Python package..." \ + && mkdir -p "${dist_dir}" \ + && cd "${src_dir}" \ + && pip install --no-cache-dir --upgrade pip setuptools wheel \ + && python3 setup.py sdist bdist_wheel -d "${dist_dir}" \ + && cp -r "${dist_dir}"/*.whl /opt/selkies/ \ + && echo "--> Installing Selkies Python package..." \ + && pip install --no-cache-dir "${dist_dir}"/*.whl \ + && rm -rf "${dist_dir}" ; } setup_selkies_addons_from_source() { @@ -82,10 +88,10 @@ setup_selkies_runtime_wrapper() { cat > /opt/selkies/selkies-gstreamer-run <<'EOF' #!/usr/bin/env bash set -euo pipefail -if [ -x /opt/selkies/venv/bin/selkies-gstreamer ]; then - exec /opt/selkies/venv/bin/selkies-gstreamer "$@" +if command -v selkies-gstreamer &>/dev/null; then + exec selkies-gstreamer "$@" fi -exec /opt/selkies/venv/bin/selkies "$@" +exec selkies "$@" EOF chmod +x /opt/selkies/selkies-gstreamer-run \ && ln -sf /opt/selkies/selkies-gstreamer-run /usr/local/bin/selkies-gstreamer-run ; @@ -126,7 +132,7 @@ setup_selkies_from_source() { && setup_selkies_addons_from_source "${src_dir}" \ && setup_selkies_runtime_wrapper \ && git -C "${src_dir}" rev-parse HEAD > /opt/selkies/version_info.txt \ - && cleanup_selkies_build_dependencies ; + && rm -rf /tmp/selkies-src /root/.cache /root/.npm /var/tmp/* ; [ -x /opt/selkies/selkies-gstreamer-run ] && echo "@ Version of Selkies-GStreamer $(cat /opt/selkies/version_info.txt)" || return 1 ; } From d7bad6731b11efa0987aa61e540eabd5ea21dd58 Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Tue, 9 Jun 2026 23:32:54 +0800 Subject: [PATCH 10/16] debug addons --- docker_gui/gui_linux.Dockerfile | 7 +++++++ docker_gui/work/script-setup-gui.sh | 12 ++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/docker_gui/gui_linux.Dockerfile b/docker_gui/gui_linux.Dockerfile index 66cce26..9cac417 100644 --- a/docker_gui/gui_linux.Dockerfile +++ b/docker_gui/gui_linux.Dockerfile @@ -41,6 +41,13 @@ RUN set -eux && source /opt/utils/script-utils.sh \ && install_apt /opt/selkies/install_list_selkies.apt \ && cd /opt/selkies \ && pip install --no-cache-dir ./*.whl \ + && if [ -f /opt/selkies/lib/selkies_joystick_interposer.so ]; then \ + ln -sf /opt/selkies/lib/selkies_joystick_interposer.so /usr/lib/selkies_joystick_interposer.so ; \ + fi \ + && if [ -f /opt/selkies/lib/libudev.so.1.0.0-fake ]; then \ + mkdir -p /opt/lib \ + && ln -sf /opt/selkies/lib/libudev.so.1.0.0-fake /opt/lib/libudev.so.1.0.0-fake ; \ + fi \ && list_installed_packages \ && install__clean diff --git a/docker_gui/work/script-setup-gui.sh b/docker_gui/work/script-setup-gui.sh index ad2b236..4b4d017 100644 --- a/docker_gui/work/script-setup-gui.sh +++ b/docker_gui/work/script-setup-gui.sh @@ -69,18 +69,22 @@ setup_selkies_python_from_source() { setup_selkies_addons_from_source() { local src_dir="${1:-/tmp/selkies-src}" + local lib_dir="/opt/selkies/lib" + + mkdir -p "${lib_dir}" if [ -f "${src_dir}/addons/js-interposer/joystick_interposer.c" ]; then echo "--> Building Selkies joystick interposer..." \ - && gcc -shared -fPIC -ldl -o /usr/lib/selkies_joystick_interposer.so \ - "${src_dir}/addons/js-interposer/joystick_interposer.c" ; + && gcc -shared -fPIC -ldl -o "${lib_dir}/selkies_joystick_interposer.so" \ + "${src_dir}/addons/js-interposer/joystick_interposer.c" \ + && ln -sf "${lib_dir}/selkies_joystick_interposer.so" /usr/lib/selkies_joystick_interposer.so ; fi if [ -f "${src_dir}/addons/fake-udev/Makefile" ]; then echo "--> Building Selkies fake udev..." \ && make -C "${src_dir}/addons/fake-udev" \ - && mkdir -pv /opt/lib \ - && mv "${src_dir}/addons/fake-udev/libudev.so.1.0.0-fake" /opt/lib/ ; + && mv "${src_dir}/addons/fake-udev/libudev.so.1.0.0-fake" "${lib_dir}/" \ + && ln -sf "${lib_dir}/libudev.so.1.0.0-fake" /opt/lib/libudev.so.1.0.0-fake ; fi } From 39d0da8d13bf803f33038ecab18f213d9e92a952 Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Tue, 9 Jun 2026 23:34:58 +0800 Subject: [PATCH 11/16] add xclip --- docker_gui/work/install_list_selkies.apt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker_gui/work/install_list_selkies.apt b/docker_gui/work/install_list_selkies.apt index 42c8485..0170e55 100644 --- a/docker_gui/work/install_list_selkies.apt +++ b/docker_gui/work/install_list_selkies.apt @@ -32,4 +32,6 @@ libxfixes3 % XFixes 扩展库,支持光标和屏幕修补相 libxv1 % XVideo 运行库,供旧式视频/X11 输出链路使用。 libxtst6 % XTest 运行库,支持注入键鼠事件,Selkies 输入控制会用到。 libxext6 % X11 扩展库集合,提供多种必需的 X 扩展支持。 -xvfb % 虚拟 X 服务器,在容器里提供无头显示环境。 +xvfb % +xclip % +x11-xserver-utils % 虚拟 X 服务器,在容器里提供无头显示环境。 From 67f0fa9bd92ac0ae5f479968e3386f3d63610840 Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Tue, 9 Jun 2026 23:53:56 +0800 Subject: [PATCH 12/16] fix pytoml build --- docker_gui/work/install_list_selkies.apt | 79 +++++++++++++----------- docker_gui/work/script-setup-gui.sh | 4 +- 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/docker_gui/work/install_list_selkies.apt b/docker_gui/work/install_list_selkies.apt index 0170e55..f32fa4f 100644 --- a/docker_gui/work/install_list_selkies.apt +++ b/docker_gui/work/install_list_selkies.apt @@ -1,37 +1,42 @@ -jq % 解析 GitHub API 返回的 JSON,读取 Selkies release 或元数据。 -tar % 解包 Selkies 下载包和构建产物。 -gzip % 处理 gzip 压缩文件流,配合 tar/curl 下载包使用。 -ca-certificates % 提供 TLS 证书链,确保 curl 能安全访问 GitHub 和外部服务。 -curl % 下载 Selkies release、GitHub API 数据以及运行期需要的远程资源。 -libatomic1 % Node.js 运行时依赖,避免清理阶段触发 npm 时缺少 libatomic.so.1。 -gstreamer1.0-alsa % GStreamer ALSA 音频输入输出插件,支持本地音频管线。 -gstreamer1.0-gl % GStreamer GL 渲染相关插件,支撑浏览器画面渲染链路。 -gstreamer1.0-libav % 提供 FFmpeg 编解码支持,补齐常见媒体格式能力。 -gstreamer1.0-plugins-bad % 一组额外 GStreamer 插件,Selkies 某些媒体功能会用到。 -gstreamer1.0-plugins-base % GStreamer 基础插件集,提供最基本的音视频管线能力。 -gstreamer1.0-plugins-good % 稳定常用的 GStreamer 插件,支撑编码、传输和处理。 -gstreamer1.0-plugins-ugly % 提供部分专有或受限编码器插件,补齐可用编码选项。 -gstreamer1.0-pulseaudio % GStreamer PulseAudio 插件,支持音频采集和播放。 -gstreamer1.0-tools % GStreamer 命令行工具,便于调试和检查运行时管线。 -gstreamer1.0-x % GStreamer X11 相关插件,支持 X11 显示和窗口采集链路。 -libpulse0 % PulseAudio 客户端库,Selkies 音频子系统运行时需要。 -python3-gi % Python 的 GObject Introspection 绑定,Selkies Python 代码会调用。 -python3-gst-1.0 % Python 的 GStreamer 绑定,Selkies Python 层需要操作 GStreamer。 -wayland-protocols % Wayland 协议定义,支持 Wayland/X11 混合桌面环境。 -libwayland-dev % Wayland 开发头文件,供构建或运行时绑定加载使用。 -libwayland-egl1 % Wayland EGL 运行库,支撑图形渲染和显示输出。 -x11-utils % X11 基础工具,便于检查和驱动 X 会话。 -x11-xkb-utils % XKB 键盘布局工具,支持键盘输入和布局处理。 -x11-xserver-utils % X11 服务器辅助工具,支持屏幕配置和输入管理。 -xserver-xorg-core % X.Org 核心服务器,Selkies 需要它提供虚拟 X 显示。 -libx11-xcb1 % X11 与 XCB 桥接库,支持 X 客户端和底层事件通信。 -libxcb-dri3-0 % XCB DRI3 扩展库,图形加速和显示管线常会用到。 -libxkbcommon0 % 键盘布局与按键映射运行库,支持输入事件转换。 -libxdamage1 % XDamage 扩展库,帮助检测和推送屏幕内容变化。 -libxfixes3 % XFixes 扩展库,支持光标和屏幕修补相关功能。 -libxv1 % XVideo 运行库,供旧式视频/X11 输出链路使用。 -libxtst6 % XTest 运行库,支持注入键鼠事件,Selkies 输入控制会用到。 -libxext6 % X11 扩展库集合,提供多种必需的 X 扩展支持。 -xvfb % -xclip % -x11-xserver-utils % 虚拟 X 服务器,在容器里提供无头显示环境。 +% X11 and display server +xvfb % Virtual X server that runs in memory without a display +x11-xserver-utils % X11 server utilities including xrandr +x11-utils % X11 utilities +x11-xkb-utils % X11 XKB utilities for keyboard handling + +% X11 libraries +libx11-xcb1 % X11 XCB interoperability library +libxcb-dri3-0 % XCB DRI3 extension for graphics acceleration +libxkbcommon0 % Keyboard layout and key mapping library +libxdamage1 % X Damage extension to track screen content changes +libxfixes3 % X Fixes extension for cursor and screen fixes +libxv1 % X Video extension library +libxtst6 % X Test extension for injecting input events +libxext6 % X11 extensions library +libxkbcommon-dev % XKB library development files (for building) +libatomic1 % Atomic operations library + +% GStreamer - core, plugins base, and plugins +gstreamer1.0-tools % GStreamer command-line tools +gstreamer1.0-plugins-base % GStreamer base plugins set +gstreamer1.0-plugins-good % GStreamer good and reliable plugins set +gstreamer1.0-plugins-bad % GStreamer bad but useful plugins set +gstreamer1.0-plugins-ugly % GStreamer ugly plugins set with patent-encumbered codecs +gstreamer1.0-libav % GStreamer libav/FFmpeg plugin +gstreamer1.0-alsa % GStreamer ALSA plugin for audio +gstreamer1.0-pulseaudio % GStreamer PulseAudio plugin +gstreamer1.0-gl % GStreamer GL plugin for graphics + +% Python GObject introspection +python3-gi % Python GObject introspection bindings +python3-gst-1.0 % Python GStreamer bindings + +% Wayland support +wayland-protocols % Wayland protocols +libwayland-egl1 % Wayland EGL library + +% Clipboard support +xclip % Command line interface to X selections (clipboard) + +% PulseAudio +libpulse0 % PulseAudio client library diff --git a/docker_gui/work/script-setup-gui.sh b/docker_gui/work/script-setup-gui.sh index 4b4d017..1c7dd4a 100644 --- a/docker_gui/work/script-setup-gui.sh +++ b/docker_gui/work/script-setup-gui.sh @@ -59,8 +59,8 @@ setup_selkies_python_from_source() { echo "--> Building Selkies Python package..." \ && mkdir -p "${dist_dir}" \ && cd "${src_dir}" \ - && pip install --no-cache-dir --upgrade pip setuptools wheel \ - && python3 setup.py sdist bdist_wheel -d "${dist_dir}" \ + && pip install --no-cache-dir --upgrade pip setuptools wheel build \ + && python3 -m build --outdir "${dist_dir}" \ && cp -r "${dist_dir}"/*.whl /opt/selkies/ \ && echo "--> Installing Selkies Python package..." \ && pip install --no-cache-dir "${dist_dir}"/*.whl \ From deafc85d7ed3bdc1418a07c487a18894aef70bb7 Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Wed, 10 Jun 2026 00:17:18 +0800 Subject: [PATCH 13/16] debug libs --- docker_gui/gui_linux.Dockerfile | 8 ++++---- docker_gui/work/script-setup-gui.sh | 6 ++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/docker_gui/gui_linux.Dockerfile b/docker_gui/gui_linux.Dockerfile index 9cac417..0d7aaef 100644 --- a/docker_gui/gui_linux.Dockerfile +++ b/docker_gui/gui_linux.Dockerfile @@ -45,11 +45,11 @@ RUN set -eux && source /opt/utils/script-utils.sh \ ln -sf /opt/selkies/lib/selkies_joystick_interposer.so /usr/lib/selkies_joystick_interposer.so ; \ fi \ && if [ -f /opt/selkies/lib/libudev.so.1.0.0-fake ]; then \ - mkdir -p /opt/lib \ - && ln -sf /opt/selkies/lib/libudev.so.1.0.0-fake /opt/lib/libudev.so.1.0.0-fake ; \ + ln -sf /opt/selkies/lib/libudev.so.1.0.0-fake /usr/lib/libudev.so.1.0.0-fake \ + && ln -sf /opt/selkies/lib/libudev.so.1.0.0-fake /usr/lib/libudev.so.1 \ + && ln -sf /opt/selkies/lib/libudev.so.1.0.0-fake /usr/lib/libudev.so ; \ fi \ - && list_installed_packages \ - && install__clean + && list_installed_packages && install__clean ENV PATH=/opt/selkies:${PATH} diff --git a/docker_gui/work/script-setup-gui.sh b/docker_gui/work/script-setup-gui.sh index 1c7dd4a..6abaf89 100644 --- a/docker_gui/work/script-setup-gui.sh +++ b/docker_gui/work/script-setup-gui.sh @@ -76,15 +76,13 @@ setup_selkies_addons_from_source() { if [ -f "${src_dir}/addons/js-interposer/joystick_interposer.c" ]; then echo "--> Building Selkies joystick interposer..." \ && gcc -shared -fPIC -ldl -o "${lib_dir}/selkies_joystick_interposer.so" \ - "${src_dir}/addons/js-interposer/joystick_interposer.c" \ - && ln -sf "${lib_dir}/selkies_joystick_interposer.so" /usr/lib/selkies_joystick_interposer.so ; + "${src_dir}/addons/js-interposer/joystick_interposer.c" ; fi if [ -f "${src_dir}/addons/fake-udev/Makefile" ]; then echo "--> Building Selkies fake udev..." \ && make -C "${src_dir}/addons/fake-udev" \ - && mv "${src_dir}/addons/fake-udev/libudev.so.1.0.0-fake" "${lib_dir}/" \ - && ln -sf "${lib_dir}/libudev.so.1.0.0-fake" /opt/lib/libudev.so.1.0.0-fake ; + && mv "${src_dir}/addons/fake-udev/libudev.so.1.0.0-fake" "${lib_dir}/" ; fi } From 8bb86f414b8ca87e1b0eede4d2d3eec8b7b086ef Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Wed, 10 Jun 2026 01:58:38 +0800 Subject: [PATCH 14/16] code clean --- docker_gui/README.md | 2 +- docker_gui/gui_linux.Dockerfile | 18 ++- docker_gui/work/docker-entrypoint.sh | 196 +++++++++++++++++++---- docker_gui/work/install_list_selkies.apt | 10 +- docker_gui/work/script-setup-gui.sh | 23 ++- 5 files changed, 193 insertions(+), 56 deletions(-) diff --git a/docker_gui/README.md b/docker_gui/README.md index bd7322e..fccc896 100644 --- a/docker_gui/README.md +++ b/docker_gui/README.md @@ -1,4 +1,4 @@ -# docker_gui +# GUI Linux 这个镜像用于打包 Selkies-GStreamer,把容器内的 Linux GUI 会话通过浏览器访问。 镜像只负责 GUI 串流层,默认关闭 Selkies 内置 Basic Auth,认证和鉴权建议放在上游网关、反向代理或平台侧处理。 diff --git a/docker_gui/gui_linux.Dockerfile b/docker_gui/gui_linux.Dockerfile index 0d7aaef..a3b28e8 100644 --- a/docker_gui/gui_linux.Dockerfile +++ b/docker_gui/gui_linux.Dockerfile @@ -2,23 +2,23 @@ ARG BASE_NAMESPACE ARG BASE_IMG_BUILD="node" -ARG BASE_IMG="node" +ARG BASE_IMG="base" ARG ARG_SELKIES_INSTALL_METHOD=source ARG ARG_SELKIES_REF=main # Stage 1: build selkies from source -FROM ${BASE_NAMESPACE:+$BASE_NAMESPACE/}${BASE_IMG_BUILD} as builder +FROM ${BASE_NAMESPACE:+$BASE_NAMESPACE/}${BASE_IMG_BUILD} AS builder ARG ARG_SELKIES_INSTALL_METHOD=source ARG ARG_SELKIES_REF=main COPY work /opt/utils/ -RUN set -eux && source /opt/utils/script-utils.sh \ - && chmod +x /opt/utils/*.sh \ +RUN set -eux && chmod +x /opt/utils/*.sh \ + && source /opt/utils/script-utils.sh \ && source /opt/utils/script-setup-gui.sh \ - && setup_selkies_dependencies \ + && install_apt /opt/utils/install_list_selkies.apt \ && if [ "${ARG_SELKIES_INSTALL_METHOD}" = "release" ] ; then \ setup_selkies_from_release ; \ else \ @@ -37,9 +37,12 @@ LABEL maintainer="postmaster@labnow.ai" COPY --from=builder /opt/selkies /opt/selkies -RUN set -eux && source /opt/utils/script-utils.sh \ +RUN set -eux && cd /opt/selkies \ + && source /opt/utils/script-utils.sh \ && install_apt /opt/selkies/install_list_selkies.apt \ - && cd /opt/selkies \ + && apt install -y build-essential cmake pkg-config libx11-dev libxext-dev libxfixes-dev libjpeg-dev libx264-dev libyuv-dev libavcodec-dev libavutil-dev libva-dev \ + && pip install --no-cache-dir --no-binary :all: pixelflux \ + && apt purge -y build-essential cmake pkg-config libx11-dev libxext-dev libxfixes-dev libjpeg-dev libx264-dev libyuv-dev libavcodec-dev libavutil-dev libva-dev \ && pip install --no-cache-dir ./*.whl \ && if [ -f /opt/selkies/lib/selkies_joystick_interposer.so ]; then \ ln -sf /opt/selkies/lib/selkies_joystick_interposer.so /usr/lib/selkies_joystick_interposer.so ; \ @@ -64,4 +67,3 @@ WORKDIR /opt/selkies # After that, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. SHELL ["/bin/bash", "--login", "-o", "pipefail", "-c"] ENTRYPOINT ["/opt/selkies/docker-entrypoint.sh"] -CMD [] diff --git a/docker_gui/work/docker-entrypoint.sh b/docker_gui/work/docker-entrypoint.sh index d976a03..a8cdaff 100644 --- a/docker_gui/work/docker-entrypoint.sh +++ b/docker_gui/work/docker-entrypoint.sh @@ -1,37 +1,169 @@ #!/usr/bin/env bash -set -euo pipefail +set -Eeuo pipefail +# +# Runtime env +# export DISPLAY="${DISPLAY:-:99}" -export PIPEWIRE_LATENCY="${PIPEWIRE_LATENCY:-128/48000}" -export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/tmp}" -export PIPEWIRE_RUNTIME_DIR="${PIPEWIRE_RUNTIME_DIR:-${XDG_RUNTIME_DIR}}" -export PULSE_RUNTIME_PATH="${PULSE_RUNTIME_PATH:-${XDG_RUNTIME_DIR}/pulse}" -export PULSE_SERVER="${PULSE_SERVER:-unix:${PULSE_RUNTIME_PATH}/native}" - -if [ "$#" -eq 0 ]; then - set -- \ - --addr="${SELKIES_ADDR:-0.0.0.0}" \ - --port="${SELKIES_PORT:-8080}" \ - --web_root="${SELKIES_WEB_ROOT:-/opt/selkies/share/selkies-web}" \ - --enable_https="${SELKIES_ENABLE_HTTPS:-false}" \ - --https_cert="${SELKIES_HTTPS_CERT:-/etc/ssl/certs/ssl-cert-snakeoil.pem}" \ - --https_key="${SELKIES_HTTPS_KEY:-/etc/ssl/private/ssl-cert-snakeoil.key}" \ - --enable_basic_auth="${SELKIES_ENABLE_BASIC_AUTH:-false}" \ - --basic_auth_user="${SELKIES_BASIC_AUTH_USER:-}" \ - --basic_auth_password="${SELKIES_BASIC_AUTH_PASSWORD:-}" \ - --stun_host="${SELKIES_STUN_HOST:-stun.l.google.com}" \ - --stun_port="${SELKIES_STUN_PORT:-19302}" \ - --turn_host="${SELKIES_TURN_HOST:-}" \ - --turn_port="${SELKIES_TURN_PORT:-3478}" \ - --turn_protocol="${SELKIES_TURN_PROTOCOL:-udp}" \ - --turn_tls="${SELKIES_TURN_TLS:-false}" \ - --turn_username="${SELKIES_TURN_USERNAME:-}" \ - --turn_password="${SELKIES_TURN_PASSWORD:-}" \ - --turn_shared_secret="${SELKIES_TURN_SHARED_SECRET:-}" \ - --encoder="${SELKIES_ENCODER:-x264enc}" \ - --enable_resize="${SELKIES_ENABLE_RESIZE:-false}" -elif [[ "$1" != "-"* ]]; then - exec "$@" + +export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/tmp/runtime-root}" +export PIPEWIRE_RUNTIME_DIR="${PIPEWIRE_RUNTIME_DIR:-$XDG_RUNTIME_DIR}" + +export PULSE_RUNTIME_PATH="${PULSE_RUNTIME_PATH:-$XDG_RUNTIME_DIR/pulse}" +export PULSE_SERVER="${PULSE_SERVER:-unix:$PULSE_RUNTIME_PATH/native}" + +export SELKIES_ENABLE_BASIC_AUTH="${SELKIES_ENABLE_BASIC_AUTH:-false}" +export SELKIES_ENABLE_RESIZE="${SELKIES_ENABLE_RESIZE:-false}" +export SELKIES_ENABLE_HTTPS="${SELKIES_ENABLE_HTTPS:-false}" + +mkdir -pv "$XDG_RUNTIME_DIR" "$PULSE_RUNTIME_PATH" + +chmod 700 "$XDG_RUNTIME_DIR" + +# +# Xvfb +# +if ! xdpyinfo -display "$DISPLAY" >/dev/null 2>&1; then + Xvfb "$DISPLAY" \ + -screen 0 "${XVFB_SCREEN:-3840x2160x24}" \ + +extension RANDR \ + +extension GLX \ + +extension RENDER \ + -nolisten tcp \ + >/tmp/xvfb.log 2>&1 & +fi + +# +# wait X ready +# +for _ in $(seq 1 50); do + xdpyinfo -display "$DISPLAY" >/dev/null 2>&1 && break + sleep 0.2 +done + +xdpyinfo -display "$DISPLAY" >/dev/null 2>&1 || { + echo "Xvfb failed to start" + cat /tmp/xvfb.log || true + exit 1 +} + +# +# Openbox +# +if command -v openbox >/dev/null 2>&1; then + openbox >/tmp/openbox.log 2>&1 & +fi + +# +# xsettingsd +# +if command -v xsettingsd >/dev/null 2>&1; then + mkdir -p /root/.config/xsettingsd + + cat >/root/.config/xsettingsd/xsettingsd.conf </dev/null 2>&1 || true + xsettingsd >/tmp/xsettingsd.log 2>&1 & +fi + +# +# PulseAudio +# +if command -v pulseaudio >/dev/null 2>&1; then + pulseaudio \ + --system \ + --daemonize=yes \ + --disallow-exit \ + --exit-idle-time=-1 \ + >/tmp/pulseaudio.log 2>&1 || true + + # + # wait pulseaudio ready + # + for _ in $(seq 1 30); do + pactl info >/dev/null 2>&1 && break + sleep 0.2 + done + + # + # create dummy sink if missing + # + if pactl info >/dev/null 2>&1; then + if ! pactl list short sinks | grep -q '^output'; then + pactl load-module module-null-sink \ + sink_name=output \ + sink_properties=device.description=output \ + >/dev/null + fi + fi +fi + +# +# Selkies args +# +args=( + "--addr=${SELKIES_ADDR:-0.0.0.0}" + "--port=${SELKIES_PORT:-8080}" + "--web-root=${SELKIES_WEB_ROOT:-/opt/selkies/share/selkies-web}" + + "--encoder=${SELKIES_ENCODER:-x264enc}" + + "--stun-host=${SELKIES_STUN_HOST:-stun.l.google.com}" + "--stun-port=${SELKIES_STUN_PORT:-19302}" + + "--enable-https=${SELKIES_ENABLE_HTTPS}" + "--enable-basic-auth=${SELKIES_ENABLE_BASIC_AUTH}" + "--enable-resize=${SELKIES_ENABLE_RESIZE}" +) + +# +# HTTPS +# +if [ "$SELKIES_ENABLE_HTTPS" = "true" ]; then + args+=( + "--https-cert=${SELKIES_HTTPS_CERT:-/etc/ssl/certs/ssl-cert-snakeoil.pem}" + "--https-key=${SELKIES_HTTPS_KEY:-/etc/ssl/private/ssl-cert-snakeoil.key}" + ) +fi + +# +# Basic auth +# +if [ "$SELKIES_ENABLE_BASIC_AUTH" = "true" ]; then + args+=( + "--basic-auth-user=${SELKIES_BASIC_AUTH_USER:-admin}" + "--basic-auth-password=${SELKIES_BASIC_AUTH_PASSWORD:-admin}" + ) +fi + +# +# TURN +# +if [ -n "${SELKIES_TURN_HOST:-}" ]; then + args+=( + "--turn-host=${SELKIES_TURN_HOST}" + "--turn-port=${SELKIES_TURN_PORT:-3478}" + "--turn-protocol=${SELKIES_TURN_PROTOCOL:-udp}" + ) + + [ "${SELKIES_TURN_TLS:-false}" = "true" ] && \ + args+=("--turn-tls=true") + + [ -n "${SELKIES_TURN_USERNAME:-}" ] && \ + args+=("--turn-username=${SELKIES_TURN_USERNAME}") + + [ -n "${SELKIES_TURN_PASSWORD:-}" ] && \ + args+=("--turn-password=${SELKIES_TURN_PASSWORD}") + + [ -n "${SELKIES_TURN_SHARED_SECRET:-}" ] && \ + args+=("--turn-shared-secret=${SELKIES_TURN_SHARED_SECRET}") fi -exec /opt/selkies/selkies-gstreamer-run "$@" +set -x +exec /opt/selkies/selkies-gstreamer-run "${args[@]}" diff --git a/docker_gui/work/install_list_selkies.apt b/docker_gui/work/install_list_selkies.apt index f32fa4f..4e3b4de 100644 --- a/docker_gui/work/install_list_selkies.apt +++ b/docker_gui/work/install_list_selkies.apt @@ -12,9 +12,12 @@ libxdamage1 % X Damage extension to track screen content change libxfixes3 % X Fixes extension for cursor and screen fixes libxv1 % X Video extension library libxtst6 % X Test extension for injecting input events -libxext6 % X11 extensions library +libxext6 % X11 extensions library libxkbcommon-dev % XKB library development files (for building) libatomic1 % Atomic operations library +dbus-x11 +xserver-xorg-core + % GStreamer - core, plugins base, and plugins gstreamer1.0-tools % GStreamer command-line tools @@ -39,4 +42,7 @@ libwayland-egl1 % Wayland EGL library xclip % Command line interface to X selections (clipboard) % PulseAudio -libpulse0 % PulseAudio client library +pulseaudio libpulse0 % PulseAudio client library + +openbox % minimal window manager +xsettingsd \ No newline at end of file diff --git a/docker_gui/work/script-setup-gui.sh b/docker_gui/work/script-setup-gui.sh index 6abaf89..2be51ad 100644 --- a/docker_gui/work/script-setup-gui.sh +++ b/docker_gui/work/script-setup-gui.sh @@ -1,17 +1,21 @@ -source /opt/utils/script-utils.sh +# ref: https://selkies-project.github.io/selkies/start/#quick-start +# ref: https://github.com/linuxserver/docker-baseimage-selkies/blob/master/Dockerfile -setup_selkies_dependencies() { - install_apt /opt/utils/install_list_selkies.apt ; -} +source /opt/utils/script-utils.sh setup_selkies_build_dependencies() { apt-get -qq update -yq --fix-missing && apt-get -qq install -yq --no-install-recommends \ build-essential cmake g++ gcc git libxkbcommon-dev make pkg-config python3-dev python3-venv ; } +cleanup_selkies_build_dependencies() { + apt-get purge -y --auto-remove \ + build-essential cmake g++ gcc git libxkbcommon-dev make pkg-config python3-dev \ + python3-venv \ + && rm -rf /tmp/selkies-src /root/.cache /root/.npm /var/tmp/* ; +} + setup_selkies_from_release() { - # ref: https://selkies-project.github.io/selkies/start/#quick-start - # ref: https://github.com/linuxserver/docker-baseimage-selkies/blob/master/Dockerfile [ "$(dpkg --print-architecture)" = "amd64" ] || { echo "Unsupported architecture for Selkies portable distribution: $(dpkg --print-architecture)" && return 1 ; } @@ -99,13 +103,6 @@ EOF && ln -sf /opt/selkies/selkies-gstreamer-run /usr/local/bin/selkies-gstreamer-run ; } -cleanup_selkies_build_dependencies() { - apt-get purge -y --auto-remove \ - build-essential cmake g++ gcc git libxkbcommon-dev make pkg-config python3-dev \ - python3-venv \ - && rm -rf /tmp/selkies-src /root/.cache /root/.npm /var/tmp/* ; -} - checkout_selkies_source() { local ref="${1:-main}" local src_dir="${2:-/tmp/selkies-src}" From 521f98abb9cf14eb51ef1ff63f09ed4989edf98b Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Wed, 10 Jun 2026 02:18:02 +0800 Subject: [PATCH 15/16] update install pkgs --- docker_gui/work/install_list_selkies.apt | 88 +++++++++++------------- 1 file changed, 40 insertions(+), 48 deletions(-) diff --git a/docker_gui/work/install_list_selkies.apt b/docker_gui/work/install_list_selkies.apt index 4e3b4de..2efcd4a 100644 --- a/docker_gui/work/install_list_selkies.apt +++ b/docker_gui/work/install_list_selkies.apt @@ -1,48 +1,40 @@ -% X11 and display server -xvfb % Virtual X server that runs in memory without a display -x11-xserver-utils % X11 server utilities including xrandr -x11-utils % X11 utilities -x11-xkb-utils % X11 XKB utilities for keyboard handling - -% X11 libraries -libx11-xcb1 % X11 XCB interoperability library -libxcb-dri3-0 % XCB DRI3 extension for graphics acceleration -libxkbcommon0 % Keyboard layout and key mapping library -libxdamage1 % X Damage extension to track screen content changes -libxfixes3 % X Fixes extension for cursor and screen fixes -libxv1 % X Video extension library -libxtst6 % X Test extension for injecting input events -libxext6 % X11 extensions library -libxkbcommon-dev % XKB library development files (for building) -libatomic1 % Atomic operations library -dbus-x11 -xserver-xorg-core - - -% GStreamer - core, plugins base, and plugins -gstreamer1.0-tools % GStreamer command-line tools -gstreamer1.0-plugins-base % GStreamer base plugins set -gstreamer1.0-plugins-good % GStreamer good and reliable plugins set -gstreamer1.0-plugins-bad % GStreamer bad but useful plugins set -gstreamer1.0-plugins-ugly % GStreamer ugly plugins set with patent-encumbered codecs -gstreamer1.0-libav % GStreamer libav/FFmpeg plugin -gstreamer1.0-alsa % GStreamer ALSA plugin for audio -gstreamer1.0-pulseaudio % GStreamer PulseAudio plugin -gstreamer1.0-gl % GStreamer GL plugin for graphics - -% Python GObject introspection -python3-gi % Python GObject introspection bindings -python3-gst-1.0 % Python GStreamer bindings - -% Wayland support -wayland-protocols % Wayland protocols -libwayland-egl1 % Wayland EGL library - -% Clipboard support -xclip % Command line interface to X selections (clipboard) - -% PulseAudio -pulseaudio libpulse0 % PulseAudio client library - -openbox % minimal window manager -xsettingsd \ No newline at end of file +% ============================================================================== +% Selkies Docker Image APT Package Dependencies +% ============================================================================== + +% 1. X11 Virtual Display & Core Services +xvfb xserver-xorg-core dbus-x11 % Headless virtual display server, core Xorg framework, and DBus for IPC. +x11-xserver-utils x11-utils x11-xkb-utils % Core X11 utilities for resolution scaling, window management, and key mapping. + +% 2. Desktop Environment & Window Management +openbox xsettingsd xclip % Lightweight window manager, X11 daemon config, and remote clipboard support. + +% 3. Screen Capture & Remote Input Libraries +libx11-xcb1 libxcb-dri3-0 libxext6 % XCB interoperability and DRI3 hardware graphics acceleration. +libxdamage1 libxfixes3 libxv1 % Screen damage tracking and cursor fixes for low-latency capture. +libxtst6 % X Test extension for injecting remote WebRTC mouse and keyboard events. + +% 4. Keyboard Layout & Input Mapping +libxkbcommon0 libxkbcommon-dev % Keyboard layout processing and keycode translation for remote input. + +% 5. Wayland Compatibility Layer +wayland-protocols libwayland-egl1 % Wayland display protocols and EGL hardware-accelerated rendering contexts. + +% 6. Audio Server Infrastructure +pulseaudio libpulse0 % Virtual audio daemon and client library to intercept container audio streams. + +% 7. GStreamer Multimedia Pipeline Core +gstreamer1.0-tools gstreamer1.0-plugins-base gstreamer1.0-gl % GStreamer CLI, base plugins, and OpenGL support for hardware rendering. +gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav % Comprehensive plugins (including FFmpeg/H.264) for video stream encoding. + +% 8. GStreamer Audio Bridging +gstreamer1.0-alsa gstreamer1.0-pulseaudio % Audio I/O plugins routing PulseAudio streams into the WebRTC pipeline. + +% 9. Video Frame Pre-processing +libyuv0 % Essential YUV video scaling and color space conversion before encoding. + +% 10. Control Plane & Language Bindings +python3-gi python3-gst-1.0 % Python bindings for GObject and GStreamer to orchestrate media pipelines. + +% 11. System Level Essentials +libatomic1 % Atomic operations for thread-safe C/C++ audio/video processing. From 346137026cf4aa2d9cda9ee9cddf5cd9f4fa588d Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Wed, 10 Jun 2026 02:39:01 +0800 Subject: [PATCH 16/16] fix path --- docker_gui/gui_linux.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker_gui/gui_linux.Dockerfile b/docker_gui/gui_linux.Dockerfile index a3b28e8..c8c861f 100644 --- a/docker_gui/gui_linux.Dockerfile +++ b/docker_gui/gui_linux.Dockerfile @@ -54,7 +54,7 @@ RUN set -eux && cd /opt/selkies \ fi \ && list_installed_packages && install__clean -ENV PATH=/opt/selkies:${PATH} +ENV PATH=/opt/selkies:/opt/conda/bin:${PATH} EXPOSE 8080 WORKDIR /opt/selkies