Docker Entrypoint执行脚本与手动执行结果不一致问题排查
容器Entrypoint执行邮件脚本失败,手动执行正常的问题排查与解决
问题场景
我有一个用于执行SQL查询并根据结果发送邮件的容器,对应的执行脚本如下:
#!/bin/bash AMOUNT=$(mysql -h foo -u foo -pfoo foo < order-check.sql | sed 's/amount//'| cut -f1 -d '.') if [ $AMOUNT -eq 0 ] then sendmail foo@bar.com < /app/order-check-email.txt sleep 30 echo `cat /var/log/exim4/mainlog` else sendmail foo@bar.com < /app/order-check-email-ok.txt fi
当我通过docker exec进入容器并手动运行sh app/order-check.sh时,脚本可正常执行并发送邮件。但将其设置为容器启动时执行(Dockerfile配置如下):
FROM namshi/smtp ENV MAILNAME foo.com RUN apt-get update RUN apt-get install -y default-mysql-client RUN mkdir /app WORKDIR /app COPY . . RUN chmod 744 /app/order-check.sh ENTRYPOINT ["sh", "/app/order-check.sh"]
此时发送邮件出现错误,日志关键信息:
2022-10-06 14:42:26 1ogS4w-00000B-Of ... foo@bar.co.uk R=nonlocal: Mailing to remote domains not supported ...
原因分析
问题核心是namshi/smtp镜像的初始化流程被跳过:
- 该镜像默认的ENTRYPOINT脚本会读取RELAY_HOST、SMTP_USER等环境变量,自动配置Exim使其支持远程邮件投递;
- 自定义ENTRYPOINT直接运行脚本时,镜像自带的初始化逻辑完全没执行,Exim保持默认的仅本地投递配置,因此无法发送邮件到远程域名;
- 手动exec执行脚本时,容器已经完成了镜像默认的初始化,Exim已具备远程投递能力,所以脚本能正常工作。
解决方法
方案1:改用CMD替代ENTRYPOINT
保留镜像默认的ENTRYPOINT,将自定义脚本设为CMD,让镜像先完成Exim初始化,再执行你的脚本:
修改Dockerfile最后一行:
CMD ["sh", "/app/order-check.sh"]
namshi/smtp的默认ENTRYPOINT会先处理SMTP配置,再自动执行CMD指定的命令,确保脚本运行时Exim已具备远程投递能力。
方案2:在自定义脚本中先执行镜像初始化逻辑
如果必须使用ENTRYPOINT,可在脚本开头调用镜像自带的初始化脚本,确保Exim配置完成后再执行业务逻辑:
修改order-check.sh:
#!/bin/bash # 先执行namshi/smtp的初始化脚本,完成Exim配置 /opt/namshi/smtp/entrypoint.sh # 原有业务逻辑 AMOUNT=$(mysql -h foo -u foo -pfoo foo < order-check.sql | sed 's/amount//'| cut -f1 -d '.') if [ $AMOUNT -eq 0 ] then sendmail foo@bar.com < /app/order-check-email.txt sleep 30 cat /var/log/exim4/mainlog else sendmail foo@bar.com < /app/order-check-email-ok.txt fi
注:初始化脚本路径可通过查看
namshi/smtp镜像的Dockerfile确认,通常为/opt/namshi/smtp/entrypoint.sh。
额外检查
确保容器运行时已正确设置namshi/smtp所需的环境变量,比如:
RELAY_HOST:远程SMTP服务器地址SMTP_USER:SMTP认证用户名SMTP_PASSWORD:SMTP认证密码
这些变量是配置远程邮件中继的必要条件。
内容的提问来源于stack exchange,提问作者Ydrab
相关产品推荐
相关产品推荐

