ngIRCd 28 Docker Compose 部署指南

目标:以 Docker Compose 在内网服务器上部署 ngIRCd 28,覆盖镜像获取(官方 Dockerfile 自建 + 第三方镜像对照)、compose 编排、drop-in 配置、启动验证与运维要点,全部步骤与回显来自真实环境实测。

ngircdngircdIRC即时通讯2026/10/26

ngIRCd 28 Docker Compose 部署指南

目标:以 Docker Compose 在内网服务器上部署 ngIRCd 28,覆盖镜像获取(官方 Dockerfile 自建 + 第三方镜像对照)、compose 编排、drop-in 配置、启动验证与运维要点,全部步骤与回显来自真实环境实测。

一、部署形态与前置说明

ngIRCd 没有官方 Docker 镜像(Docker Hub 上不存在 ngircd 官方仓库),官方提供的是源码树内的 contrib/Dockerfile(需自行构建)与 doc/Container.md 文档。可选形态对照:

形态版本说明
官方 contrib/Dockerfile 自建28(源码)本文主方案:拿到上游最新版,配置通过 drop-in 注入
LinuxServer.io 第三方镜像 lscr.io/linuxserver/ngircd27-r1(截至 2026-10-24 推送的 latest)落后上游一个大版本;s6-overlay 形态,amd64 压缩层约 12.4MB;对版本敏感的场景需知情选用

⚠️ 版本提示:截至本文实测日(2026-10-26),LinuxServer.io 镜像的最新 tag(latest / version-27-r1 / 27-r1-ls169)均为 ngIRCd 27,与上游 28 存在版本差;且其 27-r1-ls169 于 2026-07-11 构建、2026-10-24 仅刷新构建。需要 28 请走自建路线。

二、环境规划

  • 宿主机:Debian 12 x86_64,内网 10.89.58.0/24(专属网段)
  • 端口:宿主机 8133 → 容器 6667(明文 IRC;8128–8132 已被同网段其他服务占用,经实查选定 8133)
  • Compose 项目名:ngircd-28-stack(compose 顶层 name: 字段设定)
  • 网络:复用既有的外部 Docker 网络 ngircd-net(external: true,不随项目销毁)
  • 目录布局:
compose-28/
├── docker-compose.yml
└── conf.d/
    └── 00-server.conf      # 业务配置 drop-in

三、获取并修正 Dockerfile

官方 Dockerfile 在 ngIRCd 28 源码树内(contrib/Dockerfile)。先下载源码包(下载与校验方法见 《Debian 12 安装 ngIRCd 28 指南》 4.2 节,sha256 一致),解包后取出:

tar xf ngircd-28.tar.xz
cp ngircd-28/contrib/Dockerfile .

该官方 Dockerfile 当前无法直接构建成功:其运行阶段安装依赖列表里写的是 libident,而当前 debian:stable-slim(trixie)中该包已更名为 libident0,构建时报 Unable to locate package libident。这是官方文件未跟进 Debian 包更名导致,修正只需一行(libident → libident0),其余内容保持原样:

# 运行阶段 RUN apt-get install 列表中:
		libident0 \

修正前后的完整差异仅此一处(构建阶段 libident-dev 包名未变,无需改动)。

四、构建镜像

在源码树目录(Dockerfile 的 COPY . 需要源码上下文)执行:

cd ngircd-28
sed -i 's/\t\tlibident \\/\t\tlibident0 \\/' contrib/Dockerfile
docker build -t ngircd:28 -f contrib/Dockerfile .

构建为两阶段:build 阶段基于 debian:stable-slim 装编译依赖(autoconf/automake/build-essential/libgnutls28-dev/libident-dev/libpam0g-dev/zlib1g-dev 等),以 bin 用户执行 ./autogen.sh --prefix=/opt/ngircd --with-gnutls --with-iconv --with-ident --with-pam && make && make install,并生成一份最小内置配置;run 阶段仅拷贝 /opt/ngircd 产物并安装运行库。构建完成后的镜像(实测):

$ docker images ngircd:28
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
ngircd       28        <image_id>     <time>           135MB

镜像要点(来自官方 Dockerfile 原文):

  • 入口:catatonit -- /opt/ngircd/sbin/ngircd --nodaemon(init 进程 + 前台运行,PID 1 由 catatonit 充当);
  • 运行用户:irc(uid/gid 39);
  • EXPOSE 6667 6697;
  • 内置健康检查:grep -F ":1A0B " /proc/net/tcp——:1A0B 是 6667 的十六进制形式,通过内核 TCP 表判断端口是否在听,不依赖任何额外工具。

五、编写 docker-compose.yml

name: ngircd-28-stack

