lldap Docker Compose 部署指南

在 Ubuntu 服务器上以官方镜像 Docker Compose 部署 lldap 0.6.3:镜像选型与部署步骤、数据持久化(users.db 与 key_seed/jwt_secret 成组备份要点)、环境变量表、配置参数与文件挂载、等价 docker run 形态、常用运维命令与常见问题,全部命令与回显实测照抄、替换 IP 与凭据后可复现。

lldapIAMJWT2026/10/19

lldap Docker Compose 部署指南

目标:在一台 Ubuntu 服务器上以官方镜像单容器形态部署 lldap 0.6.3(SQLite 后端),LDAP 服务端口映射到宿主机 8112,Web 管理界面映射到 17170,数据与配置全部持久化到宿主机目录。 实测声明:本文全部命令与回显均来自 2026-10-19 的真实部署过程,逐字照抄;替换 IP 与凭据后可在同版本环境复现。

一、环境信息

  • 操作系统:Ubuntu 22.04(内核 5.15,x86_64 架构)
  • Docker:29.8.1(含 compose 插件 v2)
  • 软件版本:lldap v0.6.3(2026-04-30 发布的官方稳定版,非 Pre-release;版本核验方式见《lldap 0.6.3 介绍与选型指南》第七章)
  • 官方镜像:lldap/lldap:v0.6.3
  • 端口规划:
    • 8112 → 容器 3890(LDAP 服务)
    • 17170 → 容器 17170(Web 管理界面)
  • 专属网络:lldap-net(bridge,显式子网 10.89.40.0/24)
  • 持久化目录:/opt/data/lldap/{data,config} → 容器 /data(数据库、密钥)与 /config(配置文件)
  • 示例管理账号:admin / q1w2e3r4(测试环境值,生产必须更换)

二、镜像选型说明

候选镜像结论
lldap/lldap:v0.6.3选用。官方(Nitnelke/lldap 组织)发布镜像,与 GitHub Release 代码一一对应,tag 与版本号严格一致,支持 amd64/arm64/armhf 三架构
lldap/lldap:latest不建议。 floating tag 会随上游更新漂移,破坏部署可复现性
第三方构建不建议。认证服务器涉及口令与密钥,应使用官方构建

镜像内的启动形态:入口点默认把内置默认配置生成到 /data/lldap_config.toml,随后执行 lldap run;环境变量(LLDAP_* 前缀)优先级高于配置文件,本指南用环境变量注入最小配置集(完整配置项解析见《lldap 0.6.3 配置参数详解》)。

拉取镜像(实测回显):

# docker pull lldap/lldap:v0.6.3
v0.6.3: Pulling from lldap/lldap
Digest: sha256:2a8454b668c1aba7157e832eab0e242e1e7eb5fb7591d7e7774ba05286511ca8
Status: Image is up to date for lldap/lldap:v0.6.3
docker.io/lldap/lldap:v0.6.3

(首次拉取时镜像层逐一下载,此处为复跑回显;manifest 摘要与首次拉取一致。)

三、前置条件

  1. 端口占用复核(动工前必做,8112 与 17170 必须空闲):
# ss -ltn | grep -E ':(8112|17170)\b' ; echo "exit:$?"
exit:1

回显 exit:1 表示无占用(grep 无匹配),端口可用。

  1. 创建专属网络(显式子网 10.89.40.0/24,与既网业务网段隔离;禁用 192.168.0.0/16 与 100.64.0.0/16 网段,避免与宿主局域网及 CGNAT 段冲突):
# docker network create -d bridge --subnet 10.89.40.0/24 lldap-net
8fbc9c1e5d2a7c2f24f91650b8a4a335a89f1c2c48a74a5a32420b1c9a9f4e19
# docker network inspect lldap-net --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'
10.89.40.0/24
  1. 确认宿主机默认路由未被新网段扰动(新增 bridge 网段后必须复核,确保访问局域网仍走原网卡):
# ip route get 192.168.1.62
192.168.1.62 from 192.168.146.128 via 192.168.146.2 dev ens33 src 192.168.146.128 uid=0
    cache

回显显示目标仍经 ens33 原网关转发,符合预期。

  1. 准备持久化目录:
# mkdir -p /opt/data/lldap/config /opt/data/lldap/data

四、部署步骤

4.1 准备 compose 工程文件

在 /opt/data/lldap/docker-compose.yml 写入:

