专属域名
文档搜索
轩辕助手
Run助手
邀请有礼
返回顶部
快速返回页面顶部
收起
收起工具栏
轩辕镜像 官方专业版
轩辕镜像 官方专业版轩辕镜像 官方专业版官方专业版
首页个人中心搜索镜像

交易
充值流量我的订单
工具
提交工单镜像收录一键安装
Npm 源Pip 源Homebrew 源
帮助
常见问题
其他
关于我们网站地图

官方QQ群: 1072982923

jcberthon/unifi Docker 镜像 - 轩辕镜像

unifi
jcberthon/unifi
自动构建
A Unifi Controller in a Box
2 收藏0 次下载
😅 镜像要是出问题,背锅的一定是你
镜像简介版本下载
😅 镜像要是出问题,背锅的一定是你

UniFi Network Controller in a Box - Docker Edition

Supported tags and respective Dockerfile links

Note: I do not update the README file regularly. So please check the tag lists if newer releases have been pushed.

  • 5.10.21, 5.10, latest, stable (Dockerfile): currently unifi-5.10 branch
  • 5.9.29, 5.9, oldstable (Dockerfile): currently unifi-5.9 branch
  • 5.6.40, 5.6, lts (Dockerfile): currently unifi-5.6 branch

You will find specific versions (as they build), e.g. 5.6.39 or 5.10.19 or etc.
And "branch versions" tag such as 5.6 and 5.10 which always point to the latest release within a branch (e.g. the most recent 5.10.x release).

"Build" versions per release (e.g. 5.6.39-syyyyyyyy), I'm using the first 8 characters of the SHA1 commit ID. The purpose is when I'm changing my image definition but UniFi Controller release has not changed, I need to distinguish between the previous and newer image although both are 5.6.39 variants. So when a user picks one of the "build" image he is sure to get the same image definition.

My recommendation is to either stick to a "rolling tag" (e.g. lts or stable) or to pick one of the build tag (for better repeatability, e.g. 5.5.20-s***).
In any case it is recommended to activate scheduled backup in your UniFi Controller so that if you automatically upgrade when using a rolling tag, you always have a backup file to revert if things get broken.

Project Presentation

This project has for purpose to run the UniFi Network Controller (also known as UniFi Controller or UniFi SDN Controller) inside a Docker container with the following principles:

  • Minimum privilege basis, we expose or need what's required
  • Update often, we want security fixes to be includes asap
  • Rolling update of the stable UniFi Controller releases

We have currently the following features to progress towards those goals:

  • We drop all capabilities Docker usually grant to a container, no privilege container;
  • We forbid acquiring new privileges (e.g. via setuid programs);
  • We run the container as a non-root user;
  • We provide instructions so you do not need to use the host network;
  • We have weekly rebuild, so the full stack (from base image to UniFi Controller package) is kept up-to-date;
  • We provide a stable tag, which follow the stable branch of UniFi;
  • We usually have the UniFi Controller tested internally before it is published here;
  • And of course it works!

WARNING: in order to guarantee stability of the UID and GID. We are now creating a unifi dedicated user which will always have the UID 750 and its main group is also called unifi and has GID 750. When updating you will need to perform a change of ownership on your volumes (chmod -R 750:750 ...).
This feature is compatible with the new UniFi Controller 5.6 which supports a similar feature.

This project container image can be pulled from:

  • Docker Hub: e.g. docker pull jcberthon/unifi:stable
  • GitLab Registry: e.g. docker pull registry.gitlab.com/huygens/unifi-docker/unifi:stable

Description

This is a containerized version of Ubiquiti Network's UniFi Controller (current LTS is version 5.6 branch).

Use docker run --net=host -d jcberthon/unifi to run it using your host network stack and with default user settings (usually this is root unless you configured user namespaces), but you might want to do better than that see below.

The following options may be of use:

  • Set the timezone with TZ
  • Use volumes to persist application data: the data and log volumes

