Docker LEMP Stack: Get Your Logs With Rsyslog
In this post, i will explain howto collect your logs when you have a LEMP stack with Docker and rsyslog.
PHP: log to stdout
Nginx use php-fpm and in order to have PHP to log to stdout, you will have to change two parameters. My examples is based on a Debian Stretch installation, so files locations can change for you.
-
Change in /etc/php/7.0/fpm/php-fpm.conf :
error_log = /proc/self/fd/2
-
Change in /etc/php/7.0/fpm/pool.d/www.conf:
access.log = /proc/self/fd/2
Now restart your PHP container and you will see that all your PHP logs will display on your terminal.
Hints: if you use the official PHP docker image, no needs to change these parameters. They are already set
Nginx : log to stdout
The changes are more easy here.
-
Change in /etc/nginx/nginx.conf:
access_log /dev/stdout; error_log /dev/stderr;
MariaDB: I will skip this step since the official Docker image already logs everything to stdout.
Docker : use the syslog driver
Now that all your containers log to stdout, we will tell Docker to send them to syslog. For this, you can add these lines to your docker-compose file:
services:
web:
image: "customer/nginx"
container_name: web
networks:
- core
ports:
- "80:80"
volumes:
- ./src/:/var/www/
logging:
driver: syslog
options:
syslog-address: "tcp://x.x.x.x:514"
syslog-format: rfc3164
tag: web
The import part is the last 6 lines :
driver: syslog
: tell Docker which driver to usesyslog-address
: put the address and port of your syslog serversyslog-format
: the syslog message format to usetag
: A string that is appended to ‘APP-NAME’ in the syslog message. It’s important because we will use it to sort messages
As usual the Docker documentation is usefull.
We will do the same for our PHP container:
logging:
driver: syslog
options:
syslog-address: "tcp://127.0.0.1:514"
syslog-format: rfc3164
tag: php
For the MariaDB container :
logging:
driver: syslog
options:
syslog-address: "tcp://127.0.0.1:514"
syslog-format: rfc3164
tag: db
Configure rsyslog
Now all your container’s logs will go to syslog. That’s cool but we will probably sort them by type.
We will store our logs in ‘/var/log/docker/xxx’
Here is the rsyslog configuration file :
# Files locations
$template webaccess,"/var/log/docker/web/access/%timereported:0:10:date-rfc3339%.log"
$template weberror,"/var/log/docker/web/error/%timereported:0:10:date-rfc3339%.log"
$template php,"/var/log/docker/php/access/%timereported:0:10:date-rfc3339%.log"
$template phperror,"/var/log/docker/php/error/%timereported:0:10:date-rfc3339%.log"
$template mysql,"/var/log/docker/mysql/%timereported:0:10:date-rfc3339%.log"
# Nginx
if $programname == "web" and $syslogseverity-text == "info" then ?webaccess
& stop
if $programname == "web" and $syslogseverity-text == "error" then ?weberror
& stop
# PHP
if $programname == "php" and $syslogseverity-text == "info" then ?php
& stop
if $programname == "php" and $syslogseverity-text == "error" then ?phperror
& stop
# MySQL
if $programname == "db" then ?mysql
& stop
In the first part, I declare the files locations and their formats:
$template webaccess,"/var/log/docker/web/access/%timereported:0:10:date-rfc3339%.log"
$template weberror,"/var/log/docker/web/error/%timereported:0:10:date-rfc3339%.log"
$template php,"/var/log/docker/php/access/%timereported:0:10:date-rfc3339%.log"
$template phperror,"/var/log/docker/php/error/%timereported:0:10:date-rfc3339%.log"
$template mysql,"/var/log/docker/mysql/%timereported:0:10:date-rfc3339%.log"
More informations in the rsyslog documentation
The next step is to tell rsyslog how to filter the logs:
if $programname == "web" and $syslogseverity-text == "info" then ?webaccess
& stop
The syntax is clear and you can see that that’s here that we use the syslog tag defined in our docker-compose file. By default the tag (if not specified) is the container ID.. so it’s not very usefull because we cannot know it by advance.
Start your stack and get your logs
$ docker-compose up
Creating network "test_default" with the default driver
Creating network "test_core" with driver "bridge"
Creating db ...
Creating php71 ...
Creating php71
Creating php71 ... done
Creating web ...
Creating web ... done
Attaching to db, php71, web
db | WARNING: no logs are available with the 'syslog' log driver
php71 | WARNING: no logs are available with the 'syslog' log driver
web | WARNING: no logs are available with the 'syslog' log driver
Go to the ‘/var/log/docker’ directory and check your logs:
$ cd /var/log/docker
$ ls -hlR
.:
total 12K
drwxr-xr-x 2 root root 4.0K Feb 23 15:23 mysql
drwxr-xr-x 4 root root 4.0K Feb 23 14:09 php
drwxr-xr-x 3 root root 4.0K Feb 23 14:02 web
./mysql:
total 24K
-rw-r+++-- 1 root adm 21K Feb 23 15:15 2018-02-23.log
./php:
total 8.0K
drwxr-xr-x 2 root root 4.0K Feb 23 15:23 access
drwxr-xr-x 2 root root 4.0K Feb 23 14:09 error
./php/access:
total 0
./php/error:
total 4.0K
-rw-r+++-- 1 root adm 561 Feb 23 15:15 2018-02-23.log
./web:
total 4.0K
drwxr-xr-x 2 root root 4.0K Feb 23 14:02 access
./web/access:
total 4.0K
-rw-r+++-- 1 root adm 820 Feb 23 14:09 2018-02-23.log
Everything is fine (not for me because I have a php error file).
Now you can use your LEMP stack and check your logs if you have some problems.
Enjoy 😉