I’m wondering if using logrotate is the best approach for rotating the logs written by our various programs in a container. All logs are written to a persistent shared volume.
We have in one container:
a C++ program that writes to a log file,
a bash script that is our dockerfile CMD and it writes to a log file,
a health check as bash script that also writes to a log file
In another container:
a tomcat host java servlet that writes logs using log4j2
a bash script that is our dockerfile CMD and it writes to a log file,
a C++ program that writes to a log file
In another container:
an nginx proxy that writes to access and error logs
Other than the log4j2 logging, which has the ability to rotate logs, all of the logs are being rotated using logrotate, which is if I understand it correctly requires systemctl. Which may require INITSYSTEM=0.
Is there a better way to rotate logs than using logrotate in each container? I realize that having a single container rotate all of the logs would require a single list of logs to be configured, although we could use a file pattern to rotate everything the same way.
While logrotate is often controlled via systemd timer, it is not strictly necessary. You can call logrotate from any daemonized program if you like. It is quite common to run such housekeeping tasks from cron if systemd is not available on device.
Personally, I would recommend logging from all containers to a single root (ie mapping each container’s storage in a central place, like /data/logs/{container1,container2,container3} and then rotating those files from another container altogether, using a logrotate configuration similar to the following (ymmv). You should be able to run this all from a simple crontab entry or daemon.
I’m going to go with writing all of the logs to a shared volume and have one of the containers that already requires systemctl specify the log rotation. Thanks
Now that I’ve moved to newer balenaOS base images, I have found that systemctl is deprecated. I’ve tried to use cron to rotate the logs but my log rotations are not being performed.
Is there any additional examples of using cron and logrotate?
Hi,
Are you getting any error back?
Can you share your dockerfile and your logrotate configuration?
Please re-check that the container running the logrotate should have enough permissions to access the location of the logs in the shared volume.
Let me point you to our cron example:
Have you tried running logrotate manually using SSH, to config that the configuration is correct and it indeed works as expected?
If the repeating job seems to be the source of the trouble you could as easily have a separate container that runs logrotate then sleep in a loop.
No errors, and when I run the logrotate manually it works. Permissions are good for /etc/logrotate.etc, /etc/cron.hourly/logrotate, /etc/cron.daily/logrotate and everything else I have checked.
I looked at the “balena-io-playground/cron-example” but it is using crontab rather than /etc/cron.hourly/logrotate. If my understanding is correct, scripts in cron.hourly are executed using run-parts. When I test if my logrotate script in cron.hourly meets the requirements of run-parts the answer appears to be yes:
I don’t see cron being started in the balena cron example. Where is that happening?
The initsystem is leftover from the resin base image. Sometimes migration to a new base image isn’t clean. I’ll look into it. Unfortunately I’m not an expert on what an “initsystem” does. So much to learn.
The cron example is quite old and as you can see, it is not using a balenalib/xxxx base image (it uses resin/%%RESIN_MACHINE_NAME%%-debian)
These old images had an option to run with an init system (systemd or openrc): ENV INITSYSTEM on.
If you have systemd running and you install cron, systemd will start cron when the container is started.
This feature was removed in balenalib base images so you need to either:
Just a small suggestion, if you place a file in /etc/cron.d/ with the contents * * * * * {{path to script}} you shouldn’t need to pipe that into crontab, as cron instead will just execute that every minute.