
Dockerfile 链接注意:README文件不会定期更新,请查看标签列表确认是否有新版本发布。
您可以找到特定版本(随构建发布),例如 5.6.39 或 5.10.19 等。还有“分支版本”标签,如 5.6 和 5.10,它们始终指向分支内的最新版本(例如最新的 5.10.x 版本)。
每个版本的“构建”版本(例如 5.6.39-syyyyyyyy)使用 SHA1 提交 ID 的前 8 个字符。目的是当镜像定义更改但 UniFi Controller 版本未变时,能够区分先前和更新的镜像(尽管两者都是 5.6.39 变体)。因此,当用户选择“构建”标签时,可以确保获得相同的镜像定义。
建议要么使用“滚动标签”(例如 lts 或 stable),要么选择构建标签(为了更好的可重复性,例如 5.5.20-s11594497)。无论如何,建议在 UniFi Controller 中启用定期备份,以便使用滚动标签自动升级时,若出现问题可通过备份文件恢复。
本项目旨在将 UniFi Network Controller(也称为 UniFi Controller 或 UniFi SDN Controller)运行在 Docker 容器中,遵循以下原则:
为实现这些目标,目前具备以下特性:
stable 标签,跟随 UniFi 的稳定分支警告:为保证 UID 和 GID 的稳定性,现在创建了专用
unifi用户(UID 750)及其主组unifi(GID 750)。更新时需要对卷执行所有权更改(chmod -R 750:750 ...)。此特性与支持类似功能的新版 UniFi Controller 5.6 兼容。
本项目容器镜像可从以下位置拉取:
docker pull jcberthon/unifi:stabledocker pull registry.gitlab.com/huygens/unifi-docker/unifi:stable这是 Ubiquiti Network 的 UniFi Controller 的容器化版本(当前 LTS 为 5.6 分支版本)。
使用 docker run --net=host -d jcberthon/unifi 可使用主机网络堆栈和默认用户设置(通常为 root,除非配置了用户命名空间)运行,但建议按以下方式优化配置。
以下选项可能有用:
TZ 设置时区data 和 log 卷以下是一些测试示例,或直接使用仓库中的 docker-compose.yml 文件,执行 docker-compose up -d 启动。该文件包含一些推荐的合理选项,如 restart、cpus、mem_limit、memswap_limit、pids_limit、cap_drop、security_opt。建议根据环境和需求修改这些选项的值(例如增加 CPU 数量)。
注意:以下示例设置卷权限,使容器能以非特权用户运行。这是因为示例使用绑定挂载,因此必须授予对这些文件夹的读/写/搜索权限,就像以其他用户启动进程访问这些文件夹一样。示例显示同时设置用户和组所有权,但您完全可以灵活设置(仅设置用户或组,通过组提供权限,若文件系统支持可使用 ACL 等)。
console$ mkdir -p ~/unifi/data $ mkdir -p ~/unifi/logs $ sudo chown 750:750 ~/unifi/data ~/unifi/logs $ docker run --rm --cap-drop ALL -e TZ='Europe/Berlin' \ -p 8080:8080 -p 8443:8443 -p 8843:8843 \ -v ~/unifi/data:/var/lib/unifi \ -v ~/unifi/logs:/var/log/unifi \ --name unifi jcberthon/unifi
在此示例中,我们移除所有权限,启用端口转发,可在配置了用户命名空间的 Docker 主机上运行。但请注意,在此配置下,您需要遵循 UniFi Layer 3 设备 adoption 和管理方法。我个人使用过 DNS 和 DHCP 方法,均能正常工作。
类似示例,但为了更简单的 L2 adoption,需要映射 UDP 端口 ***。
注意:以下命令预期能工作,但未经过测试,只需将上述命令的最后一行替换为:
console$ docker run --rm --cap-drop ALL -e TZ='Europe/Berlin' \ -p 8080:8080 -p 8443:8443 -p 8843:8843 -p 10001:10001/udp \ -v ~/unifi/data:/var/lib/unifi \ -v ~/unifi/logs:/var/log/unifi \ --name unifi jcberthon/unifi
您也可以避免所有端口映射,直接使用 --net=host,但这样会使容器访问主机网络设备。如果以 root 运行容器,***者若利用 UniFi Controller 软件栈的未来漏洞,可能会监视网络流量甚至造成更严重后果。这会移除网络栈与容器之间的隔离层,类似于在主机上直接运行 UniFi 服务而不使用 Docker。无论如何,默认情况下此容器以非 root 用户运行,因此使用此选项仍能限制安全风险。
升级到新版本时(例如从 5.6 分支升级到 5.7 分支),建议先执行备份。可使用 UniFi Controller 应用执行备份(在“设置”->“维护”中点击“下载备份”按钮)。确保备份可用,可在其他主机上创建新容器并尝试恢复备份以验证其有效性。
强烈建议查看 UniFi 新版本的变更日志,确认已知问题、变更、弃用等信息,其中可能包含额外的升级说明。
通常只需停止并删除旧容器,使用更新后的 Docker 镜像重新创建容器。若使用 docker-compose,可更新镜像标签并执行 docker-compose up --pull -d,这将拉取新版本镜像(如有),并使用该镜像重新创建容器(停止、删除、创建并启动容器)。
/var/lib/unifi:配置数据(例如 system.properties)/var/log/unifi:日志文件(并非必需)注意:UniFi Controller 还会在
/var/run/unifi文件夹下写入数据。Dockerfile 中未暴露此文件夹,因为无需持久化其数据(包含 PID 文件和有关固件或控制器更新的 json 文件)。但如果您认为需要持久化此信息(例如删除并重新创建容器时),即使 Dockerfile 未定义,也可添加卷映射。
TZ:时区。(例如 "Europe/Berlin")若要设置 UniFi Controller 或 JVM 环境选项,可在创建容器时添加环境变量,或编辑当前文件夹中的 unifi.default 文件并将其作为卷挂载(/etc/default/unifi)。以上述示例为例:
console$ docker run --rm --cap-drop ALL -e TZ='Europe/Berlin' \ -p 8080:8080 -p 8443:8443 -p 8843:8843 -p 10001:10001/udp \ -v ~/unifi/data:/var/lib/unifi \ -v ~/unifi/logs:/var/log/unifi \ -v unifi.default:/etc/default/unifi:ro \ --name unifi jcberthon/unifi
未被容器镜像暴露的端口会特别标记。未指定时,默认已暴露。
3478/udp:STUN 服务(用于 NAT 穿透 - WebRTC、SIP 等)- 不确定 Ubiquiti 具体用途,但似乎需要它(至少对于交换机)来显示受管设备的某些信息(例如交换机上可实时显示端口状态)。5656-5699/udp:用于 UPA-EDU(未暴露)6789/tcp:速度测试(仅 unifi5)8080/tcp:设备命令/控制(API)8443/tcp:Web 界面 + API8843/tcp:HTTPS 门户(访客 WiFi?)8880/tcp:HTTP 门户(访客 WiFi?)8881/tcp:不使用(保留,未暴露)8882/tcp:不使用(保留,未暴露)10001/udp:UBNT 发现27017/tcp 和 27117/tcp:DB 服务器本地绑定端口(MongoDB,未暴露)54123/udp:???容器至少应转发 8443/tcp 端口,若使用访客网络则还需 8843/tcp 端口。另可查看本仓库的 docker-compose.yml 文件,获取功能完整的 UniFi Controller 所需映射的端口列表。
参见 UniFi - 所用端口
本镜像基于 Java 8u131 或更新版本,因此 JVM 支持容器感知,能够根据容器的 CPU 和 RAM 限制(基于 CGroups 限制)进行优化。因此,JVM 会适应为容器设置的资源限制(例如使用 --cpus 2.0 或 --memory 2048m)。当前方法是 JVM 进程最多可使用容器允许的最大内存的一半,另一半供 MongoDB 数据库使用。对于家庭使用(一个 AP 和一个交换机),当前 5.6 分支的容器内存使用未超过 600MB。
未尝试在内存小于 1GB 的设备上运行。但在 1GB 或更少内存的设备上,应确保 Java 进程可分配最多 512MB 堆内存。这意味着需要手动将最大堆大小设置为 512MB。
此外,建议限制整个容器的内存。例如,若有 1GB RAM,可将内存限制为 768MB,以便系统(内核等)有足够空间。此设置下,MongoDB 仍有足够内存。
限制为 768MB 内存的示例:
console$ docker run --rm --cap-drop ALL \ -e JVM_MAX_HEAP_SIZE="512m" \ --memory 768m \ -p 8080:8080 -p 8443:8443 -p 8843:8843 -p 10001:10001/udp \ -v ~/unifi/data:/var/lib/unifi \ -v ~/unifi/logs:/var/log/unifi \ --name unifi jcberthon/unifi
本容器基于 Docker Hub 官方 Ubuntu 18.04 镜像(FROM ubuntu:bionic),当前使用 OpenJDK 8。Ubiquiti 推荐使用 Debian 或 Ubuntu,因此该镜像适用。官方 Mongo 镜像基于 Debian 7 Wheezy,意味着使用过时包且默认基于 OpenJDK 7,不适用。未考虑 Alpine,因其使用 musl libc 而非 GNU libc,前者测试不足,且不想对基于此 C 库的 MongoDB 和 Java 8 进行大量测试。
本方案未严格遵循 Docker 关于微服务和每个容器运行一个进程的最佳实践。容器包含 UniFi 控制器所需的所有组件,特别是嵌入式 MongoDB 数据库以及构成控制器的 3 个 Java 进程。因此需要轻量级的 init 系统。Ubiquiti 提供的官方 init 脚本提供信号处理和进程监控(退出时重启等)。这些功能与 Docker 功能略有冗余,因此未使用其技术,而是利用 Docker 原生功能。通过自定义启动脚本,确保所有服务可以非特权用户运行。
最初方案依赖 Docker 提供的 init 守护进程(使用 --init 触发),提供适当的信号处理(捕获 SIGTERM 并将信号“传播”给子进程)和僵尸进程回收。init 函数捕获 SIGTERM 以向 UniFi 控制器进程发出适当的停止命令,使其优雅关闭,还能防止僵尸进程累积。但该方案依赖 Docker 1.13+,而许多供应商仍提供 Docker 1.12 或更早版本。因此当前方案嵌入了一个小型 init 进程,即 Docker 选择实现 init 选项的 https://github.com/krallin/tini%E3%80%82%E5%AE%83%E6%8F%90%E4%BE%9B%E6%89%80%E9%9C%80%E7%9A%84%E4%BF%A1%E5%8F%B7%E5%A4%84%E7%90%86%E5%92%8C%E5%83%B5%E5%B0%B8%E5%9B%9E%E6%94%B6%E5%8A%9F%E8%83%BD%EF%BC%8C%E4%B8%94%E9%9D%9E%E5%B8%B8%E5%B0%8F%E5%B7%A7%EF%BC%88<100KB)。
容器启动后的进程示例:
console$ docker exec -t 49b9e24a58f8 ps -e -o pid,ppid,cmd PID PPID CMD 1 0 /sbin/init -- /usr/lib/unifi/bin/unifi.init start 6 1 /bin/bash /usr/lib/unifi/bin/unifi.init start 55 6 unifi -home /usr/lib/jvm/java-8-openjdk-amd64 -cp /usr/share/java/commons-daemon.jar:/usr/lib/unifi/lib/ace.jar -p 56 55 unifi -home /usr/lib/jvm/java-8-openjdk-amd64 -cp /usr/share/java/commons-daemon.jar:/usr/lib/unifi/lib/ace.jar -p 57 55 unifi -home /usr/lib/jvm/java-8-openjdk-amd64 -cp /usr/share/java/commons-daemon.jar:/usr/lib/unifi/lib/ace.jar -p 70 57 /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java -Xmx1024M -XX:ErrorFile=/usr/lib/unifi/data/logs/hs_err_pid<pid>.lo 89 70 bin/mongod --dbpath /usr/lib/unifi/data/db --port 27117 --logappend --logpath logs/mongod.log --nohttpinterface -- 959 0 ps -e -o pid,ppid,cmd
提供 Dockerfile,因此可构建自己的容器镜像。构建示例:
console$ docker build -t jcberthon/unifi .
构建容器前,可调整 unifi.default 文件。
该文件包含多个可覆盖默认配置的参数,文件中对这些参数有描述。但请注意,修改这些参数可能导致控制器故障(尤其是尝试更改数据和日志文件夹但未更改容器卷时)。
可能的参数(在 unifi.default 文件中有详细描述):
UNIFI_DATA_DIR:UniFi Controller 数据文件夹,谨慎更改UNIFI_LOG_DIR:UniFi Controller 日志文件夹,谨慎更改UNIFI_RUN_DIR:UniFi Controller 运行时文件夹JAVA_ENTROPY_GATHER_DEVICE:高级参数,大多数用户不需要JVM_MAX_HEAP_SIZE:限制 JVM 最大堆以下是 jcberthon/unifi 相关的常用 Docker 镜像,适用于 不同场景 等不同场景:
您可以使用以下命令拉取该镜像。请将 <标签> 替换为具体的标签版本。如需查看所有可用标签版本,请访问 标签列表页面。




探索更多轩辕镜像的使用方法,找到最适合您系统的配置方式
通过 Docker 登录认证访问私有仓库
无需登录使用专属域名
Kubernetes 集群配置 Containerd
K3s 轻量级 Kubernetes 镜像加速
VS Code Dev Containers 配置
Podman 容器引擎配置
HPC 科学计算容器配置
ghcr、Quay、nvcr 等镜像仓库
Harbor Proxy Repository 对接专属域名
Portainer Registries 加速拉取
Nexus3 Docker Proxy 内网缓存
需要其他帮助?请查看我们的 常见问题Docker 镜像访问常见问题解答 或 提交工单
docker search 限制
站内搜不到镜像
离线 save/load
插件要用 plugin install
WSL 拉取慢
安全与 digest
新手拉取配置
镜像合规机制
manifest unknown
no matching manifest(架构)
invalid tar header(解压)
TLS 证书失败
DNS 超时
域名连通性排查
410 Gone 排查
402 与流量用尽
401 认证失败
429 限流
D-Bus 凭证提示
413 与超大单层
来自真实用户的反馈,见证轩辕镜像的优质服务