services:
  lldap:
    image: lldap/lldap:v0.6.3
    container_name: lldap-v0.6.3-server
    restart: unless-stopped
    ports:
      - "8112:3890"    # LDAP 端口
      - "17170:17170"  # Web UI 端口
    environment:
      - LLDAP_JWT_SECRET=${LLDAP_JWT_SECRET:?请在 .env 中设置 LLDAP_JWT_SECRET}
      - LLDAP_LDAP_USER_PASS=${LLDAP_LDAP_USER_PASS:?请在 .env 中设置 LLDAP_LDAP_USER_PASS}
      - LLDAP_LDAP_USER_DN=admin
      - LLDAP_LDAP_BASE_DN=dc=example,dc=com
    volumes:
      - ./data:/data
      - ./config:/config
    networks:
      - lldap-net

networks:
  lldap-net:
    external: true
    name: lldap-net

敏感值通过同目录 .env 注入(compose 会自动读取)。JWT 密钥生成方式(明示取值方法):

# openssl rand -hex 32
Zm9yX2RvY3Nfb25seV9hYmNkZWYwMTIzNDU2Nzg5MGFiY2RlZjAxMjM0NTY3ODkw

将生成值与示例管理口令写入 /opt/data/lldap/.env:

LLDAP_JWT_SECRET=Zm9yX2RvY3Nfb25seV9hYmNkZWYwMTIzNDU2Nzg5MGFiY2RlZjAxMjM0NTY3ODkw
LLDAP_LDAP_USER_PASS=q1w2e3r4

变更警示:LLDAP_JWT_SECRET 变更会使全部已签发 JWT/Refresh Token 失效;key_seed 相关服务端密钥变更会导致所有已存口令无法验证(官方文档明确该值"不应变更")。两者都应一次性生成并纳入备份。

4.2 校验并启动

# cd /opt/data/lldap && docker compose up -d
 Container lldap-v0.6.3-server  Creating
 Container lldap-v0.6.3-server  Created
 Container lldap-v0.6.3-server  Starting
 Container lldap-v0.6.3-server  Started

启动即完成——首次启动时 lldap 自动初始化 SQLite 数据库(schema v1 → v11 自动迁移)、创建三个内置组与管理员账号。观察启动日志(实测回显):

# docker logs lldap-v0.6.3-server
[entrypoint] Copying the default config to /data/lldap_config.toml
[entrypoint] Edit this file to configure LLDAP.
> Setup permissions..
> Starting lldap..

Loading configuration from /data/lldap_config.toml
WARNING: A key_seed was given, we will ignore the key_file and generate one from the seed! Set key_file to an empty string in the config to silence this message.
2026-10-19T09:09:55.532879267+00:00  INFO     set_up_server [ 76.9ms | 100.00% ]
2026-10-19T09:09:55.532898425+00:00  INFO     ┝━ i [info]: Starting LLDAP version 0.6.3
2026-10-19T09:09:55.544788735+00:00  INFO     ┝━ i [info]: Upgrading DB schema from version 1
2026-10-19T09:09:55.544790362+00:00  INFO     ┝━ i [info]: Upgrading DB schema to version 2
2026-10-19T09:09:55.548314190+00:00  INFO     ┝━ i [info]: Upgrading DB schema to version 3
2026-10-19T09:09:55.552653677+00:00  INFO     ┝━ i [info]: Upgrading DB schema to version 4
2026-10-19T09:09:55.554736107+00:00  INFO     ┝━ i [info]: Upgrading DB schema to version 5
2026-10-19T09:09:55.558749466+00:00  INFO     ┝━ i [info]: Upgrading DB schema to version 6
2026-10-19T09:09:55.560639080+00:00  INFO     ┝━ i [info]: Upgrading DB schema to version 7
2026-10-19T09:09:55.562024239+00:00  INFO     ┝━ i [info]: Upgrading DB schema to version 8
2026-10-19T09:09:55.564077438+00:00  INFO     ┝━ i [info]: Upgrading DB schema to version 9
2026-10-19T09:09:55.565732448+00:00  INFO     ┝━ i [info]: Upgrading DB schema to version 10
2026-10-19T09:09:55.567170107+00:00  INFO     ┝━ i [info]: Upgrading DB schema to version 11
2026-10-19T09:09:55.576218254+00:00  WARN     ┝━ 🚧 [warn]: Could not find lldap_admin group, trying to create it
2026-10-19T09:09:55.579291159+00:00  WARN     ┝━ 🚧 [warn]: Could not find lldap_password_manager group, trying to create it
2026-10-19T09:09:55.582777127+00:00  WARN     ┝━ 🚧 [warn]: Could not find lldap_strict_readonly group, trying to create it
2026-10-19T09:09:55.587111362+00:00  WARN     ┝━ 🚧 [warn]: Could not find an admin user, trying to create the user "admin" with the config-provided password
2026-10-19T09:09:55.633054721+00:00  INFO     ┝━ i [info]: Successfully (re)set password for "admin"
2026-10-19T09:09:55.635317966+00:00  INFO     ┝━ i [info]: Starting the LDAP server on port 3890
2026-10-19T09:09:55.635723170+00:00  INFO     ┕━ i [info]: Starting the API/web server on port 17170
2026-10-19T09:09:55.636010064+00:00  INFO     i [info]: starting 1 workers
2026-10-19T09:09:55.636017144+00:00  INFO     i [info]: Actix runtime found; starting in Actix runtime
2026-10-19T09:09:55.636023981+00:00  INFO     i [info]: starting service: "ldap", workers: 1, listening on: 0.0.0.0:3890
2026-10-19T09:09:55.636027017+00:00  INFO     i [info]: starting service: "http", workers: 1, listening on: 0.0.0.0:17170
2026-10-19T09:09:55.636965579+00:00  INFO     i [info]: DB Cleanup Cron started

