10 Commits

Author SHA1 Message Date
Nick007
a5f832dd09 feat: automate upstream wechat version detection 2026-04-07 17:35:47 +08:00
Nick007
77edc4b33e fix: add curl retry for WeChat/QQ download to handle transient network failures 2026-03-23 21:06:24 +08:00
Nick007
680ee6dd4a feat: support minimal image variant with WeChat only (#92)
Add INSTALL_QQ and INSTALL_PCMANFM build args to conditionally skip QQ
and file manager installation. CI builds both :latest (full) and :minimal
(WeChat only) tags for each release.
2026-03-23 19:54:35 +08:00
Nick007
63b3f34527 feat: extract docker-compose config to .env and update commands to docker compose 2026-03-23 19:39:28 +08:00
Nick007
c2b6106fff docs: add WeChat/QQ version update guide and file manager feature docs (#100) 2026-03-23 18:56:51 +08:00
Nick007
e42a8e861d feat: add PCManFM file manager with right-click menu entry (#86) 2026-03-23 18:56:44 +08:00
Nick007
d87cb16fb9 feat: open WeChat/QQ as normal windows instead of maximized (#69) 2026-03-23 18:55:55 +08:00
Nick007
7c13e87a69 fix: clean up stale dbus pid file on startup (#81) 2026-03-23 18:55:36 +08:00
Nick007
ecc68281c3 fix: use start scripts instead of restart in menu to support multi-instance (#102) 2026-03-23 14:00:27 +08:00
Nick007
6d039cf06e docs: add AGENTS.md project knowledge base 2026-03-23 13:52:38 +08:00
14 changed files with 550 additions and 79 deletions

14
.env.example Normal file
View File

@@ -0,0 +1,14 @@
# Ports
HTTP_PORT=3000
HTTPS_PORT=3001
# User/Group
PUID=1000
PGID=100
# Selkies Web UI
# CUSTOM_USER=
# PASSWORD=
# Shared Memory
SHM_SIZE=1gb

125
.github/scripts/detect-upstream.sh vendored Executable file
View File

@@ -0,0 +1,125 @@
#!/usr/bin/env bash
set -euo pipefail
STATE_FILE="${STATE_FILE:-versions/upstream.env}"
TMP_DIR="$(mktemp -d)"
CHANGE_DETECTED="false"
ENV_WECHAT_AMD64_URL="${WECHAT_AMD64_URL-__UNSET__}"
ENV_WECHAT_ARM64_URL="${WECHAT_ARM64_URL-__UNSET__}"
cleanup() {
rm -rf "$TMP_DIR"
}
trap cleanup EXIT
if [[ -f "$STATE_FILE" ]]; then
# shellcheck disable=SC1090
source "$STATE_FILE"
fi
if [[ "$ENV_WECHAT_AMD64_URL" != "__UNSET__" ]]; then
WECHAT_AMD64_URL="$ENV_WECHAT_AMD64_URL"
fi
if [[ "$ENV_WECHAT_ARM64_URL" != "__UNSET__" ]]; then
WECHAT_ARM64_URL="$ENV_WECHAT_ARM64_URL"
fi
WECHAT_AMD64_URL="${WECHAT_AMD64_URL:-https://dldir1v6.qq.com/weixin/Universal/Linux/WeChatLinux_x86_64.deb}"
WECHAT_ARM64_URL="${WECHAT_ARM64_URL:-https://dldir1v6.qq.com/weixin/Universal/Linux/WeChatLinux_arm64.deb}"
download_package() {
local source_path="$1"
local destination="$2"
case "$source_path" in
http://*|https://*)
curl --fail --silent --show-error --location \
--retry 3 --retry-delay 5 --retry-all-errors \
-o "$destination" "$source_path"
;;
*)
cp "$source_path" "$destination"
;;
esac
}
read_metadata() {
local package_name="$1"
local arch="$2"
local source_path="$3"
local package_path="$TMP_DIR/${package_name}-${arch}.deb"
local version_var="${package_name}_${arch}_VERSION"
local sha_var="${package_name}_${arch}_SHA256"
local current_version="${!version_var:-}"
local current_sha="${!sha_var:-}"
local detected_version
local detected_sha
echo "Checking ${package_name} ${arch} from ${source_path}"
download_package "$source_path" "$package_path"
detected_version="$(dpkg-deb -f "$package_path" Version)"
detected_sha="$(sha256sum "$package_path" | awk '{print $1}')"
printf -v "$version_var" '%s' "$detected_version"
printf -v "$sha_var" '%s' "$detected_sha"
if [[ "$current_version" != "$detected_version" || "$current_sha" != "$detected_sha" ]]; then
CHANGE_DETECTED="true"
fi
}
read_metadata "WECHAT" "AMD64" "$WECHAT_AMD64_URL"
read_metadata "WECHAT" "ARM64" "$WECHAT_ARM64_URL"
if [[ "$CHANGE_DETECTED" == "true" || ! -f "$STATE_FILE" ]]; then
WECHAT_LAST_CHECKED_AT="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
fi
NEW_STATE_FILE="$TMP_DIR/upstream.env"
cat > "$NEW_STATE_FILE" <<EOF
# Upstream package state tracked by automation.
WECHAT_AMD64_URL="$WECHAT_AMD64_URL"
WECHAT_ARM64_URL="$WECHAT_ARM64_URL"
WECHAT_AMD64_VERSION="$WECHAT_AMD64_VERSION"
WECHAT_ARM64_VERSION="$WECHAT_ARM64_VERSION"
WECHAT_AMD64_SHA256="$WECHAT_AMD64_SHA256"
WECHAT_ARM64_SHA256="$WECHAT_ARM64_SHA256"
WECHAT_LAST_CHECKED_AT="$WECHAT_LAST_CHECKED_AT"
EOF
mkdir -p "$(dirname "$STATE_FILE")"
if [[ ! -f "$STATE_FILE" ]] || ! cmp -s "$NEW_STATE_FILE" "$STATE_FILE"; then
cp "$NEW_STATE_FILE" "$STATE_FILE"
fi
echo "Change detected: $CHANGE_DETECTED"
echo "WECHAT_AMD64_VERSION=$WECHAT_AMD64_VERSION"
echo "WECHAT_ARM64_VERSION=$WECHAT_ARM64_VERSION"
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
{
echo "changed=$CHANGE_DETECTED"
echo "wechat_amd64_version=$WECHAT_AMD64_VERSION"
echo "wechat_arm64_version=$WECHAT_ARM64_VERSION"
echo "state_file=$STATE_FILE"
} >> "$GITHUB_OUTPUT"
fi
if [[ -n "${GITHUB_STEP_SUMMARY:-}" ]]; then
{
echo "## Upstream Detection"
echo ""
echo "- Changed: \`$CHANGE_DETECTED\`"
echo "- WeChat amd64: \`$WECHAT_AMD64_VERSION\`"
echo "- WeChat arm64: \`$WECHAT_ARM64_VERSION\`"
echo "- State file: \`$STATE_FILE\`"
} >> "$GITHUB_STEP_SUMMARY"
fi

32
.github/workflows/detect-upstream.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: Detect Upstream Package Updates
on:
workflow_dispatch:
schedule:
- cron: '23 */6 * * *'
permissions:
contents: write
jobs:
detect-wechat-updates:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Detect upstream package changes
id: detect
run: ./.github/scripts/detect-upstream.sh
- name: Commit updated version state
if: steps.detect.outputs.changed == 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add versions/upstream.env
git commit -m "chore: update upstream package state"
git push

View File

@@ -3,6 +3,10 @@ name: Build and Publish Docker Image
on:
workflow_dispatch:
push:
branches:
- master
paths:
- 'versions/upstream.env'
tags:
- 'v*'
@@ -70,6 +74,37 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Extract metadata for minimal image
id: meta-minimal
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/${{ github.repository }}
${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }},enable=${{ vars.ENABLE_DOCKERHUB == 'true' }}
flavor: |
latest=false
suffix=-minimal
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=raw,value=minimal,enable=${{ github.ref == format('refs/heads/{0}', 'master') || startsWith(github.ref, 'refs/tags/') }}
- name: Build and push minimal Docker image
id: build-minimal
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta-minimal.outputs.tags }}
labels: ${{ steps.meta-minimal.outputs.labels }}
build-args: |
INSTALL_QQ=false
INSTALL_PCMANFM=false
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Generate artifact attestation
if: github.event_name != 'workflow_dispatch'
uses: actions/attest-build-provenance@v1
@@ -84,11 +119,16 @@ jobs:
echo "### GitHub Container Registry" >> $GITHUB_STEP_SUMMARY
echo "**Registry:** ${{ env.REGISTRY }}" >> $GITHUB_STEP_SUMMARY
echo "**Repository:** ${{ env.IMAGE_NAME }}" >> $GITHUB_STEP_SUMMARY
echo "**Digest:** \`${{ steps.build-image.outputs.digest }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Tags:**" >> $GITHUB_STEP_SUMMARY
echo "**Full image digest:** \`${{ steps.build-image.outputs.digest }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Minimal image digest:** \`${{ steps.build-minimal.outputs.digest }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Tags (full):**" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "**Tags (minimal):**" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "${{ steps.meta-minimal.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
if [ "${{ vars.ENABLE_DOCKERHUB }}" == "true" ]; then
echo "" >> $GITHUB_STEP_SUMMARY
@@ -115,6 +155,7 @@ jobs:
body: |
## 🐳 Docker Images
### Full (WeChat + QQ + File Manager)
**GitHub Container Registry:**
```bash
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}
@@ -127,17 +168,20 @@ jobs:
docker pull ${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:latest
```
## 🚀 Quick Start
**GitHub Container Registry:**
### Minimal (WeChat only)
```bash
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:minimal
```
## 🚀 Quick Start
**Full:**
```bash
docker run -it -p 3001:3001 -v ./config:/config --device /dev/dri:/dev/dri ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}
docker run -it -p 3001:3001 -v ./config:/config --device /dev/dri:/dev/dri ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
```
**Docker Hub** (if enabled):
**Minimal:**
```bash
docker run -it -p 3001:3001 -v ./config:/config --device /dev/dri:/dev/dri ${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:${{ steps.meta.outputs.version }}
docker run -it -p 3001:3001 -v ./config:/config --device /dev/dri:/dev/dri ${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:latest
docker run -it -p 3001:3001 -v ./config:/config --device /dev/dri:/dev/dri ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:minimal
```
Then visit: https://localhost:3001
Then visit: https://localhost:3001

3
.gitignore vendored
View File

@@ -1 +1,2 @@
/config/
/config/
.env

94
AGENTS.md Normal file
View File

@@ -0,0 +1,94 @@
# PROJECT KNOWLEDGE BASE
**Generated:** 2026-03-23
**Commit:** e18821f
**Branch:** master
## OVERVIEW
Docker 容器化微信/QQ Linux 客户端,基于 LinuxServer Selkies WebRTC 基础镜像,通过浏览器远程访问桌面应用。支持 AMD64/ARM64 双架构。
## STRUCTURE
```
wechat-selkies/
├── Dockerfile # 单阶段构建,基于 selkies:ubuntunoble
├── docker-compose.yml # 单服务编排
├── root/ # COPY /root / → 容器内脚本和配置
│ ├── defaults/
│ │ ├── autostart # 容器启动入口,仅一行: /scripts/start.sh
│ │ └── menu.xml # Openbox 右键菜单模板(静态基础项)
│ └── scripts/
│ ├── start.sh # 主启动脚本openbox配置 → 菜单刷新 → 监听桌面 → 启动应用
│ ├── refresh-menu.sh # 合并 menu.xml + ~/Desktop/*.desktop → 生成最终菜单
│ ├── window_switcher.py # ⚠️ 已废弃,仅保留
│ ├── wechat/ # wechat-start.sh / wechat-restart.sh / wechat-unminimize.sh
│ └── qq/ # qq-restart.sh
├── .github/workflows/ # CI: 多架构构建 + Issue 自动化
├── docs/images/ # README 截图
└── config/ # ⚠️ gitignored 运行时数据挂载点
```
## WHERE TO LOOK
| 任务 | 位置 | 备注 |
|------|------|------|
| 添加新应用 | `Dockerfile` (安装) + `root/defaults/menu.xml` (菜单) | 参考 QQ 安装段落的 case 模式 |
| 修改启动行为 | `root/scripts/start.sh` | 入口脚本,由 `root/defaults/autostart` 触发 |
| 修改右键菜单 | `root/defaults/menu.xml` + `root/scripts/refresh-menu.sh` | menu.xml 是模板refresh-menu.sh 动态合并 ~/Desktop/*.desktop |
| 修改菜单动态生成逻辑 | `root/scripts/refresh-menu.sh` | 解析 .desktop 文件的 Name/Exec/Icon 字段,处理图标搜索 |
| 添加新应用启动/重启脚本 | `root/scripts/<app>/` | 遵循 wechat/ 目录模式: start.sh + restart.sh |
| 修改环境变量 | `Dockerfile` (ENV) + `docker-compose.yml` (environment) | 两处需同步 |
| CI/CD | `.github/workflows/docker.yml` | tag v* 触发,多架构 buildx可选推送 Docker Hub |
| Issue 自动化 | `.github/workflows/issue-validation.yml` + `cleanup-issues.yml` | 标题/描述校验 + 7天自动关闭 |
## CONVENTIONS
- **语言**: 脚本用 Bash (#!/bin/bash),窗口切换器用 Python3 + Xlib + tkinter
- **容器路径约定**: `COPY /root /``root/` 目录内容映射到容器根 `/`,因此 `root/scripts/start.sh` → 容器内 `/scripts/start.sh`
- **自启动机制**: Selkies 基础镜像读取 `/defaults/autostart` 文件执行启动脚本
- **菜单刷新**: inotifywait 监听 `~/Desktop/` 变更自动刷新 Openbox 菜单
- **进程管理**: 应用通过 `nohup ... &` 后台启动restart 脚本先 `pkill -9` 再启动
- **restart 脚本模式**: `pkill -9 -f /usr/bin/<app>``nohup /usr/bin/<app> >/dev/null 2>&1 &`QQ 需额外 `--no-sandbox`
- **菜单模板 vs 运行时**: `root/defaults/menu.xml` 是源码模板,`/config/.config/openbox/menu.xml` 是运行时生成的,不要混淆
- **refresh-menu.sh**: 仅在内容变更时才写入 + reconfigure避免无意义刷新
- **图标搜索优先级**: proot-apps icons (256→512→128→64→48→scalable) → system icons → fallback xterm icon
- **多架构**: Dockerfile 使用 `$TARGETPLATFORM` 条件分支安装不同架构 deb 包
## ANTI-PATTERNS (THIS PROJECT)
- **不要直接修改 `config/` 目录下的文件** — 这是运行时挂载数据gitignored
- **不要修改 `config/.config/openbox/` 下文件作为"源码"** — 这些由 `root/defaults/` 模板生成
- **不要在 `root/` 下放非容器必需文件** — `COPY /root /` 会将所有内容复制到容器根目录
- **不要在 menu.xml 中添加 .desktop 动态条目** — 由 refresh-menu.sh 自动处理
- **不要在 start.sh 中用 `exec` 替代 `nohup ... &`** — 需要多进程并行运行
- **升级后功能缺失** → 清空 `./config/.config/openbox/` 目录(已知 gotcha见 README
- **window_switcher.py 已废弃** — `start.sh` 中已注释掉,但文件保留,不要删除
## COMMANDS
```bash
# 本地构建并启动
docker-compose up -d --build
# 仅启动(使用已有镜像)
docker-compose up -d
# 查看日志
docker-compose logs -f wechat-selkies
# 进入容器调试
docker exec -it wechat-selkies bash
# 清理升级问题
rm -rf ./config/.config/openbox
```
## NOTES
- 端口 3000=HTTP, 3001=HTTPS推荐 HTTPS
- `shm_size: "1gb"` 影响 WebRTC 性能,建议保留
- `/dev/dri` 映射为可选 GPU 加速
- `AUTO_START_WECHAT` / `AUTO_START_QQ` 控制容器启动时是否自动拉起应用
- 第三方应用通过 proot-apps 安装,快捷方式自动出现在右键菜单
- Docker Hub 推送需在 GitHub 仓库 Environment 中配置 `ENABLE_DOCKERHUB=true`

View File

@@ -13,9 +13,10 @@ LABEL org.opencontainers.image.licenses="GPL-3.0-only"
# Build arguments for multi-arch support
ARG TARGETPLATFORM
ARG BUILDPLATFORM
ARG INSTALL_QQ=true
ARG INSTALL_PCMANFM=true
RUN echo "🏗️ Building WeChat-Selkies on $BUILDPLATFORM, targeting $TARGETPLATFORM"
# set environment variables
RUN apt-get update && \
apt-get install -y fonts-noto-cjk libxcb-icccm4 libxcb-image0 libxcb-keysyms1 \
libxcb-render-util0 libxcb-xkb1 libxkbcommon-x11-0 \
@@ -27,7 +28,12 @@ RUN apt-get update && \
libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 \
libxcomposite1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 \
libxss1 libxtst6 libatomic1 libxcomposite1 libxrender1 libxrandr2 libxkbcommon-x11-0 \
libfontconfig1 libdbus-1-3 libnss3 libx11-xcb1 python3-tk stalonetray inotify-tools
libfontconfig1 libdbus-1-3 libnss3 libx11-xcb1 stalonetray inotify-tools
ARG INSTALL_PCMANFM
RUN if [ "$INSTALL_PCMANFM" = "true" ]; then \
apt-get install -y --no-install-recommends pcmanfm; \
fi
RUN pip install --no-cache-dir python-xlib
@@ -45,31 +51,35 @@ RUN case "$TARGETPLATFORM" in \
exit 1 ;; \
esac && \
echo "📦 Downloading WeChat for $WECHAT_ARCH architecture..." && \
curl -fsSL -o wechat.deb "$WECHAT_URL" && \
curl -fsSL --retry 3 --retry-delay 10 --retry-all-errors -o wechat.deb "$WECHAT_URL" && \
echo "🔧 Installing WeChat..." && \
(dpkg -i wechat.deb || (apt-get update && apt-get install -f -y && dpkg -i wechat.deb)) && \
rm -f wechat.deb && \
echo "✅ WeChat installation completed for $WECHAT_ARCH"
# Install QQ based on target architecture
RUN case "$TARGETPLATFORM" in \
"linux/amd64") \
QQ_URL="https://dldir1v6.qq.com/qqfile/qq/QQNT/Linux/QQ_3.2.22_251203_amd64_01.deb"; \
QQ_ARCH="x86_64" ;; \
"linux/arm64") \
QQ_URL="https://dldir1v6.qq.com/qqfile/qq/QQNT/Linux/QQ_3.2.22_251203_arm64_01.deb"; \
QQ_ARCH="arm64" ;; \
*) \
echo "❌ Unsupported platform: $TARGETPLATFORM" >&2; \
echo "Supported platforms: linux/amd64, linux/arm64" >&2; \
exit 1 ;; \
esac && \
echo "📦 Downloading QQ for $QQ_ARCH architecture..." && \
curl -fsSL -o qq.deb "$QQ_URL" && \
echo "🔧 Installing QQ..." && \
(dpkg -i qq.deb || (apt-get update && apt-get install -f -y && dpkg -i qq.deb)) && \
rm -f qq.deb && \
echo "✅ QQ installation completed for $QQ_ARCH"
# Install QQ based on target architecture (optional)
ARG INSTALL_QQ
RUN if [ "$INSTALL_QQ" = "true" ]; then \
case "$TARGETPLATFORM" in \
"linux/amd64") \
QQ_URL="https://dldir1v6.qq.com/qqfile/qq/QQNT/Linux/QQ_3.2.22_251203_amd64_01.deb"; \
QQ_ARCH="x86_64" ;; \
"linux/arm64") \
QQ_URL="https://dldir1v6.qq.com/qqfile/qq/QQNT/Linux/QQ_3.2.22_251203_arm64_01.deb"; \
QQ_ARCH="arm64" ;; \
*) \
echo "❌ Unsupported platform: $TARGETPLATFORM" >&2; \
exit 1 ;; \
esac && \
echo "📦 Downloading QQ for $QQ_ARCH architecture..." && \
curl -fsSL --retry 3 --retry-delay 10 --retry-all-errors -o qq.deb "$QQ_URL" && \
echo "🔧 Installing QQ..." && \
(dpkg -i qq.deb || (apt-get update && apt-get install -f -y && dpkg -i qq.deb)) && \
rm -f qq.deb && \
echo "✅ QQ installation completed for $QQ_ARCH"; \
else \
echo "⏭️ Skipping QQ installation (INSTALL_QQ=$INSTALL_QQ)"; \
fi
# Clean up
RUN apt-get purge -y --autoremove

View File

@@ -22,6 +22,8 @@
> 如果升级后部分功能缺失请先清空本地挂载目录下的openbox目录(如`./config/.config/openbox`)。
> 仓库内置了上游微信版本自动检测机制GitHub Actions 会定时检查官方 `.deb` 包版本,检测到变化后自动更新 `versions/upstream.env` 并触发镜像构建。
## 功能特性
- 🌐 **浏览器访问**:通过 Web 浏览器直接使用微信,无需本地安装
@@ -35,6 +37,7 @@
- 🪟 **窗口切换器**:左上角增加切换悬浮窗,方便切换到后台窗口,为后续添加其它功能做基础
- 🤖 **自动启动**可配置自动启动微信和QQ客户端可选
- 📋 **桌面快捷方式集成**:自动扫描 `~/Desktop/` 下的 `.desktop` 文件并添加到右键菜单,方便启动第三方应用(如通过 proot-apps 安装的应用)
- 📂 **文件管理器**:内置 PCManFM 轻量文件管理器,右键菜单即可启动,方便管理容器内文件
## 截图展示
![微信截图](./docs/images/wechat-selkies-1.jpg)
@@ -62,12 +65,18 @@ Docker Hub镜像
docker run -it -p 3001:3001 -v ./config:/config --device /dev/dri:/dev/dri nickrunning/wechat-selkies:latest
```
> **精简版镜像**:如果只需要微信(不含 QQ 和文件管理器),可使用 `minimal` 标签,镜像体积更小:
> ```bash
> docker run -it -p 3001:3001 -v ./config:/config --device /dev/dri:/dev/dri ghcr.io/nickrunning/wechat-selkies:minimal
> ```
> 精简版也支持版本号标签,如 `:1.2.3-minimal`、`:1.2-minimal`,方便锁定特定版本。
2. **访问微信**
在浏览器中访问:`https://localhost:3001``https://<服务器IP>:3001`
> **注意:** 映射3000端口用于HTTP访问3001端口用于HTTPS访问建议使用HTTPS。
### docker-compose 部署
### Docker Compose 部署
1. **创建项目目录并进入**
```bash
mkdir wechat-selkies
@@ -80,27 +89,43 @@ docker run -it -p 3001:3001 -v ./config:/config --device /dev/dri:/dev/dri nickr
image: nickrunning/wechat-selkies:latest # or ghcr.io/nickrunning/wechat-selkies:latest
container_name: wechat-selkies
ports:
- "3000:3000" # http port
- "3001:3001" # https port
- "${HTTP_PORT:-3000}:3000"
- "${HTTPS_PORT:-3001}:3001"
restart: unless-stopped
volumes:
- ./config:/config
devices:
- /dev/dri:/dev/dri # optional, for hardware acceleration
- /dev/dri:/dev/dri
environment:
- PUID=1000 # user ID, set according to your system
- PGID=100 # group ID, set according to your system
- TZ=Asia/Shanghai # timezone, set according to your timezone
- LC_ALL=zh_CN.UTF-8 # locale, set according to your needs
- AUTO_START_WECHAT=true # default is true
- AUTO_START_QQ=false # default is false
# - CUSTOM_USER=<Your Name> # recommended to set a custom user name
# - PASSWORD=<Your Password> # recommended to set a password for selkies web ui
shm_size: "1gb" # recommended, will improve performance
- PUID=${PUID:-1000}
- PGID=${PGID:-100}
- TZ=Asia/Shanghai
- LC_ALL=zh_CN.UTF-8
- AUTO_START_WECHAT=true
- AUTO_START_QQ=false
- CUSTOM_USER=${CUSTOM_USER:-}
- PASSWORD=${PASSWORD:-}
shm_size: "${SHM_SIZE:-1gb}"
```
3. **启动服务**
3. **创建 `.env` 文件(可选)**
复制 `.env.example` 并按需修改,未设置的变量将使用默认值:
```bash
docker-compose up -d
cp .env.example .env
```
`.env` 文件示例:
```env
HTTP_PORT=3000
HTTPS_PORT=3001
PUID=1000
PGID=100
# CUSTOM_USER=
# PASSWORD=
SHM_SIZE=1gb
```
4. **启动服务**
```bash
docker compose up -d
```
### 源码部署
@@ -113,13 +138,18 @@ docker run -it -p 3001:3001 -v ./config:/config --device /dev/dri:/dev/dri nickr
2. **启动服务**
```bash
docker-compose up -d
docker compose up -d
```
3. **访问微信**
在浏览器中访问:`https://localhost:3001` 或 `https://<服务器IP>:3001`
> **构建精简版**:源码部署时可通过 build-arg 构建仅含微信的精简镜像:
> ```bash
> docker build --build-arg INSTALL_QQ=false --build-arg INSTALL_PCMANFM=false -t wechat-selkies:minimal .
> ```
### 配置说明
更多自定义配置请参考 [Selkies Base Images from LinuxServer](https://github.com/linuxserver/docker-baseimage-selkies)。
@@ -136,7 +166,7 @@ docker run -it -p 3001:3001 -v ./config:/config --device /dev/dri:/dev/dri nickr
#### 环境变量配置
在 `docker-compose.yml` 中可以配置以下环境变量:
在 `docker-compose.yml` 中可以配置以下环境变量,支持通过 `.env` 文件覆盖带有 `${VAR:-default}` 的配置项
| 变量名 | 默认值 | 说明 |
|--------|--------|------|
@@ -189,6 +219,7 @@ devices:
```
wechat-selkies/
├── docker-compose.yml # Docker Compose 配置文件
├── .env.example # 环境变量示例文件
├── Dockerfile # Docker 镜像构建文件
├── LICENSE # License
├── README.md # 项目说明文档
@@ -201,6 +232,33 @@ wechat-selkies/
## 故障排除
### 更新微信/QQ版本
当微信或QQ提示"版本过期"时,只需重新拉取最新镜像并重建容器即可,聊天记录和配置不受影响:
```bash
# 使用预构建镜像
docker compose pull && docker compose up -d
# 使用源码构建
git pull && docker compose up -d --build
```
> **注意:** 微信和QQ的安装包 URL 指向官方最新版本,重新构建镜像时会自动下载最新版。
对于仓库维护者,当前自动化流程如下:
1. `Detect Upstream Package Updates` 每 6 小时检查一次微信官方安装包版本,也支持手动触发
2. 如果检测到版本号或安装包哈希变化,工作流会更新 `versions/upstream.env`
3. 该文件变更提交到 `master` 后,会自动触发 `Build and Publish Docker Image`
版本状态文件位于 `versions/upstream.env`,当前记录了:
- 微信 amd64/arm64 下载地址
- 微信 amd64/arm64 解析出的版本号
- 微信 amd64/arm64 安装包 SHA256
- 最近一次发生变更的检测时间
### 常见问题
1. **无法访问 Web UI**
@@ -211,7 +269,7 @@ wechat-selkies/
查看容器运行日志:
```bash
docker-compose logs -f wechat-selkies
docker compose logs -f wechat-selkies
```
## 技术架构
@@ -278,4 +336,4 @@ docker-compose logs -f wechat-selkies
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=nickrunning/wechat-selkies&type=Date)](https://www.star-history.com/#nickrunning/wechat-selkies&Date)
[![Star History Chart](https://api.star-history.com/svg?repos=nickrunning/wechat-selkies&type=Date)](https://www.star-history.com/#nickrunning/wechat-selkies&Date)

View File

@@ -22,6 +22,8 @@ This project packages the official WeChat/QQ Linux client in a Docker container,
> If some features are missing after an upgrade, please clear the `openbox` directory in the local mounted directory (e.g., `./config/.config/openbox`).
> This repository includes automatic upstream WeChat version detection: GitHub Actions periodically checks the official `.deb` packages, updates `versions/upstream.env` when changes are detected, and then triggers the image build workflow.
## Features
- 🌐 **Browser Access**: Use WeChat directly through web browsers without local installation
@@ -35,6 +37,7 @@ This project packages the official WeChat/QQ Linux client in a Docker container,
- 🪟 **Window Switcher**: Added a floating window switcher in the top left corner for easy switching to background windows, laying the foundation for adding other features in the future
- 🤖 **Auto Start**: Configurable auto-start for WeChat and QQ clients (optional)
- 📋 **Desktop Shortcut Integration**: Automatically scans `.desktop` files in `~/Desktop/` and adds them to the right-click menu, making it easy to launch third-party applications (e.g., apps installed via proot-apps)
- 📂 **File Manager**: Built-in PCManFM lightweight file manager, accessible from the right-click menu for easy file management inside the container
## Screenshots
![WeChat Screenshot](./docs/images/wechat-selkies-1.jpg)
@@ -60,12 +63,18 @@ Docker Hub image:
docker run -it -p 3001:3001 -v ./config:/config --device /dev/dri:/dev/dri nickrunning/wechat-selkies:latest
```
> **Minimal image**: If you only need WeChat (without QQ and file manager), use the `minimal` tag for a smaller image:
> ```bash
> docker run -it -p 3001:3001 -v ./config:/config --device /dev/dri:/dev/dri ghcr.io/nickrunning/wechat-selkies:minimal
> ```
> Versioned minimal tags are also available, e.g. `:1.2.3-minimal`, `:1.2-minimal`, for pinning to a specific release.
2. **Access WeChat**
Open in browser: `https://localhost:3001` or `https://<server-ip>:3001`
> **Note**: 3001 port is for HTTPS access. If you need HTTP access, please map port 3000 as well.
### docker-compose Deployment
### Docker Compose Deployment
1. **Create project directory and navigate into it**
```bash
mkdir wechat-selkies
@@ -78,27 +87,43 @@ docker run -it -p 3001:3001 -v ./config:/config --device /dev/dri:/dev/dri nickr
image: nickrunning/wechat-selkies:latest # or ghcr.io/nickrunning/wechat-selkies:latest
container_name: wechat-selkies
ports:
- "3000:3000" # http port
- "3001:3001" # https port
- "${HTTP_PORT:-3000}:3000"
- "${HTTPS_PORT:-3001}:3001"
restart: unless-stopped
volumes:
- ./config:/config
devices:
- /dev/dri:/dev/dri # optional, for hardware acceleration
- /dev/dri:/dev/dri
environment:
- PUID=1000 # user ID, set according to your system
- PGID=100 # group ID, set according to your system
- TZ=Asia/Shanghai # timezone, set according to your timezone
- LC_ALL=zh_CN.UTF-8 # locale, set according to your needs
- AUTO_START_WECHAT=true # default is true
- AUTO_START_QQ=false # default is false
# - CUSTOM_USER=<Your Name> # recommended to set a custom user name
# - PASSWORD=<Your Password> # recommended to set a password for selkies web ui
shm_size: "1gb" # recommended, will improve performance
- PUID=${PUID:-1000}
- PGID=${PGID:-100}
- TZ=Asia/Shanghai
- LC_ALL=zh_CN.UTF-8
- AUTO_START_WECHAT=true
- AUTO_START_QQ=false
- CUSTOM_USER=${CUSTOM_USER:-}
- PASSWORD=${PASSWORD:-}
shm_size: "${SHM_SIZE:-1gb}"
```
3. **Start the service**
3. **Create `.env` file (optional)**
Copy `.env.example` and modify as needed. Variables not set will use default values:
```bash
docker-compose up -d
cp .env.example .env
```
`.env` file example:
```env
HTTP_PORT=3000
HTTPS_PORT=3001
PUID=1000
PGID=100
# CUSTOM_USER=
# PASSWORD=
SHM_SIZE=1gb
```
4. **Start the service**
```bash
docker compose up -d
```
### Source Code Deployment
@@ -111,13 +136,18 @@ docker run -it -p 3001:3001 -v ./config:/config --device /dev/dri:/dev/dri nickr
2. **Start the service**
```bash
docker-compose up -d
docker compose up -d
```
3. **Access WeChat**
Open in browser: `https://localhost:3001` or `https://<server-ip>:3001`
> **Build minimal version**: When building from source, use build-arg to create a WeChat-only image:
> ```bash
> docker build --build-arg INSTALL_QQ=false --build-arg INSTALL_PCMANFM=false -t wechat-selkies:minimal .
> ```
### Configuration
For more custom configurations, please refer to [Selkies Base Images from LinuxServer](https://github.com/linuxserver/docker-baseimage-selkies).
@@ -134,7 +164,7 @@ This project supports pushing to both GitHub Container Registry and Docker Hub.
#### Environment Variables
Configure the following environment variables in `docker-compose.yml`:
Configure the following environment variables in `docker-compose.yml`. Variables with `${VAR:-default}` syntax can be overridden via a `.env` file:
| Variable | Default | Description |
|----------|---------|-------------|
@@ -187,6 +217,7 @@ devices:
```
wechat-selkies/
├── docker-compose.yml # Docker Compose configuration file
├── .env.example # Environment variables example file
├── Dockerfile # Docker image build file
├── LICENSE # License
├── README.md # Project documentation (Chinese)
@@ -200,6 +231,33 @@ wechat-selkies/
## Troubleshooting
### Updating WeChat/QQ Version
When WeChat or QQ displays a "version outdated" message, simply pull the latest image and recreate the container. Your chat history and configurations will be preserved:
```bash
# Using pre-built images
docker compose pull && docker compose up -d
# Using source code build
git pull && docker compose up -d --build
```
> **Note:** The WeChat and QQ download URLs point to the latest official versions. Rebuilding the image will automatically download the newest version.
For maintainers, the current automation flow is:
1. `Detect Upstream Package Updates` checks the official WeChat packages every 6 hours and can also be triggered manually
2. If the version or package hash changes, the workflow updates `versions/upstream.env`
3. Once that file is committed to `master`, it automatically triggers `Build and Publish Docker Image`
The version state file is stored at `versions/upstream.env` and currently records:
- WeChat amd64/arm64 download URLs
- Parsed WeChat amd64/arm64 package versions
- WeChat amd64/arm64 package SHA256 hashes
- The last detection time that actually changed the tracked state
### Common Issues
1. **Unable to access Web UI**
@@ -210,7 +268,7 @@ wechat-selkies/
View container runtime logs:
```bash
docker-compose logs -f wechat-selkies
docker compose logs -f wechat-selkies
```
## Technical Architecture
@@ -277,4 +335,4 @@ This project is licensed under **MIT License**. See the [LICENSE](LICENSE) file
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=nickrunning/wechat-selkies&type=Date)](https://www.star-history.com/#nickrunning/wechat-selkies&Date)
[![Star History Chart](https://api.star-history.com/svg?repos=nickrunning/wechat-selkies&type=Date)](https://www.star-history.com/#nickrunning/wechat-selkies&Date)

View File

@@ -10,12 +10,12 @@ services:
devices:
- /dev/dri:/dev/dri # optional, for hardware acceleration
ports:
- "3000:3000" # http port
- "3001:3001" # https port
- "${HTTP_PORT:-3000}:3000" # http port
- "${HTTPS_PORT:-3001}:3001" # https port
restart: unless-stopped
environment:
- PUID=1000 # set user id according to your system
- PGID=100 # set group id according to your system
# - CUSTOM_USER=<Your Name> # recommended to set a custom user name
# - PASSWORD=<Your Password> # recommended to set a password for selkies web ui
shm_size: "1gb" # recommended, will improve performance
- PUID=${PUID:-1000} # set user id according to your system
- PGID=${PGID:-100} # set group id according to your system
- CUSTOM_USER=${CUSTOM_USER:-} # recommended to set a custom user name
- PASSWORD=${PASSWORD:-} # recommended to set a password for selkies web ui
shm_size: "${SHM_SIZE:-1gb}" # recommended, will improve performance

View File

@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<openbox_menu xmlns="http://openbox.org/3.4/menu">
<menu id="root-menu" label="MENU">
<item label="WeChat" icon="/usr/share/icons/hicolor/128x128/apps/wechat.png"><action name="Execute"><command>/scripts/wechat/wechat-start.sh</command></action></item>
<item label="QQ" icon="/usr/share/icons/hicolor/512x512/apps/qq.png"><action name="Execute"><command>/scripts/qq/qq-start.sh</command></action></item>
<separator />
<item label="File Manager" icon="/usr/share/pixmaps/xterm-color_48x48.xpm"><action name="Execute"><command>pcmanfm</command></action></item>
<item label="xterm" icon="/usr/share/pixmaps/xterm-color_48x48.xpm"><action name="Execute"><command>/usr/bin/xterm</command></action></item>
<item label="WeChat" icon="/usr/share/icons/hicolor/128x128/apps/wechat.png"><action name="Execute"><command>/scripts/wechat/wechat-restart.sh</command></action></item>
<item label="QQ" icon="/usr/share/icons/hicolor/512x512/apps/qq.png"><action name="Execute"><command>/scripts/qq/qq-restart.sh</command></action></item>
</menu>
</openbox_menu>

3
root/scripts/qq/qq-start.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
/usr/bin/qq --no-sandbox

View File

@@ -1,5 +1,8 @@
#!/bin/bash
# clean up stale dbus pid file to prevent startup failures after container restart
rm -f /run/dbus/pid
# configure openbox dock mode for stalonetray
if [ ! -f /config/.config/openbox/rc.xml ] || grep -A20 "<dock>" /config/.config/openbox/rc.xml | grep -q "<noStrut>no</noStrut>"; then
mkdir -p /config/.config/openbox
@@ -8,6 +11,21 @@ if [ ! -f /config/.config/openbox/rc.xml ] || grep -A20 "<dock>" /config/.config
openbox --reconfigure
fi
# configure default window behavior: open WeChat/QQ as normal windows instead of maximized
OB_RC="/config/.config/openbox/rc.xml"
if [ -f "$OB_RC" ] && ! grep -q '<application class="wechat"' "$OB_RC"; then
sed -i '/<\/openbox_config>/i \
<applications>\
<application class="wechat">\
<maximized>no</maximized>\
</application>\
<application class="QQ">\
<maximized>no</maximized>\
</application>\
</applications>' "$OB_RC"
openbox --reconfigure 2>/dev/null || true
fi
# generate openbox menu from defaults + ~/Desktop/*.desktop files
/scripts/refresh-menu.sh

12
versions/upstream.env Normal file
View File

@@ -0,0 +1,12 @@
# Upstream package state tracked by automation.
WECHAT_AMD64_URL="https://dldir1v6.qq.com/weixin/Universal/Linux/WeChatLinux_x86_64.deb"
WECHAT_ARM64_URL="https://dldir1v6.qq.com/weixin/Universal/Linux/WeChatLinux_arm64.deb"
WECHAT_AMD64_VERSION=""
WECHAT_ARM64_VERSION=""
WECHAT_AMD64_SHA256=""
WECHAT_ARM64_SHA256=""
WECHAT_LAST_CHECKED_AT=""