A Docker image that performs log rotation for other containers running in the same Docker Swarm environment.
This container runs logrotate to manage log files from other containers in your Docker Swarm. It helps prevent log files from growing too large and consuming all available disk space. The container is designed to be lightweight and configurable through environment variables.
- Rotates log files from other containers in the same Docker Swarm
- Configurable rotation interval (daily, weekly, monthly, yearly)
- Configurable size-based rotation
- Configurable number of backup copies to keep
- Timezone support
- Automatic compression of rotated logs
All environment variables are optional and have default values:
| Variable | Description | Default | Options |
|---|---|---|---|
LOGS_PATH |
Path to log files to rotate | /logs/*.log |
Any valid path pattern |
TRIGGER_INTERVAL |
How often to rotate logs | daily |
hourly, daily, weekly, monthly, yearly |
MAX_SIZE |
Rotate if log file size reaches this threshold | NONE |
NONE or size (e.g., 1K, 10M, 1G) |
MAX_BACKUPS |
Number of backup copies to keep | 365 |
Any positive integer |
DELAYCOMPRESS |
Delay compression of rotated logs until next rotation | true |
true, false |
TZ |
Timezone | UTC |
Any valid timezone (e.g., Europe/Berlin) |
SU_USER |
User for logrotate su directive (helps with bind mounts on Docker Desktop) |
root |
Any existing user inside container |
SU_GROUP |
Group for logrotate su directive |
root |
Any existing group inside container |
version: '3.8'
services:
# Example service that generates logs
traefik:
image: traefik:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- logs:/logs # folder containing access.log file
ports:
- "80:80"
- "443:443"
command:
- "--accesslog=true"
- "--accesslog.filepath=/logs/access.log"
deploy:
restart_policy:
condition: on-failure
delay: 5s
# Logrotate service
logrotate:
image: samuelrunggaldier/logrotate:latest # Use latest version, or specify a version like 1.0.0
volumes:
- logs:/logs
environment:
TZ: "Europe/Berlin"
LOGS_PATH: "/logs/*.log"
TRIGGER_INTERVAL: daily
MAX_SIZE: NONE
MAX_BACKUPS: 365
DELAYCOMPRESS: "true"
deploy:
restart_policy:
condition: on-failure
delay: 5s
volumes:
logs:
driver: localYou can run this stack locally with Docker Desktop using Docker Compose. The included docker-compose.yml already contains an example app (Traefik) that writes logs for logrotate to rotate.
Steps:
- Clone this repository or copy the
docker-compose.ymlinto an empty folder. - From that folder, start the stack:
docker compose up -d
- Watch the
logrotatecontainer logs:docker compose logs -f logrotate
- List rotated files (example uses the named volume
logsmounted at/logs):docker compose exec logrotate sh -lc "ls -l /logs"
- Stop and clean up when done:
docker compose down -v
Notes for Windows/macOS:
- The provided compose file uses a named volume (
logs), which works out-of-the-box on Docker Desktop. If you prefer a bind mount, use./logs:/logsand ensure the project folder is within a directory shared with Docker Desktop (Settings → Resources → File sharing). - Timezone can be set via
TZ(e.g.,Europe/Berlin). - You can change which files are rotated by adjusting
LOGS_PATH(default/logs/*.log). - If you use a bind mount (
./logs:/logs) and see an error like:error: skipping "/logs/*.log" because parent directory has insecure permissions (...) Set "su" directive in config file, setSU_USERandSU_GROUP(e.g.,root/root). This addssu user groupto the logrotate config to handle Docker Desktop’s permissions semantics.
Run without Compose (optional):
docker run -d --name logrotate \
-e TZ=UTC \
-e LOGS_PATH="/logs/*.log" \
-e TRIGGER_INTERVAL=daily \
-e MAX_SIZE=NONE \
-e MAX_BACKUPS=365 \
-e SU_USER=root \
-e SU_GROUP=root \
-v logs:/logs \
samuelrunggaldier/logrotate:latestTo deploy the stack to a Docker Swarm:
docker stack deploy -c docker-compose.yml mystacklogrotate:
image: samuelrunggaldier/logrotate:latest
volumes:
- logs:/logs
environment:
TRIGGER_INTERVAL: daily
MAX_SIZE: 100M
MAX_BACKUPS: 30logrotate:
image: samuelrunggaldier/logrotate:latest
volumes:
- logs:/logs
environment:
TRIGGER_INTERVAL: weekly
MAX_BACKUPS: 52logrotate:
image: samuelrunggaldier/logrotate:latest
volumes:
- logs:/logs
environment:
LOGS_PATH: "/logs/app-*.log"logrotate:
image: samuelrunggaldier/logrotate:latest
volumes:
- logs:/logs
environment:
TRIGGER_INTERVAL: daily
MAX_BACKUPS: 30
DELAYCOMPRESS: "true"To build the Docker image locally:
docker build -t samuelrunggaldier/logrotate:latest .This project uses GitHub Actions for continuous integration and delivery:
- Automated Builds: Every push to the main branch and pull request triggers an automated build.
- Versioned Releases: Creating a tag with the format
v*(e.g.,v1.0.0) triggers a versioned release. - Monthly Updates: The image is automatically rebuilt and published on the first day of each month to ensure it stays up-to-date.
- Docker Hub Publishing: Successfully built images are automatically published to Docker Hub.
The Docker images follow semantic versioning:
| Tag Format | Example | Description |
|---|---|---|
latest |
samuelrunggaldier/logrotate:latest |
Latest stable build from the main branch (updated monthly) |
{version} |
samuelrunggaldier/logrotate:1.2.3 |
Specific version (from git tag v1.2.3) |
{major}.{minor} |
samuelrunggaldier/logrotate:1.2 |
Latest patch version of a specific minor version |
{major} |
samuelrunggaldier/logrotate:1 |
Latest minor.patch version of a specific major version |
main |
samuelrunggaldier/logrotate:main |
Latest build from the main branch (same as latest, updated monthly) |
sha-{commit} |
samuelrunggaldier/logrotate:sha-a1b2c3d |
Build from a specific commit |
To use a specific version in your docker-compose.yml, choose one of these options:
# Option 1: Use a specific version
logrotate:
image: samuelrunggaldier/logrotate:1.0.0# Option 2: Use latest 1.x.x version
logrotate:
image: samuelrunggaldier/logrotate:1# Option 3: Use latest version
logrotate:
image: samuelrunggaldier/logrotate:latest- Check that the log files match the pattern specified in
LOGS_PATH - Verify that the container has proper permissions to access the log files
- Check the container logs for any errors:
docker service logs mystack_logrotate
- Check that the cron daemon is running properly
- Verify that the logrotate configuration is valid
- Check system resources (memory, disk space)
If you see errors like error: destination /logs/access.log-YYYYMMDD already exists, skipping rotation:
- This is fixed in the latest version by using a more precise timestamp format that includes hours, minutes, and seconds
- If using an older version, you can work around this by:
- Manually removing the existing rotated log files
- Restarting the logrotate container
- Scheduling the container to run at different times than when logs are created
This project is licensed under the MIT License - see the LICENSE file for details.
This project uses the following third-party components:
- Alpine Linux - Licensed under GNU General Public License
- logrotate - Licensed under GNU General Public License v2
- tzdata - Public Domain
- bash - Licensed under GNU General Public License v3
- coreutils - Licensed under GNU General Public License v3
- findutils - Licensed under GNU General Public License v3
- grep - Licensed under GNU General Public License v3
- Traefik (in example configuration) - Licensed under MIT License
Contributions are welcome! Please feel free to submit a Pull Request.
By contributing to this project, you agree that your contributions will be licensed under the project's MIT License.