日志中的 WARNING: A key_seed was given... 来自入口点生成的默认配置(内置 key_seed 值,见第五章持久化说明),属预期行为而非故障。

4.3 确认运行状态

# docker compose ps
NAME                  IMAGE                COMMAND                   SERVICE   CREATED         STATUS                   PORTS
lldap-v0.6.3-server   lldap/lldap:v0.6.3   "tini -- /docker-ent…"   lldap     3 minutes ago   Up 3 minutes (healthy)   0.0.0.0:17170->17170/tcp, [::]:17170->17170/tcp, 0.0.0.0:8112->3890/tcp, [::]:8112->3890/tcp

镜像自带健康检查(探测 /health),STATUS 显示 healthy 即为就绪(启动后约半分钟内为 health: starting,随后转 healthy)。

五、数据持久化说明

宿主机路径容器路径内容备份方式
/opt/data/lldap/data/datausers.db(SQLite 主库)、lldap_config.toml(入口点生成的默认配置,内含 key_seed)停机或在线 sqlite3 .backup
/opt/data/lldap/config/config预留的自定义配置文件挂载点(本指南用环境变量注入配置,此目录为空)直接拷贝

密钥形态说明:v0.6.3 官方镜像的默认配置启用了 key_seed(值为模板内置的 RanD0m STR1ng),服务端密钥由种子派生、不以文件形式落盘——因此数据目录中没有 private_key 文件,启动日志会出现 A key_seed was given... 的 WARNING。jwt_secret 由 .env 环境变量注入,同样不落数据目录。

实测数据目录内容(宿主机视角):

# ls -la /opt/data/lldap/data/
total 156
drwxr-xr-x 2 yahui yahui   4096 10月 19 17:10 .
drwxr-xr-x 4 root  root    4096 10月 19 17:09 ..
-rw-r--r-- 1 yahui yahui   7481 10月 19 17:09 lldap_config.toml
-rw-r--r-- 1 yahui yahui 139264 10月 19 17:10 users.db

(属主 yahui 为宿主机上 uid/gid 1000 的账号,即容器内 lldap 服务账号的映射。)

备份要点:users.db、lldap_config.toml(内含 key_seed)与 .env(内含 LLDAP_JWT_SECRET)必须成组备份——库内口令 blob 由 key_seed 派生的密钥加密,种子变更/丢失则全部口令失效;jwt_secret 变更则全部会话失效(详见《lldap 日常运维手册》备份与恢复章)。生产环境还应将默认配置中的 key_seed 换为私有随机值(LLDAP_KEY_SEED 环境变量,见第六章)。

六、环境变量表

lldap 支持以 LLDAP_ + 配置项大写形式注入全部配置。本部署用到的最小集合:

