Container Control Panel

OliveTin is frequently used to create simple container control panels, this is one of the default examples that ships with the standard OliveTin config.yaml.

preview

Setup if running inside a container

You can control other containers, when running OliveTin inside a container itself, however you need to do some extra setup when creating the OliveTin container.

Ensure your container has permissions to control docker

You have two alternatives to allow OliveTin (running inside a container) to talk to the Docker daemon through the bind-mounted socket. Pick one:

Option 1 — Use --privileged (simplest)

Simplest for most users. Podman does not have this requirement.
  • Run the container with --privileged and as root (eg --user root).

  • This avoids user/group permission issues on /var/run/docker.sock.

If you are getting "permission denied" errors it is probably because OliveTin runs as user UID 1000 by default, which is not allowed by your docker host. Running with --user root under --privileged resolves this quickly. Note that PUID and PGID variables will not work.

Option 2 — Run as non-root in the host docker group (no --privileged)

Use the standard Docker guidance to manage Docker as a non-root user (becoming a member of the docker group) and match the group’s GID inside the container so the process can access the socket permissions.

  • Docs: Manage Docker as a non-root user

  • Find the docker group GID on the host, for example using getent group docker.

  • Run the container with your user UID and the docker group GID, and bind-mount the socket. Using Compose:

docker-compose.yml
services:
  olivetin:
    container_name: olivetin
    image: jamesread/olivetin
    user: ${UID}:${docker_group_id}
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

Where UID and docker_group_id are provided via your shell environment or a .env file next to your Compose file, for example:

env
UID=1000
docker_group_id=995

This allows you to run the container as a non-root user, while still allowing access to /var/run/docker.sock.

Pass the docker socket into the container

  1. Pass /var/run/docker.sock as a bind mount to the container when creating it, eg:

    docker create --privileged --user root -v /var/run/docker.sock:/var/run/docker.sock ...additional args here...

    Or, using the docker run syntax;

    docker run --privileged --user root -v /var/run/docker.sock:/var/run/docker.sock --name OliveTin jamesread/olivetin
  2. The official x86_64 docker container comes with the docker client pre-installed. If you are using arm or and arm64 container, you will need to add Docker yourself.

    The reason that the arm and arm64 containers do not include docker, is that when these images are cross-compiled at build time, it takes FOREVER because we have to emulate arm.

After you have passed the socket into the container (and optionally installed docker), you should be able to setup docker actions like it’s shown in the example above.

Entity file

To build this Container Control dashboard, we use an entity file that stores and updates produced by docker ps --format json > /etc/OliveTin/entities/containers.json

/etc/OliveTin/entities/containers.json
{"Command":"\"/bin/bash\"","CreatedAt":"2024-02-28 22:33:35 +0000 GMT","ID":"fcf468e18a0e","Image":"fedora","Labels":"maintainer=Clement Verna \u003ccverna@fedoraproject.org\u003e","LocalVolumes":"0","Mounts":"","Names":"minecraft","Networks":"bridge","Ports":"","RunningFor":"3 minutes ago","Size":"0B","State":"created","Status":"Created"}
{"Command":"\"/bin/bash\"","CreatedAt":"2024-02-23 23:18:57 +0000 GMT","ID":"442dd6fe316a","Image":"fedora","Labels":"maintainer=Clement Verna \u003ccverna@fedoraproject.org\u003e","LocalVolumes":"0","Mounts":"","Names":"brave_shirley","Networks":"bridge","Ports":"","RunningFor":"4 days ago","Size":"0B","State":"created","Status":"Created"}

You can generate this file yourself the first time, but the config.yaml below shows how OliveTin can run the docker ps command on startup, and on a schedule to update the file.

Configuration

Then use the following configuration file;

config.yaml
# This config has two actions which are applied to all "container" entities 
# found in the entity file.
#
# Docs: http://localhost/docs.olivetin.app/docs/entities.html
actions:
  - title: Start {{ container.Names }}
    icon: box
    shell: docker start {{ container.Names }}
    entity: container
    triggers:
      - Update container entity file

  - title: Stop {{ container.Names }}
    icon: box
    shell: docker stop {{ container.Names }}
    entity: container
    triggers:
      - Update container entity file

  # This is a hidden action, that is run on startup, and every 5 minutes, and 
  # when the above start/stop commands are run (see the `triggers` property).

  - title: Update container entity file
    shell: 'docker ps -a --format json > /etc/OliveTin/entities/containers.json'
    hidden: true
    execOnStartup: true
    execOnCron: '*/5 * * * *'

# Docs: http://docs.olivetin.app/entities.html
entities:
  - file: /etc/OliveTin/entities/containers.json
    name: container

# The only way to properly use entities, are to use them with a `fieldset` on
# a dashboard.
dashboards:
  # This is the second dashboard.
  - title: My Containers
    contents:
      - title: 'Container {{ container.Names }} ({{ container.Image }})'
        entity: container
        type: fieldset
        contents:
          - type: display
            title: |
              {{ container.RunningFor }} <br /><br /><strong>{{ container.State }}</strong>
          - title: 'Start {{ container.Names }}'
          - title: 'Stop {{ container.Names }}'