docker部署wildduck邮件系统(踩坑版)

一、部署方式
1、手动安装

git拉取项目

复制代码
$ git clone https://github.com/zone-eu/wildduck.git
$ cd wildduck

安装依赖

复制代码
从 npm 安装依赖项

$ npm install --production

要使用默认配置文件,请运行以下命令:

复制代码
node server.js

或者,如果您想用自己的配置选项覆盖默认配置选项,请运行以下命令(自定义配置文件将与默认配置文件合并,因此请仅指定您要更改的值):

复制代码
node server.js --config=/etc/wildduck.toml

调用API创建用户,发送邮件,api接口如下

复制代码
https://docs.wildduck.email/docs/category/wildduck-api

2、docker镜像安装

使用docker拉取镜像

复制代码
docker pull ghcr.io/zone-eu/wildduck

运行

复制代码
该镜像配置为使用默认配置文件

docker run ghcr.io/zone-eu/wildduck

由于容器内部缺少mongodb某些配置项,此操作很可能会失败。要将自定义配置选项/文件传递给 Docker 镜像中的 WildDuck,可以使用以下两种策略:redislocalhost

1)使用wild-config传递APPCONF_*环境变量以配置选项

复制代码
要设置自定义mongo主机redis,并配置FQDN用于接收电子邮件的域名:
FQDN='example.com'
MAIL_DOMAIN='mail.example.com'
docker run \ 
-e APPCONF_dbs_mongo='mongodb://mongo:27017/' \
-e APPCONF_dbs_redis='redis://redis:6379/3' \
-e APPCONF_smtp_setup_hostname=$FQDN \
-e APPCONF_log_gelf_hostname=$FQDN \
-e APPCONF_imap_setup_hostname=$FQDN \
-e APPCONF_emailDomain=$MAIL_DOMAIN \
ghcr.io/zone-eu/wildduck

2)使用自定义配置文件挂载 Docker 卷:

复制代码
/wildduck/config要替换Docker 镜像中的默认配置文件夹( )。

docker run -v '/config/from/host:/wildduck/config' ghcr.io/zone-eu/wildduck

3、git拉取wildduck-docker版,docker内网部署

基于前面踩坑,内网缺少应该DNS解析,所以我们要先安装应该解析工具 dnsmasq


前置工具安装

复制代码
安装 dnsmasq
sudo apt update
sudo apt install -y dnsmasq
配一份本地域解析(把 IP 换成你的 VM IP)
sudo tee /etc/dnsmasq.d/wildduck.conf >/dev/null <<'EOF'
address=/test.mail.com/192.168.77.78
host-record=mail.test.mail.com,192.168.77.78
mx-host=test.mail.com,mail.test.mail.com,10
EOF
sudo systemctl restart dnsmasq
让 ZoneMTA 容器使用这个 DNS
最简单是在 doker-compose.yml 里给 zonemta 服务加:
dns:
  - 192.168.77.78
然后重建:
sudo docker compose up -d --force-recreate

这样 test.mail.com(自己定义的) 的 MX 就能被查到,ZoneMTA 才能把邮件投递回你本机的 Haraka/WildDuck,Bob(用户) 的 INBOX 才会出现邮件。


内网部署访问的架构

复制代码
Windows(宿主机)
 └── Apifox
      |
      |  HTTP (REST API)
      v
VM 虚拟机(Linux)
 ├── WildDuck API     : 3000
 ├── WildDuck SMTP   : 587
 ├── MongoDB
 ├── Redis
 └── Haraka (SMTP)

项目部署

1)项目拉取

复制代码
git clone https://github.com/nodemailer/wildduck-dockerized/tree/master
cd wildduck-dockerized

运行./setup.sh

会让你设置主机名和邮箱域名

2)镜像拉取

我VM上网络不好,每次拉取不了,我才用的策略是,把项目所需要的docker镜像列出来,放到txt文件中

然后我再到windows的powershell中是docker pull命令拉取,再打包tar文件夹,再通过VM共享文件夹传到VM中,再使用docker解压运行

(这个过程是我让GPT帮我写命令的)

复制代码
traefik:3.3.4
redis:alpine
ghcr.io/zone-eu/haraka-plugin-wildduck:5.8.22
mongo
ghcr.io/zone-eu/wildduck:1.45.5
ghcr.io/zone-eu/zonemta-wildduck:1.32.20
nodemailer/wildduck-webmail:latest
nodemailer/rspamd

3)运行

镜像拉取后就可以运行了

复制代码
docker-compose up -d

这个时候遇到了的一个问题,在 docker-compose 里要把宿主机上的

/opt/wildduck/wildduck-dockerized/config/rspamd/worker-normal.conf

挂载成容器里的一个文件 /etc/rspamd/worker-normal.conf

但 Docker 发现宿主机的这个路径现在不是文件(很可能被创建成了目录),于是报:not a directory / 目录挂文件 类型不匹配。

