Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 37 additions & 27 deletions images/grafana/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,36 +1,46 @@
# We use an ARG to dynamically set the base version from CI
ARG GRAFANA_VERSION=12.3.1

# --- Stage 1: Downloader ---
FROM alpine:3.19 AS downloader
# https://grafana.com/docs/grafana/latest/setup-grafana/configure-docker/#build-a-grafana-docker-image-with-pre-installed-plugins
# https://github.com/grafana/grafana/blob/main/packaging/docker/custom/Dockerfile

# Prevents silent pipeline failures
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]

# Install tools needed to parse YAML and extract zips
RUN apk add --no-cache curl yq unzip
ARG GRAFANA_VERSION=12.3.1

WORKDIR /downloads
COPY plugins.yaml .
FROM grafana/grafana:${GRAFANA_VERSION}

# Parse the YAML file and download/extract each plugin
RUN mkdir -p /plugins && \
yq e '.plugins[] | .name + " " + .version' plugins.yaml | while read -r plugin version; do \
echo "Downloading $plugin version $version..."; \
curl -fL -o "/tmp/${plugin}.zip" "https://grafana.com/api/plugins/${plugin}/versions/${version}/download"; \
unzip -q "/tmp/${plugin}.zip" -d "/plugins/${plugin}"; \
rm "/tmp/${plugin}.zip"; \
done
ARG GF_GID="0"

# --- Stage 2: Final Image ---
FROM grafana/grafana:${GRAFANA_VERSION}
ENV GF_PATHS_PLUGINS="/var/lib/grafana-plugins"

USER root

# Copy only the extracted plugins from the downloader stage
COPY --from=downloader /plugins /opt/grafana/plugins

# Ensure Grafana owns the plugins directory
RUN chown -R 472:0 /opt/grafana/plugins
# Create the plugins directory with all permissions since Grafana will need to write to it when installing plugins, and we want to avoid permission issues
RUN mkdir -p "$GF_PATHS_PLUGINS" && \
chown -R grafana:${GF_GID} "$GF_PATHS_PLUGINS" && \
chmod -R 777 "$GF_PATHS_PLUGINS"

USER grafana

# Copy the plugins list into a temporary location in the container
COPY plugins.txt /tmp/plugins.txt

SHELL ["/bin/bash", "-o", "pipefail", "-c"]

# Loop through the file and install each plugin
RUN set -e; \
while IFS= read -r line || [ -n "$line" ]; do \
# Strip leading/trailing whitespace
plugin=$(echo "$line" | xargs); \
# Skip empty lines or comments
case "$plugin" in \
""|\#*) continue ;; \
esac; \
\
if echo "$plugin" | grep -q ';'; then \
# Handle custom plugin URLs (url;folder)
pluginUrl=$(echo "$plugin" | cut -d';' -f 1); \
pluginInstallFolder=$(echo "$plugin" | cut -d';' -f 2); \
grafana cli --pluginUrl "${pluginUrl}" --pluginsDir "${GF_PATHS_PLUGINS}" plugins install "${pluginInstallFolder}"; \
else \
# If the file contains "plugin version" (space separated), map it to "plugin@version"
formattedPlugin=$(echo "$plugin" | awk '{if ($2) print $1"@"$2; else print $1}'); \
grafana cli --pluginsDir "${GF_PATHS_PLUGINS}" plugins install "${formattedPlugin}"; \
fi; \
done < /tmp/plugins.txt
31 changes: 27 additions & 4 deletions images/grafana/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,34 @@ The default Grafana image allows installing plugins at runtime via environment v

This image extends `grafana/grafana` with the following adjustments:

- Uses a multi-stage build to download and extract plugins defined in `plugins.yaml`.
- Bakes the extracted plugins directly into the `/var/lib/grafana/plugins` directory of the final image.
- Ensures the correct permissions (`472:0`) are applied so Grafana can read the plugins seamlessly.
- Installs plugins during the build process using the `grafana cli`.
- Pre-installs plugins defined in `plugins.txt`.
- Bakes the plugins into the `/var/lib/grafana-plugins` directory.
- Configures `GF_PATHS_PLUGINS` to point to the pre-installed plugins directory.

To update or add new plugins, modify the `plugins.yaml` file and rebuild the image.
## Configuration

### Plugins List (`plugins.txt`)

To update or add new plugins, modify the `plugins.txt` file and rebuild the image. The file supports two formats:

1. **Standard Plugins:** One plugin name per line (optionally followed by a version).
```text
redis-datasource
redis-app 2.1.0
```
2. **Custom URL Plugins:** Use the format `url;folder`.
```text
https://github.com/example/plugin/releases/download/v1.0.0/plugin.zip;plugin-folder-name
```

### Pre-installed Plugins

Currently, this image includes:

- **Data Sources:** `redis-datasource`, `redis-app`
- **Panels:** `magnesium-wordcloud-panel`
- **Core / App Plugins:** `grafana-pyroscope-app`, `grafana-exploretraces-app`, `grafana-metricsdrilldown-app`, `grafana-lokiexplore-app`

## Base Image

Expand Down
12 changes: 12 additions & 0 deletions images/grafana/plugins.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Data Sources
redis-datasource
redis-app

# Panels
magnesium-wordcloud-panel

# Core / App Plugins
grafana-pyroscope-app
grafana-exploretraces-app
grafana-metricsdrilldown-app
grafana-lokiexplore-app
7 changes: 0 additions & 7 deletions images/grafana/plugins.yaml

This file was deleted.

Loading