Docker容器中的Java应用程序不能正确login到syslog

我的目标

我有一个主机内运行的几个不同的容器。 它们都与对方的/dev/log套接字共享一个卷。 主机将这些日志转发到中央日志logging服务器。 所有其他容器日志都显示在主机的/var/log/messages 。 其他容器是python程序,它允许日志logging直接附加到/dev/log unix域套接字。

基本configuration

我有一个docker容器从jar文件运行一个scala应用程序。 /dev/log套接字在主机和容器之间共享为卷。 应用程序的log4j.properties文件对我来说似乎很好,它的设置如下:

 # Root logger option log4j.rootLogger=INFO, file, stdout, SYSLOG # Direct log messages to a log file log4j.appender.file=org.apache.log4j.RollingFileAppender log4j.appender.file.File=log/associationRules.log log4j.appender.file.MaxFileSize=10MB log4j.appender.file.MaxBackupIndex=10 log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%c{1}:%L] %-5p <%X{jobID}> %m%n # Direct log messages to stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%c{1}:%L] %-5p <%X{jobID}> %m%n # Log to syslog log4j.appender.SYSLOG=org.apache.log4j.net.SyslogAppender log4j.appender.SYSLOG.syslogHost=localhost log4j.appender.SYSLOG.layout=org.apache.log4j.PatternLayout log4j.appender.SYSLOG.layout.conversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%c{1}:%L] %-5p <%X{jobID}> %m%n log4j.appender.SYSLOG.Facility=LOCAL0 log4j.appender.SYSLOG.Threshold=debug log4j.appender.SYSLOG.FacilityPrinting=true 

标准输出和文件日志正确完成,但SYSLOG似乎不能正常工作。 日志显示在容器的/var/log/syslog ,但不显示在主机的/var/log/messages 。 我认为SyslogAppender也会输出到/dev/log但似乎并没有这样做。

额外细节