config/rspamd/worker-normal.conf这个目录是开始不存在的,是docker自己创建的,所以用不了,在我们项目中实际上对应的是default-config

Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting "/opt/wildduck/wildduck-dockerized/config/rspamd/worker-normal.conf" to rootfs at "/etc/rspamd/worker-normal.conf": mount src=/opt/wildduck/wildduck-dockerized/config/rspamd/worker-normal.conf, dst=/etc/rspamd/worker-normal.conf, dstFd=/proc/thread-self/fd/11, flags=MS_BIND|MS_REC: not a directory: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type

所以我们只需要把default-config下面的目录复制到config下即可

复制代码
cd /opt/wildduck/wildduck-dockerized
docker-compose down 停止容器
sudo rm -rf config  删除
mkdir -p config  创建
cp -a default-config/* config/  复制

然后确认目标文件已经是"普通文件":

ls -l config/rspamd/worker-normal.conf

然后我们继续运行容器docker-compose up -d,继续报错

Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint wildduck-dockerized-traefik-1 (ffd7d0691d26d3525ed504b6cba5b7a08436fed122b129ba80dfe772fccd8163): Bind for 0.0.0.0:80 failed: port is already allocated

这个报错是因为我之前也部署过应该邮件系统,它的docker镜像一直在运行,所以它把邮件和网址访问所需要的端口都占用了,比如80,8080,3000,所以我们只需要把他停止就行了

还有一个坑,就是WildDuck 的 API 并不在 3000,而是在 8080,而此时8080被占用了,所以我们需要在docker-compose.yml中配置

复制代码
在 docker-compose.yml 里把 wildduck 的端口发布改成:
ports:
  - "18080:8080"

重启

sudo docker compose restart wildduck

4)创建账号

ok到这里说明你已经越过重重障碍和bug,现在我们只需要用apifox调用api创建账号

我们之前在setup中填写的域名是test.mail.com(实际上内网注册好像随便填的)

创建账号需要root权限的key,怎么找看下面

复制代码
cd /opt/wildduck/wildduck-dockerized
sudo grep -RniE "accessToken" config dynamic_conf default-config 2>/dev/null | head -n 50

这样就可以找到X-Access-Token了,我们创建账号都需要在head中带上它

复制代码
创建 alice
curl -sS -X POST "http://192.168.77.78:18080/users" \
  -H "Content-Type: application/json" \
  -H "X-Access-Token: ROOT_TOKEN" \
  -d '{"username":"alice","password":"123456","address":"alice@test.local"}'

创建 bob
curl -sS -X POST "http://192.168.77.78:18080/users" \
  -H "Content-Type: application/json" \
  -H "X-Access-Token: ROOT_TOKEN" \
  -d '{"username":"bob","password":"123456","address":"bob@test.local"}'

申请用户的X-Access-Token

复制代码
POST http://192.168.77.78:18080/authenticate

{
  "username": "alice@test.mail.com",
  "password": "123456",
  "token": true,
  "scope": "master"
}

response
{
  "success": true,
  "id": "...",
  "username": "bob",
  "address": "bob@test.mail.com",
  "scope": "master",
  "token": "xxxxxxxxxxxx"
  ...
}

这些用户id,token都要记录,因为后续发收邮件都需要用到,可以在Apifox配置环境变量

5)发送邮件

alice 发给 bob

复制代码
POST /users/{aliceId}/submit
Header:

X-Access-Token: <aliceToken>

Body:

{
  "to": [{ "address": "bob@test.mail.com" }],
  "subject": "hi",
  "text": "alice -> bob"
}

6)查看邮件

复制代码

bob 读 INBOX

GET /users/{bobId}/mailboxes(找 \Inbox 的Id)

GET /users/{bobId}/mailboxes/{inboxId}/messages(找messageId)

GET /users/{bobId}/mailboxes/{inboxId}/messages/{messageId}

每个请求 Header:

X-Access-Token:

复制代码
相关推荐
为爱停留2 小时前
Spring Boot 应用配置参数化实践:通过 Docker Run 参数传递配置
spring boot·后端·docker
林鸿风采2 小时前
在Alpine Linux上部署docker,并配置开机自启
linux·docker·eureka·alpine
江湖有缘2 小时前
Docker快速部署NeonLink:打造你的私人书签管理平台
运维·docker·容器
间彧2 小时前
docker中如何使用Arthas诊断工具
docker
l1t3 小时前
在arm64 Linux系统上编译tdoku-lib的问题和解决
linux·运维·服务器·c语言·cmake
岚天start3 小时前
【K8S分配率】Shell脚本计算Kubernetes集群CPU和内存总分配率
云原生·容器·kubernetes·分配率
珠穆峰3 小时前
RabbitMQ消息堆积问题处理
运维
取谖慕12.3 小时前
keepailved+nginx+nfs高可用
运维·nginx·nfs
txinyu的博客3 小时前
Linux 内存管理
linux·运维·开发语言·c++
cllsse3 小时前
堡垒机下载安装
运维