40

I'm running Apache2 in a docker container, and want to write nothing to the disk, writing logs to stdout and stderr. I've seen a few different ways to do this (Supervisord and stdout/stderr, Apache access log to stdout) but these seem like hacks. Is there no way to do this by default?

To be clear, I do not want to tail the log, since that will result in things being written to the disk in the container.

aronchick
  • 685
  • 3
  • 7
  • 14
  • Aren't you going to want those logs to be easily accessible for troubleshooting/debugging purposes? Why not just write them to a (r)syslog server instead? – HTTP500 Apr 04 '16 at 18:30
  • @HTTP500 - They get captured on the outside of the docker container. – hookenz Jun 18 '17 at 22:14
  • 1
    If you use: FROM php:5.6-apache, that already includes logs to stdout and stderr. – Martlark Sep 04 '17 at 02:37

3 Answers3

47
  ErrorLog /dev/stderr
  TransferLog /dev/stdout

works on ubuntu and centos fo me

Oskarowski
  • 486
  • 5
  • 2
35

How about placing this in your Dockerfile after the apache2 package is installed?

RUN ln -sf /proc/self/fd/1 /var/log/apache2/access.log && \
    ln -sf /proc/self/fd/1 /var/log/apache2/error.log

Assuming that this is the path of the logs. It is for Ubuntu 14.04 and also works for Ubuntu 16.04.

Note: if you're certain that the symbolic links /dev/stdout or /proc/stderr are there, then you may also use those. I prefer the path to the real file as this is guaranteed present.

hookenz
  • 14,132
  • 22
  • 86
  • 142
  • works great also with Ubuntu 16.04 :) – OkieOth Sep 23 '16 at 10:04
  • 2
    Damn, that's an ingenious hack! Apache tries to open a regular file, but gets redirected via symlink to its own stdout from its own perspective. – joonas.fi Dec 03 '16 at 10:22
  • 1
    Just want to say thanks... the official apache httpd 2.4 docker container fails to write logs after enabling ssl. Adding these lines + ssl_request_log to the Dockerfile that pulls from httpd2.4 worked. – j.con Apr 04 '17 at 17:22
  • 3
    You can abbreviate /proc/self/fd/1 as /dev/stdout. They're exactly the same thing. – Chuck Adams Jan 09 '18 at 23:12
  • 1
    @ChuckAdams - they are a soft link and normally there, but no guarantees when building images that they are present. Especially cut down micro images. Whereas the kernel will always export /proc/self/fd/1 & 2. – hookenz Feb 08 '18 at 00:48
  • is `/proc/self` a real thing? – MrCholo May 21 '19 at 00:46
  • I have one more log file in the `/var/log/apache2` folder last time I checked – Alexander Mills May 22 '19 at 20:33
  • Any explanation for why this works? (It does seem to). – Alexander Mills May 22 '19 at 20:37
  • @AlexanderMills - See the proc fs documentation. Search for "self". https://www.kernel.org/doc/Documentation/filesystems/proc.txt. It always refers to the process the current process. e.g. ls /proc/self represents "ls". Apache /proc/self refers to the Apache process. That's why it works. – hookenz May 22 '19 at 23:36
2

Not specifically an answer asked for but maybe a better way, depending on your scenario, would be to to not log to stdout/stderr at all. Just pipe the logs to cat in a JSON format. This would remove the need to differentiate the streams as the json could have the data needed in it to distinguish them. eg something along the lines of the following. This can then be ingested much more easily into something like graylog

GlobalLog "| cat - " gelf
ErrorLog "| cat - " 

LogFormat "{ \"apache_log\": \"ACCESS\", \"app_name\": \"apache\",  \"Connection\": \"%{X-Forwarded-Proto}i:%{X-Forwarded-Port}i \", \"X-Forwarded-For\": \"%{X-Forwarded-For}i\",  \"version\": \"1.1\", \"vhost\": \"%V\", \"short_message\": \"%r\", \"timestamp\": %{%s}t, \"level\": 6, \"user_agent\": \"%{User-Agent}i\", \"source_ip\": \"%a\", \"duration_usec\": %D, \"duration_sec\": %T, \"request_size_byte\": %O, \"http_status\": %s, \"http_request_path\": \"%U\", \"http_request\": \"%U%q\", \"http_method\": \"%m\", \"http_referer\": \"%{Referer}i\", \"X-Powered-By\": \"%{X-Powered-By}i\" }" gelf

ErrorLogFormat "{ \"app_name\": \"apache\",  \"apache_log\": \"ERROR\", \"time\":\"%{%Y-%m-%d}tT%{%T}t.%{msec_frac}tZ\", \"function\" : \"[%-m:%l]\" , \"process\" : \" [pid %P:tid %T] \" , \"message\" : \"%M\" ,\ \"referer\"\ : \" %{Referer}i \" }"

There is also a gelf logging module, so you can stream direct from apache to a graylog type server as well if you wish

krad
  • 158
  • 4