这是我在容器的/var/log/syslog得到的输出。 我看到一些imuxsock没有运行的问题,但我不明白日志如何存储在/var/log/syslog 。 最后两行是从应用程序,并与标准输出和文件appender一致

 Jul 6 18:07:18 26056b722779 rsyslogd: [origin software="rsyslogd" swVersion="7.4.4" x-pid="25" x-info="http://www.rsyslog.com"] start Jul 6 18:07:18 26056b722779 rsyslogd: cannot create '/dev/log': Address already in use Jul 6 18:07:18 26056b722779 rsyslogd: imuxsock does not run because we could not aquire any socket Jul 6 18:07:18 26056b722779 rsyslogd-3000: activation of module imuxsock failed Jul 6 18:07:18 26056b722779 rsyslogd: imklog: cannot open kernel log (/proc/kmsg): Operation not permitted. Jul 6 18:07:18 26056b722779 rsyslogd-2145: activation of module imklog failed [try http://www.rsyslog.com/e/2145 ] Jul 6 18:07:19 localhost local0: 2015-07-06 18:07:19 [AssocApp$:112] INFO <Undefined> Listening to queue ASSOCIATIONRULES Jul 6 18:07:19 localhost local0: 2015-07-06 18:07:19 [AssocApp$:113] INFO <Undefined> Listening to queue ASSOCIATIONRULES 

容器的基本映像是安装了java的ubuntu 14.04在容器映像的dockerfile中,我的CMD是:

 CMD sudo service rsyslog start; java -cp /root/AssociationRules.jar AssocApp 

我开始这样的容器:

 docker run -d -v /dev/log:/dev/log <IMAGE> 

/etc/rsyslog.conf

 ################# #### MODULES #### ################# $ModLoad imuxsock # provides support for local system logging $ModLoad imklog # provides kernel logging support #$ModLoad immark # provides --MARK-- message capability # provides UDP syslog reception #$ModLoad imudp #$UDPServerRun 514 # provides TCP syslog reception #$ModLoad imtcp #$InputTCPServerRun 514 # Enable non-kernel facility klog messages $KLogPermitNonKernelFacility on ########################### #### GLOBAL DIRECTIVES #### ########################### # # Use traditional timestamp format. # To enable high precision timestamps, comment out the following line. # $ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat # Filter duplicated messages $RepeatedMsgReduction on # # Set the default permissions for all log files. # $FileOwner syslog $FileGroup adm $FileCreateMode 0640 $DirCreateMode 0755 $Umask 0022 #$PrivDropToUser syslog #$PrivDropToGroup syslog # # Where to place spool and state files # $WorkDirectory /var/spool/rsyslog # # Include all config files in /etc/rsyslog.d/ # $IncludeConfig /etc/rsyslog.d/*.conf $ModLoad imudp $UDPServerRun 514 

和/etc/rsyslog.d/50-default.conf

 auth,authpriv.* /var/log/auth.log *.*;auth,authpriv.none -/var/log/syslog #cron.* /var/log/cron.log #daemon.* -/var/log/daemon.log kern.* -/var/log/kern.log #lpr.* -/var/log/lpr.log mail.* -/var/log/mail.log #user.* -/var/log/user.log # # Logging for the mail system. Split it up so that # it is easy to write scripts to parse these files. # #mail.info -/var/log/mail.info #mail.warn -/var/log/mail.warn mail.err /var/log/mail.err # # Logging for INN news system. # news.crit /var/log/news/news.crit news.err /var/log/news/news.err news.notice -/var/log/news/news.notice # # Some "catch-all" log files. # #*.=debug;\ # auth,authpriv.none;\ # news.none;mail.none -/var/log/debug #*.=info;*.=notice;*.=warn;\ # auth,authpriv.none;\ # cron,daemon.none;\ # mail,news.none -/var/log/messages # # Emergencies are sent to everybody logged in. # *.emerg :omusrmsg:* # # I like to have messages displayed on the console, but only on a virtual # console I usually leave idle. # #daemon,mail.*;\ # news.=crit;news.=err;news.=notice;\ # *.=debug;*.=info;\ # *.=notice;*.=warn /dev/tty8 # The named pipe /dev/xconsole is for the `xconsole' utility. To use it, # you must invoke `xconsole' with the `-file' option: # # $ xconsole -file /dev/xconsole [...] # # NOTE: adjust the list below, or you'll go crazy if you have a reasonably # busy site.. # daemon.*;mail.*;\ news.err;\ *.=debug;*.=info;\ *.=notice;*.=warn |/dev/xconsole 

在我看来,你正在推翻这一点。 如果我正确地阅读了你的问题,你希望你的Docker容器把它的syslog写入主机的系统日志。

你所描述的错误可能是由于你在容器中启动了第二个syslog守护进程,然后打开/dev/log套接字(已经存在)。

想到几个想法(所有未经testing,但谨慎使用):

  1. 为什么不configurationLog4j直接写入远程syslog守护进程? 这将消除对容器内部的syslog守护进程的需求,并且需要将/dev/log挂载到容器中?

     # Log to syslog log4j.appender.SYSLOG=org.apache.log4j.net.SyslogAppender log4j.appender.SYSLOG.syslogHost=<your-host-ip> # <-- INSERT HOST IP HERE log4j.appender.SYSLOG.layout=org.apache.log4j.PatternLayout 

    要保持容器的可移植性,最好通过使用--add-host标志来configuration容器创build时syslog服务器的IP地址:

     docker run -d --add-host sysloghost:<host-ip-here> <IMAGE> 

    这样,您可以简单地使用sysloghost作为您的Log4Jconfiguration文件中的主机名。

  2. 如果您坚持在应用程序容器中运行syslog服务器,您应该能够(记住:所有未经testing!)将其configuration为将所有消息转发到远程系统日志服务器(位于/etc/rsyslog.conf/etc/rsyslog.d某处) /etc/rsyslog.d ):

     *.* @sysloghost:512 # UDP forwarding # *.* @@sysloghost:512 # TCP forwarding 
  3. 更好的是,为什么不在自己的Docker容器中运行syslog守护进程并将该容器链接到应用程序容器?

请记住,对于这两种解决scheme,主机上的syslog守护程序都需要configuration为侦听TCP或UDP套接字[ref] :

 $ModLoad imudp $UDPServerRun 514 

或者[ref] :

 $ModLoad imtcp # needs to be done just once $InputTCPMaxSessions 500 $InputTCPServerRun 514