轻量的自托管 Docker 管理面板:一个二进制,无需任何依赖。
整个程序就是一个约 36 MB 的静态可执行文件(压缩后约 15 MB),网页前端和 Compose 引擎都编译在里面。不需要数据库、运行时或额外的库,也不需要安装 docker CLI 或 docker compose。只要机器上有 Docker Engine,下载后直接运行即可。
在线演示只展示界面,数据是浏览器里的示例,不会连接真实 Docker。
前提:服务器上已运行 Docker Engine,除此之外不需要任何东西。
用容器运行:
docker volume create phyless-datadocker run -d \
--name phyless \
--restart unless-stopped \
-p 8080:8080 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v phyless-data:/data \
ghcr.io/lisaac/phyless:latest或者用 Compose(compose.yaml):
services:
phyless:
image: ghcr.io/lisaac/phyless:latest
container_name: phyless
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- phyless-data:/data
volumes:
phyless-data:docker compose up -d镜像 latest 同时包含 amd64 / arm64 / armv7 / 386,Docker 会按宿主架构自动拉取对应版本,命令无需按架构修改。
或者直接运行二进制(Linux,自动识别架构;其他平台见 Releases):
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/;s/armv7l/armv7/;s/i.86/386/')
curl -fsSL "https://github.com/lisaac/phyless/releases/latest/download/phyless-linux-$ARCH.tar.gz" | tar -xz
sudo ./phyless-linux-$ARCH -C /var/lib/phyless打开 http://<服务器地址>:8080,按提示为 admin 设置密码,完成。
接下来可以:
- 在「容器」页点 创建,粘贴一条
docker run命令即可建容器; - 在「Compose」页新建项目,或选择已有的 Compose YAML 文件注册(容器部署需要先挂载目录,见 管理宿主机上的 Compose 项目);
- 服务器拉不动镜像时,在拉取对话框里选一个代理(见 使用代理拉取镜像)。
- 单个二进制:后端、网页和 Compose 引擎编译进同一个文件,Linux amd64 约 36 MB(压缩包约 15 MB)。容器镜像基于 scratch,里面只有这一个文件,根证书也编译在程序里。
- 无需任何依赖:静态编译,不依赖 glibc 或其他系统库;不需要数据库,账号和配置是数据目录里的普通文件;Compose 通过内嵌的 Go API 执行,宿主机无需安装
docker或docker compose命令。 - 省内存:默认把堆内存软上限设为 128 MB,路由器、NAS、小 VPS 也跑得动(可用
GOMEMLIMIT、GOGC环境变量调整)。 - 部署简单:一条
docker run,或者下载二进制直接运行。
- 每次拉取都可以临时指定代理,不用改 daemon 配置,也不用重启 Docker。
- 服务器完全连不上镜像仓库时,可以改由浏览器经 Cloudflare Worker 下载镜像,再流式导入服务器。
docker run命令和compose.yaml可以互相转换。- 容器可以批量检查有没有新镜像;升级时沿用原配置,失败会自动回滚。Compose 项目一键拉取并更新。
Docker 主机与版本、操作系统和内核、总内存、存储驱动与可用空间,以及容器(运行中 / 总数)、镜像、网络、存储卷数量。
- 列表:状态、端口、镜像、CPU/内存曲线;支持批量启动、停止、重启、删除。
- 生命周期:启动、停止、重启、暂停/恢复、强制结束、重命名、删除。
- 详情:配置(inspect)、实时日志、资源占用、进程列表(top)、网页终端(可在独立窗口打开)。没有 shell 的容器(distroless、scratch)自动进入 busybox 调试模式,不修改目标容器。
- 文件:浏览容器内文件,上传、下载、重命名,在容器之间复制文件。运行中、已停止、没有
ls的容器都能浏览,不会把整个文件系统传回来。详见 docs/file-browsing.md。 - 创建:表单或直接粘贴
docker run命令;可把常用命令保存为模板;随时查看任意容器对应的docker run命令或compose.yaml。 - 复制、导出与导入容器。
- 检查升级 / 升级:单个或批量;显示本地与远端 digest;升级失败自动回滚。详见 docs/container-upgrade.md。
- 管理 phyless 自身容器:升级、Compose 重建等会停掉自己的操作交给一次性的
phyless-helper容器完成;停止、删除、重启自身前先确认,暂停自身被拒绝。详见 docs/self-update.md。
- 新建项目时在当前服务器的 Compose 存储目录(默认
/srv)下创建同名目录;也可选择已有 YAML 文件注册。自动发现存储目录中的项目及正在运行但未注册的项目。 - 查看项目下的服务与容器状态。
- 在线编辑
compose.yaml及项目目录内的其他文件(上传、下载、重命名)。 - 操作:Up、Down、Stop、Restart、Pause、Pull、Build、Update(拉取并重建);输出以流式日志显示在任务抽屉中。
- Build 仅对含
build:的项目显示,浏览器代理模式下会先预拉 Dockerfile 的FROM镜像。详见 docs/compose-build.md。
- 拉取(可选代理)、上传 tar 导入、导出为 tar。
- 打标签 / 删除标签、删除镜像、清理悬空镜像。
- 查看详情、构建历史(history),浏览镜像内文件并下载。
- 网络:创建、删除、查看详情,把容器连入或断开网络。
- 存储卷:创建、删除(带确认)、查看详情,浏览卷内文件。
实时查看 Docker 事件,默认显示最近 1 小时;可按时间范围、事件类型筛选,并按名称 / 动作 / 镜像搜索。
浏览和编辑 phyless 所在环境的配置文件(如 /etc)。容器部署时看到的是容器内的文件系统,不是宿主机。
| 页面 | 作用 |
|---|---|
| Docker 连接 | 管理多个 Docker 主机:本机 socket、unix:///path/to/docker.sock 或 tcp://host:2375,可配置 TLS 证书(CA / Cert / Key),随时切换当前主机。 |
| 用户管理 | 创建账号并分配角色:admin(全部权限)、operator(可执行操作)、viewer(只读)。 |
| 审计日志 | 记录谁在什么时间执行了什么操作。 |
- 所有写操作进入全局任务队列,在右侧任务抽屉查看进度、日志或取消。
- 适配手机浏览器;支持日间 / 夜间主题。
phyless 需要访问 Docker Socket,并把数据(账号、JWT 密钥、配置、审计日志)存放在一个目录里。下面三种方式任选其一。
见 快速开始。镜像基于 Alpine,里面只有 phyless 二进制和 CA 证书;数据保存在 phyless-data 卷的 /data 下。latest 为多架构镜像(amd64 / arm64 / armv7 / 386),docker pull 会按宿主架构自动选择;也可直接指定 latest-amd64、latest-arm64、latest-armv7、latest-386。
升级 phyless:
docker pull ghcr.io/lisaac/phyless:latestdocker rm -f phyless然后重新执行快速开始中的 docker run 命令。phyless-data 卷会保留,账号和配置不会丢失。
常用命令:
docker logs -f phyless # 查看日志
docker restart phyless # 重启,不影响数据
docker rm -f phyless # 删除容器,phyless-data 卷仍保留适合不想多跑一个容器的机器。Releases 提供 Linux amd64 / arm64 / armv7 / 386、macOS arm64、Windows amd64 版本,其他平台请自行构建。以下命令自动识别 Linux 架构。
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/;s/armv7l/armv7/;s/i.86/386/')
curl -fsSL "https://github.com/lisaac/phyless/releases/latest/download/phyless-linux-$ARCH.tar.gz" | tar -xz
sudo install "phyless-linux-$ARCH" /usr/local/bin/phylesssudo phyless -C /var/lib/phyless-C 指定数据目录。运行用户需要能读写 /var/run/docker.sock,也就是 root 或 docker 组成员。直接运行时,phyless 能看到宿主机上的 Compose 目录和 /etc,不需要额外挂载。
作为 systemd 服务常驻:
# /etc/systemd/system/phyless.service
[Unit]
Description=phyless
After=docker.service
Requires=docker.service
[Service]
ExecStart=/usr/local/bin/phyless -C /var/lib/phyless
Restart=on-failure
[Install]
WantedBy=multi-user.targetsudo systemctl enable --now phyless升级时替换 /usr/local/bin/phyless,然后执行 sudo systemctl restart phyless。
在仓库根目录执行:
docker compose up -d --buildcompose.yaml 用本地源码构建镜像,把 ./data 挂载到 /data,把宿主机 /srv 挂载到容器内同一路径,并挂载 Docker Socket。更新代码后重新执行同一条命令即可。data/ 已被 Git 和构建上下文忽略,不要提交。
直接运行二进制时不需要这一步。以容器方式运行时,Docker Socket 只提供 Docker API,不会把宿主机的 Compose 文件带进容器。需要把项目目录以相同的绝对路径挂载进 phyless:
docker run -d \
--name phyless \
--restart unless-stopped \
-p 8080:8080 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v phyless-data:/data \
-v /srv:/srv \
ghcr.io/lisaac/phyless:latestCompose 部署时在 compose.yaml 中加同样的挂载:
services:
phyless:
volumes:
- /srv:/srv然后可在「Compose」页新建项目,生成 /srv/<项目>/compose.yaml,或选择已有 YAML 文件注册。可在「Docker 连接」中修改每台服务器的 Compose 存储目录;容器部署时需要把该目录以相同的绝对路径挂载进 phyless,否则相对路径的 build:、volumes:、env_file 会解析到错误位置。
在「设置 → Docker 连接」添加 tcp://<主机>:2375(或启用 TLS 并填写证书),保存后切换即可。远程主机需要自行开放 Docker API,务必配 TLS 或限定内网访问。
也可以填 unix:///path/to/docker.sock 连接非默认位置的 Socket,例如 rootless Docker 的 unix:///run/user/1000/docker.sock,或经 SSH 转发来的远程 Socket(见 作为客户端使用)。
| 项目 | 默认值 | 说明 |
|---|---|---|
| 端口 | 8080 |
用 -p <宿主端口>:8080 修改对外端口。 |
| 数据目录 | /data |
启动参数 -C <目录> 可修改。 |
| 内存上限 | 128 MB(软上限) | 环境变量 GOMEMLIMIT(如 256MiB)、GOGC 可覆盖。 |
| Docker Socket | /var/run/docker.sock |
管理本机 Docker 必需。 |
公网访问请放在 HTTPS 反向代理之后(见 安全须知)。
phyless 不要求和 Docker 跑在同一台机器上。在自己的电脑(macOS / Windows / Linux 桌面)上运行它,当作本地客户端,通过「设置 → Docker 连接」管理一台或多台远程 Docker 主机,服务器上什么都不用装。
1. 下载并运行
从 Releases 下载对应平台的文件:
| 平台 | 文件 |
|---|---|
| macOS(Apple Silicon) | phyless-darwin-arm64.tar.gz |
| Windows x64 | phyless-windows-amd64.zip |
| Linux x64 / arm64 / armv7 / x86 | phyless-linux-amd64.tar.gz / phyless-linux-arm64.tar.gz / phyless-linux-armv7.tar.gz / phyless-linux-386.tar.gz |
macOS:
curl -fsSL https://github.com/lisaac/phyless/releases/latest/download/phyless-darwin-arm64.tar.gz | tar -xzxattr -d com.apple.quarantine phyless-darwin-arm64 2>/dev/null; ./phyless-darwin-arm64 -C ~/.phylessWindows(PowerShell,解压 zip 后):
.\phyless-windows-amd64.exe -C $env:USERPROFILE\.phyless然后在浏览器打开 http://localhost:8080,按提示设置 admin 密码。
phyless 监听所有网卡的 8080 端口,同一局域网的机器也能访问。在不可信网络中请用防火墙限制,或只在需要时运行。
2. 连接 Docker
在「设置 → Docker 连接」添加服务器,地址三选一:
| 地址 | 场景 |
|---|---|
| 留空 | 本机的 Docker Desktop / OrbStack / Colima 等(读取 DOCKER_HOST 或默认 Socket) |
unix:///path/to/docker.sock |
指定本机 Socket,如 Colima 的 unix:///Users/<你>/.colima/default/docker.sock;也可以是 SSH 转发来的远程 Socket(macOS / Linux) |
tcp://<主机>:2376 + TLS |
远程主机开放了 Docker API(建议配 TLS 证书) |
通过 SSH 连接远程主机(远程无需开放 Docker API 端口,macOS / Linux):把远程 Socket 转发成本地文件
ssh -nNT -L /tmp/docker-myserver.sock:/var/run/docker.sock user@myserver然后添加 unix:///tmp/docker-myserver.sock。SSH 用户需要能访问远程的 Docker Socket(root 或 docker 组)。重新建立转发前先删除旧的 /tmp/docker-myserver.sock。
添加多台服务器后,在列表中随时切换。
客户端模式下,「Compose」页注册项目、编辑 compose.yaml 和「本机配置」操作的是运行 phyless 的这台电脑上的文件,而不是远程主机;Compose 的 build: 上下文也从本机读取。容器、镜像、网络、存储卷等则都在远程 Docker 上。
代理只对当前这次操作生效。镜像拉取、Compose 的 Pull / Up / Build / Update、容器升级与检查升级的对话框里都能选择:
| 方式 | 适用场景 | 要求 |
|---|---|---|
| 服务端代理 | 服务器能访问某个代理 | HTTP / HTTPS / SOCKS5 地址,需能从 phyless 容器内访问 |
| 浏览器代理导入 | 服务器完全连不上镜像仓库 | 部署一个 Cloudflare Worker |
1. 部署 Worker
Worker 源码是 cloudflare-worker/registry-proxy.js,二选一:
-
控制台:打开 Cloudflare 创建 Worker,选择 Create Worker → Deploy,把脚本完整粘贴进编辑器后再次部署。参考 Dashboard 部署文档。
-
命令行(需要 Node.js):在仓库根目录执行
npx wrangler login
npx wrangler deploy cloudflare-worker/registry-proxy.js --name phyless-registry-proxy --compatibility-date 2024-11-01
部署后在 Worker 概览页复制地址 https://<name>.<subdomain>.workers.dev。
2. 配置白名单
在 Worker 的 Settings → Variables and Secrets 添加变量并重新部署:
| 变量 | 示例 | 作用 |
|---|---|---|
ALLOWED_ORIGINS |
https://phyless.example.com |
允许调用 Worker 的 phyless 网址,多个用逗号分隔;不带路径和结尾 /。 |
UPSTREAM_ALLOWLIST |
见下 | 允许访问的镜像仓库域名,按实际使用收紧。 |
ALLOW_ANY_UPSTREAMS |
false |
是否允许任意上游,生产环境保持 false。 |
ALLOW_MISSING_ORIGIN |
false |
是否接受无 Origin 的请求,保持 false。 |
UPSTREAM_ALLOWLIST 常用取值:
# Docker Hub + GHCR
registry-1.docker.io,auth.docker.io,hub.docker.com,*.docker.io,*.docker.com,ghcr.io,lscr.io,*.githubusercontent.com
# 仅 Docker Hub
registry-1.docker.io,auth.docker.io,hub.docker.com,*.docker.io,*.docker.com
# 仅 GHCR
ghcr.io,lscr.io,*.githubusercontent.com
Quay、GCR、registry.k8s.io、MCR、ECR Public、GitLab 等其他仓库的镜像层会重定向到各自的 CDN 域名,取值见 cloudflare-worker/README.md。
完整变量说明见 cloudflare-worker/README.md。
3. 在 phyless 中使用
- 打开任一拉取 / 升级对话框,选择 浏览器代理导入;
- 填入 Worker 地址,如
https://phyless-registry-proxy.example.workers.dev(无需手动拼?url=); - 在「前端代理仓库账号」中按 registry 选用账号:可以是只存在当前浏览器的账号,也可以是 phyless 服务端保存的账号(选用时临时取用、不写入浏览器)。每个镜像只会使用其所在 registry 选中的账号;“记住凭据”只把浏览器账号存在当前浏览器的 localStorage。
- 拉取对话框点「搜索远程镜像」可搜索 Docker Hub,或输入完整仓库名(如
ghcr.io/owner/app)查看标签。搜索与拉取方式一致:「不使用代理」由 phyless 服务端直接访问,「服务端代理」经所选代理访问,「浏览器代理导入」经 Worker 访问并使用docker.io账号登录。Worker 出口 IP 为共享 IP,Docker Hub API 按 IP 限额,频繁 429 时建议改用服务端方式;标签查询遇到 429 会自动改用 registry 接口(仅标签名)。 - 仓库账号直接在拉取对话框里管理,按 registry 分组、每组单选一个账号(或匿名):「不使用代理 / 服务端代理」下是服务端仓库账号(加密保存在 phyless 服务端、所有用户共享),「浏览器代理导入」下是前端代理仓库账号。两者都可一键验证,验证走与拉取相同的网络路径。
- 「平台」默认即 Docker daemon 所在平台(含 ARM 变体,如
linux/arm/v7),与docker pull的自动选择一致;手动指定时两种代理都严格按指定平台拉取。GHCR 等非 Docker Hub 仓库的标签会读取 manifest 补全更新时间、大小、架构和仓库描述。
限制:只支持 Linux 平台的 tag 镜像,不支持 digest 引用和 foreign layer;Compose Build 只预拉 Dockerfile 中能静态解析的 FROM 镜像。Worker 只处理 GET / HEAD / OPTIONS 和发往白名单上游的小 POST(registry API 登录),不保存镜像内容。详细设计见 docs/pull-and-registry-accounts.md。搜索需白名单包含 hub.docker.com;添加 docker.io 账号后由 phyless 服务端登录换取 JWT(服务端连不上 Hub 时改经 Worker),搜索按账号额度进行。
需要 Go(版本见 go.mod)和 Node.js。
./build.sh # 构建前端并嵌入,产出 ./phyless./phyless -C ./data # 启动后端,监听 :8080cd frontend && npm install && npm run dev # 前端热更新,/api 代理到 localhost:8080测试:go test ./...、cd frontend && npm test。
- 挂载 Docker Socket 等同于授予宿主机 root 级权限,只向可信用户开放。
- 公网访问务必放在 HTTPS 反向代理之后。
/data(phyless-data卷或./data)保存 JWT 密钥、账号和审计日志:定期备份,不要公开或提交到 Git。- 给日常使用者分配 operator 或 viewer 角色,admin 只留给管理者。
本项目基于 MIT License 发布。
phyless 内嵌了 BusyBox 1.37.0 的静态可执行文件(来自 Alpine busybox-static 1.37.0-r31,amd64 / arm64 / arm / 386),只在 phyless 创建的辅助容器里运行,用于无 shell 终端和文件浏览,不与 phyless 链接。BusyBox 以 GPL-2.0-only 授权,不影响 phyless 本身的 MIT 许可证。来源、校验值和对应源码见 busybox-NOTICE.md:每个 Release 都附带上游源码包和 Alpine 的构建脚本,发布包和容器镜像的 licenses/ 目录里都有许可证文本。