
jcberthon/unifiDockerfile 链接注意:README文件不会定期更新,请查看标签列表确认是否有新版本发布。
5.10.21, 5.10, latest, stable (Dockerfile):当前为 unifi-5.10 分支5.9.29, 5.9, oldstable (Dockerfile):当前为 unifi-5.9 分支5.6.40, 5.6, lts (Dockerfile):当前为 unifi-5.6 分支您可以找到特定版本(随构建发布),例如 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-s***)。无论如何,建议在 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 ***:***/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 ***:***/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:不使用(保留,未暴露)***/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 ***:***/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 选项的 tini。它提供所需的信号处理和僵尸回收功能,且非常小巧(<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 最大堆



manifest unknown 错误
TLS 证书验证失败
DNS 解析超时
410 错误:版本过低
402 错误:流量耗尽
身份认证失败错误
429 限流错误
凭证保存错误
来自真实用户的反馈,见证轩辕镜像的优质服务