老旧Linux系统借助Docker运行新版GUI应用
前言
在工作中,我们有时会遇到这样的困境:所用的 Linux 系统版本较老,许多新的软件包无法安装和使用,但受限于公司的统一管理要求,又不能升级或更换系统。
面对这种情况,Docker 就是一个很好的解决方案——在容器中运行一个较新的 Linux 发行版(如 Ubuntu 24.04),在其中安装所需的软件,然后通过 X11 转发将 GUI 界面显示到宿主机的桌面上,实现「无缝使用」的效果。
有人可能会问:这不就是 Distrobox 干的事吗?没错,Distrobox 封装了 Docker 的各种复杂操作,专门用于在容器中运行本地 GUI 应用。但遗憾的是,在一些过于老旧的系统上,Distrobox 本身也无法正常工作(对 Docker 版本和内核特性有一定要求),所以我们只能手动搭建这套环境。
本文将从零开始,记录完整的搭建过程。
环境说明
| 项目 | 版本 |
|---|---|
| 宿主机系统 | Deepin / UOS(基于 Debian) |
| Docker | 18.09.1 |
| docker-compose | 1.21.0 |
| 容器系统 | Ubuntu 24.04 |
一、安装 Docker
首先安装 Docker 和 docker-compose:
sudo apt install docker.io docker-compose
安装完成后确认版本:
docker --version
# Docker version 18.09.1, build 4c52b90
docker-compose --version
# docker-compose version 1.21.0, build unknown
可以看到版本确实比较老,这也是 Distrobox 无法使用的原因之一。
接下来创建 docker 用户组,避免每次都需要 sudo:
# 创建 docker 用户组(已存在则忽略)
sudo groupadd docker 2>/dev/null || true
# 将当前用户加入 docker 组
sudo usermod -aG docker $USER
注意:添加用户组后需要注销并重新登录才能生效。
二、编写 docker-compose.yml
选择一个合适的位置,创建项目目录和配置文件:
mkdir -p ~/docker/ubuntu-24.04
cd ~/docker/ubuntu-24.04
touch docker-compose.yml
在编写配置之前,需要先获取当前用户的 UID 和 家目录路径,后续配置中会多次用到:
id -u
# 例如输出:24035
echo $HOME
# 例如输出:/home/magicdmer
请将下面配置中所有出现
24035和/home/magicdmer的地方替换为你的实际值。
docker-compose.yml 内容如下:
version: '2.3'
services:
dev:
image: ubuntu:24.04
container_name: dev
network_mode: host # 与宿主机共享网络栈
privileged: true # 授予完整权限(GUI 应用需要)
restart: unless-stopped
# ⚠️ 首次启动时请保持注释状态!
# 原因:全新的 Ubuntu 容器中没有 sudo,而安装 sudo 又需要 root 权限,
# 所以第一次需要以 root 身份进入容器完成初始化。
# 初始化完成后,取消下面这行注释即可以普通用户身份运行。
# user: "24035:24035"
# 下面两个比较关键,init是给docker环境提供进程回收能力,不然出现一堆僵尸进程。
# 这两个保证gui程序一直运行不会突然闪退
init: true
shm_size: '2gb'
tty: true
stdin_open: true
environment:
# ---- X11 显示 ----
- DISPLAY=${DISPLAY}
# ---- 输入法(fcitx)----
- GTK_IM_MODULE=fcitx
- QT_IM_MODULE=fcitx
- XMODIFIERS=@im=fcitx
# ---- 音频(PulseAudio)----
- PULSE_SERVER=unix:/run/user/24035/pulse/native
# ---- 语言 ----
- LANG=zh_CN.UTF-8
# ---- D-Bus 会话总线 ----
- DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/24035/bus
# ---- 代理(可选,按需配置)----
# 如果宿主机运行了代理工具(如 ***),可以通过以下配置让容器也走代理
- http_proxy=http://127.0.0.1:10800
- https_proxy=http://127.0.0.1:10800
- all_proxy=http://127.0.0.1:10800
- no_proxy=localhost,127.0.0.1,::1
# ---- 用户家目录 ----
- HOME=/home/magicdmer
volumes:
# 挂载家目录 —— 容器内的应用可以直接访问宿主机的文件
- /home/magicdmer:/home/magicdmer
# X11 socket —— 精准挂载,避免整个 /tmp 冲突
- /tmp/.X11-unix:/tmp/.X11-unix
# 音频 + D-Bus 运行时目录
- /run/user/24035:/run/user/24035
# 用户/用户组信息(只读)—— 让容器内的 UID/GID 与宿主机一致,如果是域用户建议注释
- /etc/passwd:/etc/passwd:ro
- /etc/group:/etc/group:ro
# 时区同步(只读)
- /etc/localtime:/etc/localtime:ro
# 保持容器常驻运行
entrypoint: ["tail", "-f", "/dev/null"]
配置要点解析
network_mode: host:容器与宿主机共享网络,省去端口映射的麻烦,也让代理配置更简单。privileged: true:GUI 应用通常需要访问一些特殊设备和资源,privileged 模式可以避免很多权限问题。- 挂载
/etc/passwd和/etc/group:这是关键优化——直接复用宿主机的用户信息,避免了容器内外 UID 不一致导致的文件权限问题。 - 挂载
/tmp/.X11-unix:这是 X11 显示服务的 Unix socket 所在目录,是 GUI 转发的基础。 init和shm_size: 这两个用来保证 gui 程序在本地运行的稳定性,不会运行一段时间后闪退
三、启动容器
# 拉取 Ubuntu 24.04 镜像
docker-compose pull
# 后台启动容器
docker-compose up -d
在宿主机上授权 Docker 容器访问 X11 显示服务:
xhost +local:docker
提示:
xhost +local:docker在每次重启宿主机后需要重新执行。可以将其加入~/.bashrc或设置为开机自启。
四、初始化容器环境
以 root 身份进入容器:
docker exec -it dev bash
在容器内依次执行以下操作:
4.1 基础配置
apt update
# 安装 sudo
apt install sudo -y
# 如果没有挂载宿主机的用户信息,需要我们手动添加用户
useradd -u 24035 -d /home/magicdmer -s /bin/bash magicdmer
# 为宿主机用户配置免密 sudo(替换为你的用户名)
echo "magicdmer ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/magicdmer
# 切换到普通用户
su magicdmer
# 确认 DISPLAY 变量(没有值则手动设置)
echo $DISPLAY
export DISPLAY=:0 # 如果上一行为空则执行这行
4.2 中文环境
# 安装并生成中文 locale
sudo apt install -y locales
sudo locale-gen zh_CN.UTF-8
sudo locale-gen en_US.UTF-8
sudo update-locale LANG=zh_CN.UTF-8
# 安装中文字体(解决中文显示为方块的问题)
sudo apt install -y fonts-wqy-zenhei fonts-wqy-microhei
4.3 D-Bus 与主题
# 安装 D-Bus 相关组件,使容器内应用能与宿主机桌面环境联动
sudo apt install -y dbus-x11 dconf-cli adwaita-icon-theme gnome-themes-extra
4.4 输入法支持
# 安装 fcitx 输入法前端,使容器内应用能调用宿主机的中文输入法
sudo apt install -y fcitx-frontend-gtk3 fcitx-frontend-gtk2 fcitx-frontend-qt5
4.5 验证测试
# 安装一个 GUI 应用进行测试
sudo apt install -y gedit
# 启动测试 —— 宿主机桌面上应该弹出 gedit 窗口
gedit
如果一切正常,你应该能在宿主机桌面上看到 gedit 的窗口,并且可以正常使用中文输入法。
五、创建桌面快捷方式
每次通过命令行启动容器中的应用比较麻烦,我们可以在宿主机上创建 .desktop 快捷方式,实现双击即打开:
[Desktop Entry]
Name=Gedit (Docker)
Comment=文本编辑器(运行在 Docker 容器中)
GenericName=Text Editor
Exec=docker exec -u magicdmer dev gedit
Icon=/usr/share/pixmaps/gedit.png
Type=Application
Categories=Editor;IDE;
Terminal=false
将以上内容保存为 ~/.local/share/applications/docker-gedit.desktop,即可在应用菜单中找到它。
注意:
Exec中不要使用-it参数,否则.desktop文件无法正常启动应用(-it是交互式终端参数,桌面启动时没有终端可分配)。
总结
通过以上步骤,我们实现了在老旧 Linux 系统上通过 Docker 运行新版 Ubuntu 24.04 GUI 应用的完整方案。核心原理是:
- Docker 容器提供新版本的软件运行环境
- X11 socket 挂载实现 GUI 界面转发到宿主机
- PulseAudio / D-Bus 挂载实现音频和桌面服务的联动
- fcitx 前端实现中文输入法的支持
- passwd/group 挂载解决文件权限一致性问题
这套方案虽然不如 Distrobox 那样开箱即用,但胜在兼容性强——只要系统能跑 Docker,就能用这种方式突破系统版本的限制。

浙公网安备 33010602011771号