docker-wechat: running the WeChat Linux client in a container you can reach over the web
在docker里运行wechat,可以通过web或者VNC访问wechat
At a glance
- What is it?
- docker-wechat packages the official WeChat Linux desktop client into a container with a browser-based GUI on port 5800 and VNC on port 5900, built per architecture from the vendor's own deb. It suits someone who wants WeChat on a headless box or on a machine without it, and it needs privileges and care with the network exposure.
- Who is it for?
- Adopt docker-wechat if your WeChat client has to run on a server, a virtual machine or another device, and you are prepared to think about how that container is exposed to a network. Do not adopt it as a casual local install, since running the client directly on a desktop is simpler than a privileged container with an X server in it.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 88 days ago.
- What is it written in?
- Mainly Dockerfile, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A WeChat client on a machine that cannot run one
The WeChat Linux client is a desktop application, and desktop applications are awkward to run on a headless server or on a device you administer remotely. This project puts the client inside a Docker container and exposes its graphical interface in two ways: through a browser on port 5800, and through VNC on port 5900. The README describes it simply as running WeChat in Docker and accessing it over web or VNC.
The use case is narrow but real. Someone with a NAS or a small home server who wants their WeChat account reachable from a laptop, a tablet or a phone browser, without leaving a remote desktop session open on another machine. The same container also serves as an isolated instance: the chat history, downloads and files live in mounted volumes rather than on a user's home directory, and the application runs inside the container's own namespace.
The primary language of the repository is Dockerfile, and the top level contains just a Dockerfile, a Dockerfile-base, a scripts/ directory and the README. There is no application source here, because the application is the vendor's own build. Everything this project contributes is packaging, download resolution and the runtime environment around it.
The build resolves the official deb for your CPU architecture
The mechanism that makes this image work is a two-stage arrangement between the Dockerfile and a shell script. The Dockerfile declares a base image argument, defaults to ricwang/docker-wechat:base, and then copies scripts/resolve-wechat-download.sh into /usr/local/bin/resolve-wechat-download. At build time that script parses the WeChat Linux download page at linux.weixin.qq.com and returns the deb URL matching the architecture being built, using the TARGETARCH build argument.
The download is deliberately defensive. The Dockerfile comment notes that the vendor download source occasionally drops the connection, so curl runs with explicit retries, five attempts with a ten second delay, retry-all-errors and a thirty second connect timeout. The deb is fetched to /tmp/WeChatLinux.deb, its version is read with dpkg-deb, the package is installed with dpkg -i and the file is removed again. A small startapp.sh script is written that executes /usr/bin/wechat, and the version string is stored through set-cont-env as APP_VERSION.
One more piece of surgery is worth noticing. The Dockerfile deletes /etc/passwd, /etc/group and /etc/shadow and replaces them with symlinks to files under /tmp, because the s6 init in the jlesage base image manages the user database through those links, and the build stage temporarily substitutes real files so that dpkg can write to them.
Architecture support is a moving target. The README states that images are built for linux/amd64 and linux/arm64, that the build parses the latest deb link for the current architecture, and that LoongArch is deliberately not published because the GUI base image has no LoongArch platform image.
Running the container, by hand or with compose
The README gives both forms, and they contain the same settings. The docker run invocation is the shortest path to a working instance:
docker run -d \
--name wechat_container_demo \
--hostname wechat \
-v <THE PATH>/.xwechat:/root/.xwechat \
-v <THE PATH>/xwechat_files:/root/xwechat_files \
-v <THE PATH>/downloads:/root/downloads \
-v /dev/snd:/dev/snd \
-p 5800:5800 \
-p 5900:5900 \
-e LANG=zh_CN.UTF-8 \
-e USER_ID=0 \
-e GROUP_ID=0 \
-e WEB_AUDIO=1 \
-e TZ=Asia/Shanghai \
--privileged \
ricwang/docker-wechat:latestThree host paths are mounted for state: the .xwechat directory for configuration, xwechat_files for files, and downloads for received files. The Dockerfile declares exactly these three as volumes. The /dev/snd bind mount is what makes sound work, and WEB_AUDIO=1 routes any audio the application produces through the browser instead, which is the only way to get sound over the web interface.
The compose form expresses the same thing declaratively:
services:
wechat:
image: ricwang/docker-wechat:latest
container_name: wechat_container
volumes:
- <THE PATH>/.xwechat:/root/.xwechat
- <THE PATH>/xwechat_files:/root/xwechat_files
- <THE PATH>/downloads:/root/downloads
- /dev/snd:/dev/snd
ports:
- "5800:5800"
- "5900:5900"
hostname: wechat
environment:
- LANG=zh_CN.UTF-8
- USER_ID=0
- GROUP_ID=0
- WEB_AUDIO=1
- TZ=Asia/Shanghai
privileged: trueThe browser GUI is then reachable on port 5800 and a VNC client connects to port 5900.
Environment variables that decide locale, display and access control
The README documents the container's configuration as a table of environment variables with defaults, and a few of them deserve attention because they change how the instance behaves rather than how it looks.
Locale and time come first. LANG defaults to en_US.UTF-8 and is the locale the application uses, in the language_TERRITORY.charset form, while TZ defaults to Asia/Shanghai and can also be set by mapping the host's /etc/localtime. Display sizing is DISPLAY_WIDTH at 1920 and DISPLAY_HEIGHT at 1080, and DARK_MODE set to 1 turns on the dark appearance.
Two variables affect stability and privilege. KEEP_APP_RUNNING set to 1 restarts the application if it crashes or terminates, and APP_NICENESS sets the scheduling priority, where negative nice values mean higher priority and require extra permission. The README is explicit that a negative nice value means the container must run with the docker option --cap-add=SYS_NICE.
Then there is access control, which is where the defaults matter most. WEB_AUTHENTICATION set to 1 puts a login page in front of the browser GUI, and it only works when SECURE_CONNECTION is also enabled. SECURE_CONNECTION set to 1 encrypts access over the browser or the VNC client, and it has its own variables: SECURE_CONNECTION_VNC_METHOD, which takes SSL or TLS and defaults to SSL, and SECURE_CONNECTION_CERTS_CHECK_INTERVAL, defaulting to 60 seconds, which is how often the system checks whether web or VNC certificates have changed and restarts the affected service when they have. WEB_AUTHENTICATION_USERNAME and WEB_AUTHENTICATION_PASSWORD are a convenience for a single user, and VNC_PASSWORD sets the password needed to connect to the GUI. CONTAINER_DEBUG set to 1 turns on debug logging.
The exposure problem is the part to think about
Read the defaults together and the risk profile becomes clear. WEB_AUTHENTICATION defaults to 0, SECURE_CONNECTION defaults to 0, and VNC_PASSWORD has no default value at all. In other words, a container started exactly as the README shows will serve an interactive WeChat session, with the user's account inside it, to anything that can reach the published ports.
That is not a criticism of the project, it is the nature of a GUI in a container, but it is the reason the security switches exist. Turning on WEB_AUTHENTICATION together with SECURE_CONNECTION puts credentials in front of the browser session, and enabling the VNC password protects the second access path, which is otherwise a separate way in.
The compose and run examples also add privileges in two ways. privileged: true is set in the compose file and --privileged on the command line, which grants far more than the container needs, and USER_ID=0 with GROUP_ID=0 means the process runs as root inside the container. The README does offer the narrower alternative of --cap-add=SYS_NICE for the case where a negative APP_NICENESS value is required, which is a good sign about the intent, but the shipped examples still run privileged.
The last push was on 2026-07-27, and the repository publishes no GitHub releases, so an image you run is either pulled from the registry or built from the current source.
Where the container model fights back
Several practical limits follow from the approach rather than from the configuration.
The first is the build dependency on the outside world. The image is assembled by downloading a deb from a page that the build script parses at build time. When the vendor changes that page, or the download host is briefly unreachable despite the retries, the build fails, and there is no published release to fall back on, so you build it yourself.
The second is the audio path. WEB_AUDIO routes sound through the browser, and the README states plainly that VNC clients do not support audio, so the VNC route is silent unless the host device is passed through. The third is that the client is a desktop GUI, which means a virtual display, an X server and window management all run inside the container, and the browser view of a remote desktop is not as responsive as a native application.
The fourth is architecture coverage. LoongArch users have no image because the GUI base image has no LoongArch variant, so the gap is in the base, not in this project's own build logic.
The fifth is that this is a container around a client, not a headless integration. Nothing here logs in automatically, exports messages, or exposes the account to an API, and the repository contains no such code.
Against running the client on a real desktop with remote access
The alternative to containerising the WeChat client is not another container image, it is the obvious arrangement: install the official Linux client on a machine with a display and reach that machine with whatever remote access you already trust, or install the client natively on the device you actually use.
The difference in approach is where the isolation and the remote access live. With the container, the application, its files and its X server share a namespace with the host through bind mounts and privileged mode, and the remote access is a web session served by the container on 5800 or a VNC server on 5900. With a native install, the client runs as a normal desktop program, the remote access is whatever your operating system or network already provides, and there is no extra GUI stack to reason about.
The container version earns its complexity in specific situations: an always-on box with no screen, a throwaway instance whose chat history you want mounted to a directory you control rather than to a user's profile, or the need to reach the account from a browser on a device with no WeChat client. In every other case the native install is fewer moving parts and one less set of published ports to defend.
Editorial conclusion
Adopt docker-wechat if your WeChat client has to run on a server, a virtual machine or another device, and you are prepared to think about how that container is exposed to a network. Do not adopt it as a casual local install, since running the client directly on a desktop is simpler than a privileged container with an X server in it. Before you start, confirm that the ports 5800 and 5900 sit behind something you control, because neither WEB_AUTHENTICATION nor SECURE_CONNECTION is enabled by default and VNC_PASSWORD has no default value. Also check that your CPU architecture is covered, since images are built for linux/amd64 and linux/arm64 only, and expect to rebuild rather than pull a release, as the repository publishes none.
Frequently asked questions
How do I access WeChat through the browser with docker-wechat?
Publish port 5800, which the README's compose example maps as 5800:5800, and open that port in a browser to reach the graphical interface. Port 5900 is published at the same time for VNC clients.
Which CPU architectures does the docker-wechat image support?
Images are built for linux/amd64 and linux/arm64, and the build resolves the matching deb from the WeChat Linux download page at build time. LoongArch is not published because the GUI base image has no LoongArch image.
How do I protect the web interface in docker-wechat?
Set WEB_AUTHENTICATION=1 and SECURE_CONNECTION=1, which the README notes are both required for the login page to work, and set VNC_PASSWORD for the VNC path. The defaults leave authentication off and give no VNC password, so both access paths are open on the published ports.
Why does the docker-wechat container run as privileged?
The examples in the README set privileged: true and run with --privileged, and they set USER_ID=0 and GROUP_ID=0. The documentation notes a narrower option for one specific case: a negative APP_NICENESS value needs the docker option --cap-add=SYS_NICE.
Can I get sound when using docker-wechat over VNC?
Not through the VNC client. The README states that VNC clients do not support audio, while WEB_AUDIO=1 routes any audio the application produces through the browser instead. The example also passes /dev/snd into the container.
Does docker-wechat publish tagged releases?
No, the repository has no GitHub releases. Images are pulled from the registry as ricwang/docker-wechat:latest or built from the current source, and the last push was on 2026-07-27.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ricwang-docker-wechat)Was this useful?