Below are a few examples to test with or simply use the docker-compose.yml file in the repository and do docker-compose up -d to start it. That file contains also a number of sane options which we recommend to use as well, such as: restart; cpus; mem_limit; memswap_limit; pids_limit; cap_drop; security_opt. It is recommended to change the values of those options to match your environment and requirements (e.g. increasing the number of cpus).

Note: the following examples set permissions on the volumes so that the container can run with an unprivileged user. This is because the examples are using bind-mount and therefore you must grant permission to read/write/search those folders just like if you launched a process as another user which should access those folders. The example shows that we are setting both user and group ownership, but of course you full flexibility (only setting user or group, providing the privileges via the group, using ACLs if your filesystem support them, etc.)

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

In this example, we drop all privileges, activate port forwarding and it can run on a Docker host with user namespaces configured. However, note that in this configuration you will need to follow the [UniFi Layer 3 methods for adoption and management] ([***]
I have personally used the DNS and DHCP approach, both works fine.

A similar example but with the easier L2 adoption, we will need to map the UDP port ***.

Note that I expect the following to work but I haven't tested it, simply replace the last line of the commands given above by:

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

You could of course avoid all port mapping and simply use --net=host, but by doing so you give access to the container to your network device(s). If you run the container as root, it means someone exploiting a future vulnerability in the UniFi Controller software stack could potentially use that to spy on your network traffic or worse. So you are removing the isolation layer between your network stack and your container. It is not bad, it is like if you were running the UniFi services directly on the host without Docker. Anyway, by default this container will run as a non-root user, so you could still use that option and have limited security risk.

Upgrading to newer version

When upgrading to newer version (e.g. going from the 5.6 to 5.7 branch) it is good practice to perform a backup before. You can use the UniFi Controller app to perform such a backup (under Settings -> Maintenance and click the "Download Backup" button). Make sure your backup is handy, potentially create a new container on a different host and try to restore the backup to make sure it works.

It is highly recommended to check the UniFi changelog for the newer revisions to verify for known issues, changes, depreciation, etc. They can also contain additional instructions for upgrading.

Usually simply stop and delete the previous container and respawn a new container with the updated Docker image. If you are using docker-compose, you can update the image tag and simply do docker-compose up --pull -d this will pull a newer image if any, and recreate the container using that image (so it will stop, remove, create and start the container).

Volumes:

  • /var/lib/unifi: Configuration data (e.g. system.properties)
  • /var/log/unifi: Log files (not really needed)

Note: UniFi Controller writes also data under the /var/run/unifi folder. I do not expose that folder in the Dockerfile because I do not need it to persist its data (there is a PID file and a json file with information about firmware or controller update). But if you think this information should be persisted (e.g. when you delete and recreate the container), you can just add the volume mapping even if the Dockerfile does not define it.

Environment Variables:

  • TZ: TimeZone. (i.e "Europe/Berlin")

If you want to set UniFi Controller or JVM environment options, you can add them as environment data when spawning your container or edit the unifi.default file in the current folder and mount the file as a volume (/etc/default/unifi), if we take the previous examples, that would be:

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

Ports used by the UniFi Controller:

The ports which are not exposed by the container image are marked as such. When not specified, assume the port is exposed.

  • 3478/udp: STUN service (for NAT traversal - WebRTC, SIP, etc.) - I'm not sure for which purpose exactly Ubiquiti uses that service, but it seems that one needs it (at least for switches) to display some information about the managed devices (e.g. on switches it can display in pseudo-real time the status of the ports).
  • 5656-5699/udp: Used for UPA-EDU (not exposed)
  • 6789/tcp: Speed Test (unifi5 only)
  • 8080/tcp: Device command/control (API)
  • 8443/tcp: Web interface + API
  • 8843/tcp: HTTPS portal (Guest WiFi?)
  • 8880/tcp: HTTP portal (Guest WiFi?)
  • 8881/tcp: do not use (reserved, not exposed)
  • 8882/tcp: do not use (reserved, not exposed)
  • ***/udp: UBNT Discovery
  • 27017/tcp and 27117/tcp: Local-bound port for DB server (for MongoDB, not exposed)
  • 54123/udp: ???

A container should at least redirect port 8443/tcp and port 8843/tcp (if usage of guest network is required). Also check the docker-compose.yml file in this repository for a list of useful ports to map in order to have a functional UniFi Controller.

See UniFi - Ports Used

Running the container on low-memory devices

Our image is based on Java 8u131 or newer, therefore the JVM is container aware, it is able to optimise itself to support the CPU and RAM limits set on the container (based on the CGroups limits). Therefore, the JVM will adapt to the resource limits you will give the container (e.g. if you use the --cpus 2.0 or --memory 2048m). Our current approach is that the JVM process could use up to half of the container allowed max memory, the other half can be used by the MongoDB database. Not that for a home usage (one AP and one switch), the memory usage of the container did not exceed 600MB with the current 5.6 branch.

I haven't tried running it on devices with less than 1GB. But on devices with 1GB of RAM or less, you should make sure that the Java process can allocate up to 512MB heap. This means, you will need to set the maximum heap size manually to 512.

In addition, it is recommended to limit the memory of the complete container. E.g. if you have 1GB RAM, limit the memory to 768MB so your system (kernel, etc.) always have some breathing room. And with this setting, there is still enough memory for MongoDB.

Example with limits to 768MB memory:

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

Container Content

This container is based on the Docker Hub official image for Ubuntu 18.04 ( FROM ubuntu:bionic) which is currently using OpenJDK 8. Ubiquiti recommends using either Debian or Ubuntu, so that image looks good. The official Mongo image is based on Debian 7 Wheezy which means using outdated packages and based on OpenJDK 7 by default. Not an option.
We did not *** Alpine because of it's use of the musl libc instead of the GNU libc. The former is not as well tested and I did not want to do extensive tests of MongoDB and Java 8 based on this C library.

Our approach does not strictly follows Docker best practices with respect to micro-services and running one process per container. Our container includes everything the UniFi controller needs, it has notably an embedded MongoDB database, along the 3 Java processes which makes the controller. Therefore we needed a very lightweight sort of init system. The official init script provided by Ubiquiti provides some signal handling and process watching (restarting on exit, etc.). These features are slightly redundant to what Docker can do so we do not reuse their technic but use what Docker provides natively. With our version of the startup script, we can ensure that all services can run as a non-privilege user.

Our solution originally relied on the Docker-provided init daemon (triggered using --init) which provides proper signal handling (catching of SIGTERM, and "propagation" of signals to childs) and zombie reaping. So the init function traps SIGTERM to issue the appropriate stop command to the UniFi controller processes so that they shutdown gracefully. It also prevents zombie to linger and accumulate. However, this solution relied on Docker 1.13+ which is still not widely available (many vendors are still only providing Docker 1.12 or older versions). Therefore, the current solution is to embed a tiny init process, the same that Docker chose to implement its init option: [tini] ([***] It offers the signal handlings and zombie reaping we wanted and it is very tiny (<100KB).

Example seen within the container after it was started

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

Build and Advanced options/configurations

We provide the Dockerfile so of course you can build your own container image. Example build instructions:

console
$ docker build -t jcberthon/unifi .

Before building your container, you can tweak the file unifi.default.

This files contains several parameters which can override the default configuration. The file contains descriptions of those parameters. But you should be aware that by changing them you could break the controller (especially if you try to change the data and log folders, but do not change the volumes of the container).

The possible parameters can be (they are described in the unifi.default file in much details):

  • UNIFI_DATA_DIR: data folder for UniFi Controller, change with caution
  • UNIFI_LOG_DIR: log folder for UniFi Controller, change with caution
  • UNIFI_RUN_DIR: runtime folder for UniFi Controller
  • JAVA_ENTROPY_GATHER_DEVICE: advanced parameter, most people should not require it
  • JVM_MAX_HEAP_SIZE: limit the JVM maximum heap size (for home and SOHO, 512M or 1024M is a good value)
  • JVM_INIT_HEAP_SIZE: minimum JVM heap size (on startup), usually not needed
  • UNIFI_JVM_EXTRA_OPTS: additional JVM parameters can be added here
  • ENABLE_UNIFI: boolean ('yes' or 'no') leave it to 'yes' or unset, as you want the UniFi Controller to run

Changelog

This work was based on the original project [***] However, there is little left of the original project and not really chances of merging. So I've decided to cut the link between the parent project and this one. Anyway, thank you @jacobalberty for getting me kick started on this.

The first change compare to original fork is that I use tini init process and the UniFi Controller init script. So I could remove a lot of unecessary stuff.

In addition, I use the Debian/Ubuntu APT repository from UniFi instead of downloading individual packages, this avoids changing the Dockerfile for each new release from UniFi. I simply need to rebuild my image. In addition, Ubiquiti is using "rolling updates" so that by using the "stable" branch you get always the latest stable release (was 5.4.x when I started, is now 5.6.x at time of edition)

Finally the last change is about security, I'm dropping every possible privileges, I can use user namespaces so that the container processes do not run as root, I'm not binding the container to the host networking but using Docker default bridge network so that I can control which service I expose on my network, it works very good using L3 adoption, it should work with L2 adoption if you expose the port ***/udp but I haven't tried it.

Note that with the latest update, you do not need to have user namespaces activated, I've set-up the Dockerfile so that all services can run as non-root user and I have set a default user (non-root). So you do not need to add special instructions, when you spawn your container, it will run as non-root user. You still need to specify proper permissions on the bind-mounted folder (UID should be 750 and GID should be 750) in order for the processes to have the rights to read or modify data. If you use Docker named volumes (the provided docker-compose.yml does that by default, or you can create them using the docker volume create ... command), you do not need to specify permissions, Docker will do that to you (at least with the local driver, the default one).
Note: If you really want to run as root, you can simply add --user root to the docker run command (or user: root inside the compose file).

A small extra touch, I've added a HEALTHCHECK directive in the Dockerfile, it will require you to build the container image with at least Docker 1.12. But it provides a neat visualisation when querying the container for its state (starting, healthy, etc.) and can be used by others (e.g. Swarm) for better orchestration.

Example:

console
$ docker ps
CONTAINER ID        IMAGE                                 CREATED             STATUS                             NAMES
7bb52a751107        jcberthon/unifi-docker/unifi:latest   44 seconds ago      Up 43 seconds (health: starting)   unifi
$ docker ps
CONTAINER ID        IMAGE                                 CREATED             STATUS                   NAMES
7bb52a751107        jcberthon/unifi-docker/unifi:latest   3 minutes ago       Up 3 minutes (healthy)   unifi
查看更多 unifi 相关镜像 →
linuxserver/unifi logo
linuxserver/unifi
LinuxServer.io提供的Unifi容器,用于运行Unifi控制器以管理Ubiquiti网络设备。
25810M+ pulls
上次更新:6 年前
jacobalberty/unifi logo
jacobalberty/unifi
UniFi无线接入点控制器是一款用于集中管理多台无线接入点的网络管理工具,可实现AP部署配置、用户接入控制、网络状态实时监控、流量数据分析、安全策略制定实施及固件统一更新等功能,支持远程管理与无缝漫游,能有效优化网络性能,助力构建稳定、高效、安全的企业级无线网络环境。
1423100M+ pulls
上次更新:1 个月前
goofball222/unifi logo
goofball222/unifi
运行UniFi Network Application的Docker容器,支持多种稳定版和测试版标签,提供Alpine、Debian、Ubuntu基础镜像选项,支持外部MongoDB集成、自定义SSL证书及环境变量配置,适用于网络设备集中管理与监控。
15710M+ pulls
上次更新:1 个月前
tibmeister/unifi logo
tibmeister/unifi
Ubiquiti UniFi控制器Docker镜像,用于集中管理UniFi网络设备(如路由器、交换机、无线AP)的配置、监控与维护。
10K+ pulls
上次更新:1 个月前
11notes/unifi logo
11notes/unifi
包含MongoDB的Unifi控制器镜像,无需单独数据库;默认以非root用户(1000:1000)运行,具备安全的CI/CD流程、应用级健康检查及自动更新功能,确保安全与稳定。
1910K+ pulls
上次更新:1 个月前
webhippie/unifi logo
webhippie/unifi
用于运行Unifi网络管理系统的Docker镜像,支持集中管理Ubiquiti网络设备,提供便捷的容器化部署与隔离运行环境。
10K+ pulls
上次更新:3 天前

轩辕镜像配置手册

探索更多轩辕镜像的使用方法,找到最适合您系统的配置方式

登录仓库拉取

通过 Docker 登录认证访问私有仓库

Linux

在 Linux 系统配置镜像服务

Windows/Mac

在 Docker Desktop 配置镜像

Docker Compose

Docker Compose 项目配置

K8s Containerd

Kubernetes 集群配置 Containerd

K3s

K3s 轻量级 Kubernetes 镜像加速

Dev Containers

VS Code Dev Containers 配置

MacOS OrbStack

MacOS OrbStack 容器配置

宝塔面板

在宝塔面板一键配置镜像

群晖

Synology 群晖 NAS 配置

飞牛

飞牛 fnOS 系统配置镜像

极空间

极空间 NAS 系统配置服务

爱快路由

爱快 iKuai 路由系统配置

绿联

绿联 NAS 系统配置镜像

威联通

QNAP 威联通 NAS 配置

Podman

Podman 容器引擎配置

Singularity/Apptainer

HPC 科学计算容器配置

其他仓库配置

ghcr、Quay、nvcr 等镜像仓库

专属域名拉取

无需登录使用专属域名

需要其他帮助?请查看我们的 常见问题Docker 镜像访问常见问题解答 或 提交工单

镜像拉取常见问题

轩辕镜像免费版与专业版有什么区别?

免费版仅支持 Docker Hub 访问,不承诺可用性和速度;专业版支持更多镜像源,保证可用性和稳定速度,提供优先客服响应。

轩辕镜像支持哪些镜像仓库?

专业版支持 docker.io、gcr.io、ghcr.io、registry.k8s.io、nvcr.io、quay.io、mcr.microsoft.com、docker.elastic.co 等;免费版仅支持 docker.io。

流量耗尽错误提示

当返回 402 Payment Required 错误时,表示流量已耗尽,需要充值流量包以恢复服务。

410 错误问题

通常由 Docker 版本过低导致,需要升级到 20.x 或更高版本以支持 V2 协议。

manifest unknown 错误

先检查 Docker 版本,版本过低则升级;版本正常则验证镜像信息是否正确。

镜像拉取成功后,如何去掉轩辕镜像域名前缀?

使用 docker tag 命令为镜像打上新标签,去掉域名前缀,使镜像名称更简洁。

查看全部问题→

用户好评

来自真实用户的反馈,见证轩辕镜像的优质服务

用户头像

oldzhang

运维工程师

Linux服务器

5

"Docker访问体验非常流畅,大镜像也能快速完成下载。"

轩辕镜像
镜像详情
...
jcberthon/unifi
官方博客Docker 镜像使用技巧与技术博客
热门镜像查看热门 Docker 镜像推荐
一键安装一键安装 Docker 并配置镜像源
咨询镜像拉取问题请 提交工单,官方技术交流群:1072982923
轩辕镜像面向开发者与科研用户,提供开源镜像的搜索和访问支持。所有镜像均来源于原始仓库,本站不存储、不修改、不传播任何镜像内容。
咨询镜像拉取问题请提交工单,官方技术交流群:
轩辕镜像面向开发者与科研用户,提供开源镜像的搜索和访问支持。所有镜像均来源于原始仓库,本站不存储、不修改、不传播任何镜像内容。
官方邮箱:点击复制邮箱
©2024-2026 源码跳动
官方邮箱:点击复制邮箱Copyright © 2024-2026 杭州源码跳动科技有限公司. All rights reserved.