From 1110d2e44d88d58195e63bff5e56ff209b04d9c0 Mon Sep 17 00:00:00 2001 From: Endial Fang Date: Mon, 12 Jul 2021 09:31:44 +0800 Subject: [PATCH] =?UTF-8?q?[docs:2.4]=E5=88=9D=E5=A7=8B=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E8=AF=B4=E6=98=8E=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 237 ++++++++++++++++++++++++++++++++++++++++++ img/OpenLDAP-logo.gif | Bin 0 -> 8640 bytes 2 files changed, 237 insertions(+) create mode 100644 README.md create mode 100644 img/OpenLDAP-logo.gif diff --git a/README.md b/README.md new file mode 100644 index 0000000..98a1aef --- /dev/null +++ b/README.md @@ -0,0 +1,237 @@ +# OpenLDAP + +针对 [OpenLDAP](https://www.openldap.org) 应用的 Docker 镜像,用于提供 OpenLDAP 服务。容器详细使用说明可参考仓库:[Gitee](https://www.gitee.com/endial/studylife.git) 或 [Github](https://www.github.com/endial/studylife.git)中`服务器运维`相应文档。 + +使用说明可参照:[官方说明](https://www.openldap.org/doc) + +OpenLDAP-logo + +**版本信息:** + +- 2.4、latest + +**镜像信息:** + +* 镜像地址: + - Aliyun仓库:registry.cn-shenzhen.aliyuncs.com/colovu/openldap + - DockerHub:colovu/openldap + * 依赖镜像:debian:buster-slim + +> 后续相关命令行默认使用`[Docker Hub](https://hub.docker.com)`镜像服务器做说明 + + + +## TL;DR + +Docker 快速启动命令: + +```shell +# 从 Docker Hub 服务器下载镜像并启动 +$ docker run -d docker.io/colovu/openldap +``` + + + +Docker-Compose 快速启动命令: + +```shell +# 从 Gitee 下载 Compose 文件 +$ curl -sSL -o https://gitee.com/colovu/docker-openldap/raw/master/docker-compose.yml + +# 从 Github 下载 Compose 文件 +$ curl -sSL -o https://raw.githubusercontent.com/colovu/docker-openldap/master/docker-compose.yml + +# 创建并启动容器 +$ docker-compose up -d +``` + + + +--- + + + +## 默认对外声明 + +### 端口 + +- 8389:普通 LDAP 通讯端口 +- 8639:TLS 加密 LDAP 通讯端口 + + + +### 数据卷 + +镜像默认提供以下数据卷定义,默认数据分别存储在自动生成的应用名对应`openldap`子目录中: + +```shell +/var/datalog # 数据操作日志文件 +/srv/conf # 配置文件 +/srv/data # 数据文件,主要存放应用数据 +/srv/cert # 证书文件存放目录 + +/var/log # 日志输出 +/var/run # 系统运行时文件,如 PID 文件 +``` + +如果需要持久化存储相应数据,需要**在宿主机建立本地目录**,并在使用镜像初始化容器时进行映射。宿主机相关的目录中如果不存在对应应用`openldap`的子目录或相应数据文件,则容器会在初始化时创建相应目录及文件。 + + + +## 使用镜像 + +以下使用镜像的样例中,我们使用 MariaDB Galera 实例连接 OpanLDAP 并进行用户认证. + +### 定义网络 + +定义一个私有的网络`my-network`,以方便后续应用容器的连接: + +```shell +$ docker network create my-network --driver bridge +``` + +### 启动 OpenLDAP 容器 + +使用之前定义的`my-network`网络初始化 OpenLDAP 容器: + +```shell +$ docker run --detach --rm --name openldap \ + --network my-network \ + --env LDAP_BIND_UID=bind \ + --env LDAP_BIND_PASSWORD=bindpassword \ + --env LDAP_USERS=customuser \ + --env LDAP_PASSWORDS=custompassword \ + colovu/openldap:latest +``` + +### 启动 MariaDB Galera 容器 + +使用之前定义的`my-network`网络初始化 MariaDB Galera 容器: + +```shell +$ docker run --detach --rm --name mariadb-galera \ + --network my-network \ + --env MARIADB_ROOT_PASSWORD=root-password \ + --env MARIADB_GALERA_MARIABACKUP_PASSWORD=backup-password \ + --env MARIADB_USER=customuser \ + --env MARIADB_DATABASE=customdatabase \ + --env MARIADB_ENABLE_LDAP=yes \ + --env LDAP_URI=ldap://openldap:8389 \ + --env LDAP_BASE=dc=example,dc=org \ + --env LDAP_BIND_DN=uid=bind,ou=Manager,dc=example,dc=org \ + --env LDAP_BIND_PASSWORD=bindpassword \ + bitnami/mariadb-galera:latest +``` + +### 启动 MariaDB client 容器验证 + +创建一个新的 MariaDB client 容器,进行验证客户端是否可以进行认证: + +```shell +$ docker run -it --rm --name mariadb-client \ + --network my-network \ + bitnami/mariadb-galera:latest mysql -h mariadb-galera -u customuser -D customdatabase -pcustompassword +``` + + +## 容器配置 + +在初始化 `OpenLDAP` 容器时,如果没有预置配置文件,可以在命令行中设置相应环境变量对默认参数进行修改。类似命令如下(配置环境变量`APP_ENV_KEY_NAME`的值为`key_value`): + +```shell +$ docker run -d -e "APP_ENV_KEY_NAME=key_value" colovu/openldap +``` + + + +### 常规配置参数 + +常规配置参数用来配置容器基本属性,一般情况下需要设置,主要包括: + +- `LDAP_ROOT`:默认值:**dc=example,dc=org**。设置数据库根 DN +- `LDAP_ORGNIZATION_NAME`:默认值:**Colovu Lab**。设置数据库所属组织名 +- `LDAP_ROOT_USERNAME`:默认值:**root**。设置 RootDN 用户名 +- `LDAP_ROOT_PASSWORD`:默认值:**rootpassword**。设置 RootDN 用户密码 +- `LDAP_BIND_UID`:默认值:**bind**。设置 Binder 用户 UID +- `LDAP_BIND_PASSWORD`:默认值:**bindpassword**。设置 Binder 用户密码 +- `LDAP_ADMIN_UID`:默认值:**admin**。设置 Admin 用户 UID +- `LDAP_ADMIN_PASSWORD`:默认值:**adminpassword**。设置 Admin 用户密码 +- `LDAP_ADMIN_MAIL`:默认值:**admin@example.com**。设置 Admin 用户邮箱 + + + +### 常规可选参数 + +如果没有必要,可选配置参数可以不用定义,直接使用对应的默认值,主要包括: + +- `ENV_DEBUG`:默认值:**false**。设置是否输出容器调试信息。可选值:no、true、yes +- `LDAP_BIND_GIVEN_NAME`:默认值:**false**。设置 Binder 用户名字 +- `LDAP_BIND_SURNAME`:默认值:**false**。设置 Binder 用户姓氏 +- `LDAP_ADMIN_GIVEN_NAME`:默认值:**false**。设置 Admin 用户名字 +- `LDAP_ADMIN_SURNAME`:默认值:**false**。设置 Admin 用户姓氏 +- `LDAP_PORT_NUMBER`:默认值:**8389**。非加密方式通讯端口 +- `LDAP_LDAPS_PORT_NUMBER`:默认值:**8636**。TLS 加密方式通讯端口 +- `LDAP_EXTRA_SCHEMAS`:默认值:**cosine,inetorgperson,nis**。设置加载的 Schema 文件 +- `LDAP_EXTRA_MODULES`:默认值:**accesslog**。设置加载的动态库文件(back_hdb / back_monitor / refint / memberof 默认强制加载) +- `LDAP_CUSTOM_LDIF_DIR`:默认值:**initdb.d/ldifs**。设置用户自定义 LDIF 文件相对路径 +- `LDAP_CUSTOM_SCHEMA_DIR`:默认值:**false**。设置用户自定义 Schema 文件相对路径 +- `LDAP_ULIMIT_NOFILES`:默认值:**1024**。设置默认的系统最大打开文件句柄数,用于节省内存 +- `LDAP_SKIP_DEFAULT_TREE`:默认值:**no**。设置是否初始化默认DN信息。可选值:no、yes +- `LDAP_USERS`:默认值:**user01,user02**。初始化时创建默认用户列表 +- `LDAP_PASSWORDS`:默认值:**password1,password2**。初始化时创建默认用户对应的密码 +- `LDAP_USER_OU`:默认值:**users**。初始化时创建默认用户所属 OU +- `LDAP_USER_GROUP`:默认值:**readers**。初始化时创建默认用户所属组 + + + +### 集群配置参数 + +配置服务为集群工作模式时,通过以下参数进行配置: + +- + + + +### TLS配置参数 + +配置服务使用 TLS 加密时,通过以下参数进行配置: + +- `LDAP_ENABLE_TLS`:默认值:**no**。设置是使用TLS加密。可选值:no、yes +- `LDAP_TLS_CERT_FILE`:默认值:**无**。设置 CERT 文件路径 +- `LDAP_TLS_KEY_FILE`:默认值:**无**。设置 KEY 文件路径 +- `LDAP_TLS_CA_FILE`:默认值:**无**。设置 CA 文件路径 +- `LDAP_TLS_DH_PARAMS_FILE`:默认值:**无**。设置 DH 参数文件路径 + + + +## 安全 + +### 容器安全 + +本容器默认使用`non-root`运行应用,以加强容器的安全性。在使用`non-root`用户运行容器时,相关的资源访问会受限;应用仅能操作镜像创建时指定的路径及数据。使用`non-root`方式的容器,更适合在生产环境中使用。 + +如果需要赋予容器内应用访问外部设备的权限,可以使用以下两种方式: + +- 启动参数增加`--privileged=true`选项 +- 针对特定权限需要使用`--cap-add`单独增加特定赋权,如:ALL、NET_ADMIN、NET_RAW + +如果需要切换为`root`方式运行应用,可以在启动命令中增加`-u root`以指定运行的用户。 + + + +## 注意事项 + +- 容器中应用的启动参数不能配置为后台运行,如果应用使用后台方式运行,则容器的启动命令会在运行后自动退出,从而导致容器退出 + + + +## 更新记录 + +- 2021/7/1 (2.4): 初始版本,基于 OpenLDAP 2.4.59 + + + +---- + +本文原始来源 [Endial Fang](https://github.com/colovu) @ [Github.com](https://github.com) + diff --git a/img/OpenLDAP-logo.gif b/img/OpenLDAP-logo.gif new file mode 100644 index 0000000000000000000000000000000000000000..eafa68ca6d11183a7f220d6339203719c6ef2bfe GIT binary patch literal 8640 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 Lyv8UD0#N=R@lu37 literal 0 HcmV?d00001