DEV Community

Nathan Cook
Nathan Cook

Posted on

Using Zellij for a better docker compose experience

In a previous tutorial, I described how to use TMUX and tmuxinator to create basic configurable TUIs for docker compose projects which display service logs and open shell sessions in separate windows/panes, as an alternative to the standard concantenated compose service log output.

One drawback of using TMUX for this is that it isn't particularly user friendly without messing with the TMUX configuration, even with tmuxinator helping to configure the layout.

This tutorial will show how to achieve a similar result (multiplexing docker compose up service logs, container shell sessions, and whatever else) using Zellij.

Zellij is a "Batteries Included" terminal multiplexer like TMUX which is both easy to configure and provides a much better user experience out-of-the-box.

Article Index

Install Zellij and Clone the Tutorial Repo

  • Install Zellij. I used homebrew: brew install zellij

  • Clone the tutorial repo and open it with git clone https://github.com/moofoo/compose-zellij-tutorial.git && cd compose-zellij-tutorial

compose-zellij-tutorial should have the following files/directories:

|- apps
|  |- web
|  |- api
|- db
|  |- 01_schema.sql
|  |- 02_data.sql
|- docker-compose.yml
|- Dockerfile
|- zellij.kdl
|- README.md
|- up.sh
Enter fullscreen mode Exit fullscreen mode

The tutorial Docker Compose project defines four services

The Zellij session layout has two tabs, each with four panes

  • Tab "Log"

    • Logs from "web"
    • Logs from "api"
    • Logs from "db"
    • Logs from "redis"
  • Tab "Shell"

    • Shell session in "web" container
    • Shell session in "api" container
    • PSQL session connected to "db"
    • NestJS REPL running in "api" container

Starting the Docker Compose Zellij Session

Here's the contents of the script up.sh, which starts docker compose and the Zellij session. Go ahead and run it with bash up.sh, if you like.

#!/bin/bash

# Start the docker compose project in detached mode, waiting until services are running before continuing script execution.
docker compose up --wait -d

# Run Zellij with the layout defined in `zellij.kdl`
zellij --layout zellij.kdl

#Stop docker compose after Zellij exits
docker compose stop
Enter fullscreen mode Exit fullscreen mode

Simple enough.

Configuring the Zellij Layout with KDL

Zellij uses KDL for configuration.

Here's the contents of zellij.kdl, which defines the layout for the Compose/Zellij session:

/*
    The following three settings ensure only a single Zellij session is created for the docker compose project
    and that it won't stick around after exiting (normally or abnormally).
*/
session_name "compose-zellij-tutorial"
session_serialization false
on_force_close "quit"

layout {
    /*
        This defines the default layout for the two tabs in the layout ('Log' and 'Shell'), as well as any tabs created during the Zellij session.

        Top-down it shows the tab bar, the currently active tab's contents with 'children' (the panes), and lastly the (very helpful) Zellij status bar.
    */
    default_tab_template {
        pane size=1 borderless=true {
            plugin location="zellij:compact-bar"
        }

        children

        pane size=1 borderless=true {
            plugin location="zellij:status-bar"
        }
    }


    // Log tab
    tab name="Log" split_direction="horizontal" {
        pane split_direction="vertical" {

            // Web pane: docker compose logs --since=1s -f web
            pane name="Web" command="docker" {
                args "compose" "logs" "--since=1s" "-f" "web"
            }

            // API pane: docker compose logs --since=1s -f api
            pane name="API" command="docker" {
                args "compose" "logs" "--since=1s" "-f" "api"
            }

        }

        pane split_direction="vertical" {

            // DB pane: docker compose logs --since=1s -f db
            pane name="DB" command="docker" {
                args "compose" "logs" "--since=1s" "-f" "db"
            }

            // Redis pane: docker compose logs --since=1s -f redis
            pane name="Redis" command="docker" {
                    args "compose" "logs" "--since=1s" "-f" "redis"
            }
        }
    }

    //Shell tab
    tab name="Shell" split_direction="horizontal" {
        pane split_direction="vertical" {

            // Web pane: docker compose exec -w /usr/src/app web sh
            pane name="Web" command="docker" {
                args "compose" "exec" "-w" "/usr/src/app" "web" "sh"
            }

            // API pane: docker compose exec -w /usr/src/app api sh
            pane name="API" command="docker" {
                args "compose" "exec" "-w" "/usr/src/app" "api" "sh"
            }
        }

        pane split_direction="vertical" {

            // PSQL pane: docker compose exec db psql -U postgres -d tutorial_db
            pane name="PSQL" command="docker" {
                args "compose" "exec" "db" "psql" "-U" "postgres" "-d" "tutorial_db"
            }

            // NestJS Repl pane: docker compose exec -w /usr/src/app api npm run repl
            pane name="NestJS Repl" command="docker" {
                args "compose" "exec" "-w" "/usr/src/app" "api" "npm" "run" "repl"
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

And here's the result:

The "Log" tab:

Logs Tab

The "Shell" tab:

Shell Tab

And in action:

(Note that split_direction refers to the orientation of the gap between child panes. In other words, if you want the child panes within a container pane/tab to be arranged horizontally, you would set split_direction to vertical on the container)

Fixing mouse selection copying for some terminal emulators

Zellij has mouse-drag-select-to-copy functionality similar to TMUX, but it doesn't work with some terminal emulators. This was the case for me using GNOME terminal.

The way I fixed it was to first install xclip with sudo apt update && sudo apt install xclip

And then I added copy_command "xclip -selection clipboard" to the top of zellij.kdl (outside of the layout block)

For more info, see https://zellij.dev/documentation/faq.html#copy--paste-isnt-working-how-can-i-fix-this

Resources

Zellij Screencasts and Tutorials (the first two tutorials cover the basics of Zellij keyboard commands and interactivity)

Zellij Documentation

Zellij default keybindings

Awesome Zellij

Top comments (0)