services:
  ngircd:
    image: ngircd:28
    container_name: ngircd-28
    restart: unless-stopped
    ports:
      - "8133:6667"
    volumes:
      - ./conf.d:/opt/ngircd/etc/ngircd.conf.d
    networks:
      - ngircd-net

networks:
  ngircd-net:
    external: true

字段说明:

  • name: ngircd-28-stack:compose 项目名(Compose v2 顶层字段),生成的资源均带此前缀;
  • ports: 8133:6667:宿主机 8133 映射容器 6667(容器 TLS 6697 未映射,本文仅用明文口演示);
  • volumes: ./conf.d:/opt/ngircd/etc/ngircd.conf.d:把宿主机 drop-in 目录挂进容器的配置片段目录(见第六节);
  • networks:外部网络 ngircd-net,需预先存在(docker network create ngircd-net 可创建),跨项目共享网络时用 external 模式避免 compose 删除网络。

六、drop-in 配置

6.1 内置主配置与 drop-in 机制

镜像内 /opt/ngircd/etc/ngircd.conf 是官方 Dockerfile 生成的极简配置(仅 ServerUID/ServerGID = irc、Ident=no、PAM=no、SSL CA 路径四项),不应改动镜像内文件。ngIRCd 28 支持配置片段目录(IncludeDir,默认即主配置同目录的 conf.d/ngircd.conf.d),主配置解析后自动追加读取片段目录中的 *.conf——本文把宿主机 conf.d/ 挂到该目录,业务配置全部以 drop-in 注入。

6.2 业务配置 drop-in

conf.d/00-server.conf(实测生效版本):

[Global]
	Name = irc.example.com
	Info = ngIRCd 28 Demo Server (Container)
	AdminInfo1 = ngircd Demo Administrator
	AdminInfo2 = Shanghai, China
	AdminEMail = admin@example.com
	Network = ExampleNet
	MotdPhrase = ngIRCd 28 containerized demo
	Ports = 6667

[Operator]
	Name = admin
	Password = q1w2e3r4

⚠️ MotdPhrase 不要加引号:官方示例模板里 MotdPhrase = "Hello world!" 的引号只是排版风格,ngircd 不剥引号——实测写成 MotdPhrase = "..." 时引号被原样输出到客户端 MOTD(372 行显示 - "ngIRCd 28 containerized demo")。去掉引号即恢复正常。

容器内自检(片段已合并生效,MotdFile 为空说明未配置文件式 MOTD):

$ docker exec ngircd-28 /opt/ngircd/sbin/ngircd --configtest
Ok, dump of your server configuration follows:
  MotdFile = 
  MotdPhrase = ngIRCd 28 containerized demo

七、启动与验证

7.1 启动

docker compose up -d
docker compose ps

实测容器状态(启动后健康检查通过):

NAME        IMAGE        COMMAND                  STATUS                    PORTS
ngircd-28   ngircd:28    "/usr/bin/catatonit …"   Up 29 minutes (healthy)   6697/tcp, 0.0.0.0:8133->6667/tcp, [::]:8133->6667/tcp

7.2 启动日志

docker logs ngircd-28(逐行实测;注意没有 MOTD 文件告警——drop-in 的 MotdPhrase 已生效):

[7:5    0] ngIRCd ??-CHARCONV+IDENT+IPv6+IRCPLUS+PAM+SSL+SYSLOG+ZLIB-x86_64/pc/linux-gnu starting ...
[7:6    0] Using default configuration file "/opt/ngircd/etc/ngircd.conf" ...
[7:6    0] File descriptor limit is 100000; "MaxConnections" is not set.
[7:6    0] Running as user irc(39), group irc(39), with PID 7.
[7:6    0] Not running with changed root directory.
[7:6    0] IO subsystem: epoll (hint size 100, initial maxfd 100, masterfd 3).
[7:6    0] Now listening on [0::]:6667 (socket 6).
[7:6    0] Now listening on [0.0.0.0]:6667 (socket 7).
[7:5    0] Server "irc.example.com" (on "0458280def47") ready.

逐行解读:PID 7(catatonit 之后的业务进程);以 irc(39) 用户运行;文件描述符上限 100000 且 MaxConnections 未设置(自动适配);IO 后端 epoll;IPv4/IPv6 双栈监听 6667。首行的 ?? 见 8.1 节。

7.3 客户端连接验证

从内网另一台机器(10.89.58.x)连接宿主机 8133 端口,发送 NICK ctest + USER ctest 0 * :Compose Test(实测逐行):

