containerd logging, when you’re used to Docker’s simpler docker logs command, can feel like a black box. The surprising truth is that containerd doesn’t directly write logs to files in the traditional sense for most services; it delegates that to journald.

Let’s see what that looks like. First, we need to know which services containerd is managing. If you’ve got containerd running, you’ll likely have a containerd systemd service itself, and then various container runtimes or plugins. To see what’s running, you’d typically look at systemctl status containerd. But that’s just the daemon. The actual containers’ logs are managed differently.

To view logs from a specific container, you’ll use journalctl. The key is filtering by the correct unit. For containers managed by containerd, the systemd units often follow a pattern. For example, if you have a container named my-awesome-app, you might find its logs under a unit like containerd-my-awesome-app.scope. To see these logs, you’d run:

journalctl -u containerd-my-awesome-app.scope -f

The -f flag here is just like tail -f, showing you new logs as they come in. This is how you’d typically interact with container logs when using containerd with its default journald logging driver.

Now, let’s build the mental model. journald is the systemd logging daemon. It collects log messages from various sources: systemd services, the kernel, and even applications that are configured to send logs to it. When containerd starts a container, it can be configured to direct that container’s stdout and stderr to a specific journald "unit." This unit is often a systemd scope unit, dynamically created for each container. The scope unit acts as a namespace for the container’s logs within journald.

The configuration for this is usually found in containerd’s configuration file, typically located at /etc/containerd/config.toml. Within this file, you’ll find a plugins.cri.containerd.log_runtime section. If it’s set to journald, then containerd will pipe container logs to systemd’s journal.

Here’s a snippet of what that might look like in config.toml:

[plugins.cri.containerd]
  # ... other configurations ...
  log_runtime = "journald"
  # ... other configurations ...

If you wanted to change this, say to a file-based logging driver (though journald is generally preferred for its integration and robustness), you’d modify this line. However, for this topic, we’re sticking with journald. The advantage of journald is centralized logging, structured data (if your application logs in a JSON format, for example), and easy integration with other systemd tools.

The "exact levers you control" are primarily within config.toml. You can influence how logs are tagged and filtered within journald. For instance, you can set environment variables for your container that might influence its logging behavior, or you can directly configure the CRI plugin to pass specific options. However, the core mechanism of sending to journald is controlled by that log_runtime setting.

When debugging, remember that journald itself has configuration. You might find settings in /etc/systemd/journald.conf that affect log rotation, storage, and forwarding. For example, SystemMaxUse=100M would limit the total size of journal logs to 100 megabytes. If your logs are disappearing, this is a prime suspect.

Here’s the part most people miss: while journalctl -u <unit> is great for getting logs from a specific container, you can also leverage journald’s powerful filtering capabilities to correlate logs across different services or even the containerd daemon itself. For example, to see logs from containerd and a specific container, you could use:

journalctl -u containerd.service -u containerd-my-awesome-app.scope -f

This allows you to see the daemon’s activity alongside the container’s output, which is invaluable for diagnosing issues where the container might be failing to start or crashing immediately after launch, and the root cause is in the containerd daemon’s interaction with the container runtime.

The next logical step is understanding how to configure log rotation and retention policies for journald itself to manage disk space effectively.

Want structured learning?

Take the full Containerd course →