Ghost Logging: File Transport with Rotation vs. Stdout for Docker
0 reputation · 12 Jan 2020, 04:22 UTC
0 reputation · 12 Jan 2020, 04:22 UTC
When configuring a Ghost production environment, specifically within Docker or systemd-managed instances, there is a design choice regarding how application logs are captured and retained for post-deployment diagnostics.
Ghost supports internal logging via the config.production.json file, allowing for a path to the content/logs directory with built-in rotation. Alternatively, configuring the transport to stdout delegates log management to the container runtime or journald.
docker logs, but removes Ghost's internal rotation logic, shifting the burden of retention to the host OS or container driver.A critical uncertainty arises during startup failures: errors occurring before the logger initializes may only appear in stderr, potentially creating gaps if only file transports are configured.
Should the logging configuration prioritize Ghost's internal rotation for self-contained post-mortems, or rely exclusively on stdout to leverage host-level rotation tools? Is there a documented risk of duplicate entries or truncated logs when enabling both transports simultaneously?
35275 reputation · 12 Jan 2020, 08:31 UTC
For Dockerized Ghost deployments, prioritize stdout as the primary logging transport and enforce retention limits at the container runtime level. Ghost's internal file rotation is viable only when content/logs is backed by a persistent, mapped volume; without one, file-based logs vanish on container recreation. Enabling both transports at once is not recommended—the application will likely write each event to two destinations, producing duplicates and complicating post-deployment analysis.
Confirmed behavior: Ghost's config.production.json accepts a logging block with a transport value. When set to stdout, the application emits logs to standard output, which the Docker daemon captures. When configured with a file path, Ghost writes to that directory and applies its own rotation policy.
Likely explanation: Early-boot failures—such as configuration parse errors or database connection failures occurring before the logger fully initializes—often surface only on stderr. If Ghost is configured exclusively for file transport, these pre-logger messages may not reach the log file, creating a gap exactly when diagnostics matter most. Capturing stdout and stderr at the container boundary closes this gap.
logging.transport to stdout in config.production.json.path directive to avoid duplicate writes.json-file driver (or your chosen logging driver) with max-size and max-file options in /etc/docker/daemon.json to bound disk usage.docker logs <container_id>.If your post-mortem workflow requires a self-contained artifact inside the container or volume—for example, an immutable audit bundle that must survive even if the host's Docker daemon logs are cleared—file transport is defensible. In that case, map a persistent volume to /var/lib/ghost/content/logs (or the equivalent path in your image) and rely on Ghost's rotation. Treat this as an archive, not the primary observability channel.
Confirm the active transport by inspecting config.production.json and running docker logs. Check /etc/docker/daemon.json for log-opts limits. If you are using journald via systemd, verify retention with journalctl --disk-usage and adjust SystemMaxUse in /etc/systemd/journald.conf.
One diagnostic detail that would change this advice: Is your Ghost instance running from the official Docker image with content/logs on an ephemeral layer, or do you have a persistent volume explicitly mapped to that directory? If the volume is guaranteed and immutable, a file-first strategy becomes safer; if not, stdout is the only reliable option.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.