:irc.example.com 001 ctest :Welcome to the Internet Relay Network ctest!~ctest@10.89.58.1
:irc.example.com 002 ctest :Your host is irc.example.com, running version ngircd-?? (x86_64/pc/linux-gnu)
:irc.example.com 003 ctest :This server has been started Mon Oct 26 2026 at 09:21:48 (UTC)
:irc.example.com 004 ctest irc.example.com ngircd-?? abBcCFiIoqrRswx abehiIklmMnoOPqQrRstvVz
:irc.example.com 005 ctest NETWORK=ExampleNet :is my network name
:irc.example.com 005 ctest RFC2812 IRCD=ngIRCd CHARSET=UTF-8 CASEMAPPING=ascii PREFIX=(qaohv)~&@%+ CHANTYPES=#&+ CHANMODES=beI,k,l,imMnOPQRstVz CHANLIMIT=#&+:10 :are supported on this server
:irc.example.com 005 ctest CHANNELLEN=50 NICKLEN=9 TOPICLEN=399 AWAYLEN=127 KICKLEN=399 MODES=5 MAXLIST=beI:50 EXCEPTS=e INVEX=I PENALTY FNC :are supported on this server
:irc.example.com 251 ctest :There are 1 users and 0 services on 1 servers
:irc.example.com 254 ctest 1 :channels formed
:irc.example.com 255 ctest :I have 1 users, 0 services and 0 servers
:irc.example.com 265 ctest 1 1 :Current local users: 1, Max: 1
:irc.example.com 266 ctest 1 1 :Current global users: 1, Max: 1
:irc.example.com 250 ctest :Highest connection count: 1 (2 connections received)
:irc.example.com 375 ctest :- irc.example.com message of the day
:irc.example.com 372 ctest :- ngIRCd 28 containerized demo
:irc.example.com 376 ctest :End of MOTD command
:irc.example.com NOTICE ctest :Connection statistics: client 0.0 kb, server 1.4 kb.
ERROR :Closing connection: ctest[~ctest@10.89.58.1] ("")

核对要点:001/002/004 显示服务器身份(ngircd-?? 版本串见 8.1);005 的 NETWORK=ExampleNet、CHANTYPES=#&+ 与 drop-in 配置一致;372 行 MOTD 即 MotdPhrase 内容(无引号);251/254/255 统计行正常。

八、已知问题与排障记录

8.1 版本号显示 ??(官方 Dockerfile 构建产物现象)

自建镜像的 --version、启动日志首行、IRC 004 行中版本号均显示 ngIRCd ??-CHARCONV+... 而非 ngIRCd 28-...。这是官方 contrib/Dockerfile 构建流程的版本探测问题(tarball 源码在容器内构建时版本串未能注入),不影响功能,但无法从协议层直接辨认版本;确认实际版本以所用源码包为准(本文为 28 tarball,sha256 校验一致)。对照:Debian 上源码编译安装(本系列安装篇)无此现象,版本号正常显示为 ngIRCd 28-...。

8.2 构建失败:Unable to locate package libident

官方 Dockerfile 未跟进 Debian trixie 的包更名,按第三节改 libident0 后即可构建。

8.3 MotdPhrase 引号原样输出

见 6.2 节:配置值中的引号不会被剥离,MOTD 会带引号显示;写配置时不要加引号。

8.4 Address mismatch 告警

客户端注册时日志可能出现(实测):

[16:4    4] Address mismatch: 10.89.58.1 != 127.0.1.1
[16:4    4] Possible forgery: 10.89.58.1 resolved to "master", which points to a different address!

这是 ngIRCd 对客户端来源 IP 做 DNS 反解校验:环境中的 DNS 把 10.89.58.1 反解为 master,而该名又解析回 127.0.1.1,地址不一致即告警。不影响连接与注册(后续 User "ctest!~ctest@10.89.58.1" registered 正常),属于环境 DNS 记录问题;生产环境为服务器配置正确的 PTR/hosts 记录即可消除。

8.5 端口选择

宿主机 8128–8132 端口被其他服务占用时 compose up 会报 bind 失败,实查后改用未占用端口(本文 8133)。用 ss -tlnp | grep 8133 预检。

九、日常运维

docker compose ps                 # 状态与健康检查
docker compose logs -f ngircd     # 跟踪日志
docker compose restart ngircd     # 修改 drop-in 后应用配置(推荐)
docker compose down               # 停止并移除容器(external 网络不会被删除)
docker compose up -d              # 重新拉起

改配置后用 restart 应用;不要在运行中的容器里对 ngircd 发 SIGHUP/REHASH 做重载——实测重读配置会关闭并重建全部监听套接字,偶发重绑失败导致「进程在、端口消失」,restart 更可靠。

升级镜像:下载新版源码包 → 重复第三节修正与第四节构建(tag 换新版本号)→ 改 compose 中 image → docker compose up -d 重建。配置与 drop-in 均在宿主机卷上,不受镜像更换影响。

十、参考链接