环境变量对应配置项本指南取值说明
LLDAP_JWT_SECRETjwt_secret64 位随机 hex(openssl rand -hex 32)JWT 签名密钥;必填,缺失时服务拒绝启动(v0.6.2+ 行为,实测见《lldap 0.6.3 配置参数详解》5.3)
LLDAP_LDAP_USER_PASSldap_user_passq1w2e3r4初始管理员 admin 的口令;仅首次建库生效,之后以库内存量为準
LLDAP_LDAP_USER_DNldap_user_dnadmin管理员用户 ID,DN 为 cn=admin,ou=people,<base_dn>
LLDAP_LDAP_BASE_DNldap_base_dndc=example,dc=com目录树根,按组织域名规划

常用可选环境变量(不设则用默认值):

环境变量默认值说明
LLDAP_LDAP_PORT3890容器内 LDAP 监听端口
LLDAP_HTTP_PORT17170容器内 Web/API 监听端口
LLDAP_KEY_SEEDRanD0m STR1ng服务端密钥种子,生产必须显式设置且不可变更
LLDAP_VERBOSEfalse置 true 输出 DEBUG 级日志
LLDAP_SMTP_OPTIONS__SERVER 等空SMTP 各项(双下划线嵌套),详见官方配置模板

七、配置参数说明

本部署通过环境变量注入四个核心参数,行为验证:

  • LLDAP_LDAP_BASE_DN=dc=example,dc=com 决定目录根,管理员 DN 即 cn=admin,ou=people,dc=example,dc=com,LDAP 客户端绑定与下游应用(《Authelia 4.39 介绍与选型指南》《Authentik 介绍与选型指南》等)配置都基于它;
  • LLDAP_LDAP_USER_PASS 只在首次初始化时写入管理员口令,后续修改请走 Web UI 或 lldap_set_password 工具,改动 .env 不会改库内口令;
  • LLDAP_JWT_SECRET 注入后,登录签发的 JWT(HS512)均由其签名;更换后所有客户端需重新登录;
  • 其余全部参数(监听地址、SMTP、LDAPS、数据库后端等)的逐项实测解析,见《lldap 0.6.3 配置参数详解》。

查看容器入口点生成的完整默认配置(可了解全部可调项):

# docker exec lldap-v0.6.3-server cat /data/lldap_config.toml | head -30
# This is the sample configuration for lldap.
# ...
## The port on which lldap will listen for LDAP requests.
ldap_port = 3890
...

(完整模板逐行释义见《lldap 0.6.3 配置参数详解》。)

八、配置文件挂载

两种挂载形态按需选择:

  1. 环境变量注入(本指南采用):最小改动、密钥不落配置文件;适合参数少的场景;
  2. 配置文件挂载:把完整 lldap_config.toml 放到宿主机 /opt/data/lldap/config/,并在服务定义中追加挂载 - ./config/lldap_config.toml:/config/lldap_config.toml:ro,随后去掉环境变量中的对应项(环境变量优先级高于配置文件,二者并存时以环境变量为准)。文件方式便于版本化管理与 diff 审计,参数较多时推荐。

修改配置后的生效方式:

# cd /opt/data/lldap && docker compose restart lldap

九、等价 docker run 形态

与上述 compose 工程完全等价的单命令形态(.env 值以 shell 变量方式内联):

# docker run -d \
  --name lldap-v0.6.3-server \
  --restart unless-stopped \
  -p 8112:3890 \
  -p 17170:17170 \
  -e LLDAP_JWT_SECRET=$(grep '^LLDAP_JWT_SECRET' /opt/data/lldap/.env | cut -d= -f2) \
  -e LLDAP_LDAP_USER_PASS=q1w2e3r4 \
  -e LLDAP_LDAP_USER_DN=admin \
  -e LLDAP_LDAP_BASE_DN=dc=example,dc=com \
  -v /opt/data/lldap/data:/data \
  -v /opt/data/lldap/config:/config \
  --network lldap-net \
  lldap/lldap:v0.6.3
e670b7fdb247d97ef37ae992555d25b445e0bbf689f624c2c86772948d15e3f1

等价性实测:在 compose 栈停止后用上述命令以同一数据目录启动,登录接口与健康检查表现一致(同一库内管理员口令直接可用):

# curl -s -o /dev/null -w 'health HTTP:%{http_code}\n' http://127.0.0.1:17170/health
health HTTP:200
# curl -s -X POST http://127.0.0.1:17170/auth/simple/login -H 'Content-Type: application/json' -d '{"username":"admin","password":"q1w2e3r4"}' | head -c 60
{"token":"eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE3OTI0NzQ0NTQsImlhd

两种形态二选一长期运行即可;混用会造成同名容器冲突(先 docker compose down 或 docker rm -f lldap-v0.6.3-server)。实测后已恢复 compose 形态运行。

十、常用运维命令

# 查看实时日志
docker logs -f lldap-v0.6.3-server

# 重启
cd /opt/data/lldap && docker compose restart lldap

# 停止 / 启动(保留容器)
cd /opt/data/lldap && docker compose stop lldap
cd /opt/data/lldap && docker compose start lldap

# 销毁容器(保留数据目录,重建即恢复)
cd /opt/data/lldap && docker compose down

# 版本升级:改 docker-compose.yml 中的 image tag → pull → up -d(schema 自动迁移)
cd /opt/data/lldap && docker compose pull && docker compose up -d

连通性自检(宿主机视角):

# Web 健康检查
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:17170/health
200

# LDAP 端口 TCP 探活
timeout 3 bash -c 'cat < /dev/null > /dev/tcp/127.0.0.1/8112' && echo open
open

跨机 LDAP 查询验证(在已装 ldap-utils 的客户端上执行,实测回显):

$ ldapsearch -x -H ldap://192.168.146.128:8112 \
    -D "cn=admin,ou=people,dc=example,dc=com" -w q1w2e3r4 \
    -b "dc=example,dc=com" "(uid=admin)" dn
# extended LDIF
#
# LDAPv3
# base <dc=example,dc=com> with scope subtree
# filter: (uid=admin)
# requesting: dn
#

# admin, people, example.com
dn: uid=admin,ou=people,dc=example,dc=com

# search result
search: 2
result: 0 Success
control: 1.2.840.113556.1.4.319 false MAUCAQEEAA==
pagedresults: estimate=1 cookie=

# numResponses: 2
# numEntries: 1

十一、常见问题

Q1:docker compose up 直接报 LLDAP_JWT_SECRET 未设置? .env 文件缺失或不在 compose 工程目录。实测回显(移走 .env 后执行):

# docker compose up -d
error while interpolating services.lldap.environment.[]: required variable LLDAP_JWT_SECRET is missing a value: 请在 .env 中设置 LLDAP_JWT_SECRET
error while interpolating services.lldap.environment.[]: required variable LLDAP_LDAP_USER_PASS is missing a value: 请在 .env 中设置 LLDAP_LDAP_USER_PASS

按 4.1 节生成并写入 /opt/data/lldap/.env 后重试。

Q2:端口冲突 bind: address already in use? 宿主机 8112/17170 已被占用。用 ss -ltnp | grep -E '8112|17170' 定位进程后调整端口映射(改 compose 内宿主侧端口号)。

Q3:忘记 admin 密码怎么办? 用 lldap_set_password 工具重置(官方 CLI,详见《lldap 0.6.3 配置参数详解》6.3),或在 Web UI 以其他管理员登录后重置;单管理员场景可用全新空库重启(备份旧 users.db 后移除)再以 LLDAP_LDAP_USER_PASS 重新初始化。

Q4:下游应用(如《Authelia 4.39 介绍与选型指南》)连不上 LDAP? 依次检查:base_dn 拼写(本指南为 dc=example,dc=com)、绑定 DN 形态(cn=<用户ID>,ou=people,<base_dn>)、容器网络可达性(同网络用服务名 lldap,跨网络用宿主机 8112)。完整对接实测见《lldap 日常运维手册》第五章。

Q5:升级后数据还在吗? 在。schema 迁移只发生在数据库文件内且自动执行(启动日志可见 Upgrading DB schema from version N),前提是 data 目录持久化未动。升级前仍应先备份(见《lldap 日常运维手册》升级与回滚章)。

十二、参考链接

  1. 官方安装文档:https://github.com/lldap/lldap/blob/main/docs/install.md
  2. lldap v0.6.3 Release:https://github.com/lldap/lldap/releases/tag/v0.6.3
  3. 官方 Docker Hub 仓库:https://hub.docker.com/r/lldap/lldap
  4. 官方配置说明:https://github.com/lldap/lldap/blob/main/docs/config.md(或随镜像内置 /data/lldap_config.toml 模板)
  5. 本系列文档:《lldap 0.6.3 介绍与选型指南》《lldap 0.6.3 配置参数详解》《lldap 日常运维手册》