Update docker builds (#901)

Closes #895 #896

* dont build every master commit
* push latest tags with releases
* update docs accordingly
* bump action versions
This commit is contained in:
Aram Akhavan
2026-02-08 20:11:04 -08:00
committed by GitHub
parent c95b272485
commit 19ac712b78
4 changed files with 81 additions and 77 deletions
+54 -53
View File
@@ -1,7 +1,6 @@
name: Docker name: Docker
on: on:
push: push:
branches: [ master, beta ]
# Publish semver tags as releases. # Publish semver tags as releases.
tags: [ 'v*.*.*' ] tags: [ 'v*.*.*' ]
@@ -18,20 +17,17 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v3
with: with:
platforms: 'arm64,arm' platforms: 'arm64,arm'
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v3
# Login against a Docker registry except on PR # Login against a Docker registry except on PR
# https://github.com/docker/login-action # https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }} - name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request' uses: docker/login-action@v3
uses: docker/login-action@v2
with: with:
registry: ${{ env.REGISTRY }} registry: ${{ env.REGISTRY }}
username: ${{ github.actor }} username: ${{ github.actor }}
@@ -40,30 +36,30 @@ jobs:
# https://github.com/docker/metadata-action # https://github.com/docker/metadata-action
- name: Extract Docker metadata - name: Extract Docker metadata
id: meta id: meta
uses: docker/metadata-action@v4 uses: docker/metadata-action@v5
with: with:
flavor: | flavor: |
latest=false latest=true
suffix=-collector,onlatest=true
tags: | tags: |
type=ref,enable=true,event=branch,suffix=-collector type=semver,pattern=v{{major}}.{{minor}}.{{patch}}
type=semver,pattern=v{{major}}.{{minor}}.{{patch}},suffix=-collector type=semver,pattern=v{{major}}.{{minor}}
type=semver,pattern=v{{major}}.{{minor}},suffix=-collector type=semver,pattern=v{{major}}
type=semver,pattern=v{{major}},suffix=-collector
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Build and push Docker image with Buildx (don't push on PR) # Build and push Docker image with Buildx
# https://github.com/docker/build-push-action # https://github.com/docker/build-push-action
- name: Build and push Docker image - name: Build and push Docker image
uses: docker/build-push-action@v3 uses: docker/build-push-action@v6
with: with:
platforms: linux/amd64,linux/arm64,linux/arm/v7 platforms: linux/amd64,linux/arm64,linux/arm/v7
context: . context: .
file: docker/Dockerfile.collector file: docker/Dockerfile.collector
push: ${{ github.event_name != 'pull_request' }} push: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
# cache-from: type=gha cache-from: type=gha
# cache-to: type=gha,mode=max cache-to: type=gha,mode=max
web: web:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -73,20 +69,19 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v2 uses: actions/checkout@v6
- name: "Populate frontend version information" - name: "Populate frontend version information"
run: "cd webapp/frontend && ./git.version.sh" run: "cd webapp/frontend && ./git.version.sh"
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v3
with: with:
platforms: 'arm64,arm' platforms: 'arm64,arm'
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v3
# Login against a Docker registry except on PR # Login against a Docker registry except on PR
# https://github.com/docker/login-action # https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }} - name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request' uses: docker/login-action@v3
uses: docker/login-action@v2
with: with:
registry: ${{ env.REGISTRY }} registry: ${{ env.REGISTRY }}
username: ${{ github.actor }} username: ${{ github.actor }}
@@ -95,29 +90,31 @@ jobs:
# https://github.com/docker/metadata-action # https://github.com/docker/metadata-action
- name: Extract Docker metadata - name: Extract Docker metadata
id: meta id: meta
uses: docker/metadata-action@v4 uses: docker/metadata-action@v5
with: with:
flavor: | flavor: |
latest=false latest=true
suffix=-web,onlatest=true
tags: | tags: |
type=ref,enable=true,event=branch,suffix=-web type=semver,pattern=v{{major}}.{{minor}}.{{patch}}
type=semver,pattern=v{{major}}.{{minor}}.{{patch}},suffix=-web type=semver,pattern=v{{major}}.{{minor}}
type=semver,pattern=v{{major}}.{{minor}},suffix=-web type=semver,pattern=v{{major}}
type=semver,pattern=v{{major}},suffix=-web
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Build and push Docker image with Buildx (don't push on PR)
# Build and push Docker image with Buildx
# https://github.com/docker/build-push-action # https://github.com/docker/build-push-action
- name: Build and push Docker image - name: Build and push Docker image
uses: docker/build-push-action@v3 uses: docker/build-push-action@v6
with: with:
platforms: linux/amd64,linux/arm64,linux/arm/v7 platforms: linux/amd64,linux/arm64,linux/arm/v7
context: . context: .
file: docker/Dockerfile.web file: docker/Dockerfile.collector
push: ${{ github.event_name != 'pull_request' }} push: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
# cache-from: type=gha cache-from: type=gha
# cache-to: type=gha,mode=max cache-to: type=gha,mode=max
omnibus: omnibus:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
@@ -126,20 +123,19 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v2 uses: actions/checkout@v6
- name: "Populate frontend version information" - name: "Populate frontend version information"
run: "cd webapp/frontend && ./git.version.sh" run: "cd webapp/frontend && ./git.version.sh"
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v3
with: with:
platforms: 'arm64,arm' platforms: 'arm64,arm'
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v3
# Login against a Docker registry except on PR # Login against a Docker registry except on PR
# https://github.com/docker/login-action # https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }} - name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request' uses: docker/login-action@v3
uses: docker/login-action@v2
with: with:
registry: ${{ env.REGISTRY }} registry: ${{ env.REGISTRY }}
username: ${{ github.actor }} username: ${{ github.actor }}
@@ -148,24 +144,29 @@ jobs:
# https://github.com/docker/metadata-action # https://github.com/docker/metadata-action
- name: Extract Docker metadata - name: Extract Docker metadata
id: meta id: meta
uses: docker/metadata-action@v4 uses: docker/metadata-action@v5
with: with:
flavor: |
latest=true
# tag latest and latest-omnibus
suffix=-omnibus,onlatest=false
tags: | tags: |
type=ref,enable=true,event=branch,suffix=-omnibus type=raw,value=latest
type=semver,pattern=v{{major}}.{{minor}}.{{patch}},suffix=-omnibus type=semver,pattern=v{{major}}.{{minor}}.{{patch}}
type=semver,pattern=v{{major}}.{{minor}},suffix=-omnibus type=semver,pattern=v{{major}}.{{minor}}
type=semver,pattern=v{{major}},suffix=-omnibus type=semver,pattern=v{{major}}
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Build and push Docker image with Buildx (don't push on PR)
# Build and push Docker image with Buildx
# https://github.com/docker/build-push-action # https://github.com/docker/build-push-action
- name: Build and push Docker image - name: Build and push Docker image
uses: docker/build-push-action@v3 uses: docker/build-push-action@v6
with: with:
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64,linux/arm/v7
context: . context: .
file: docker/Dockerfile file: docker/Dockerfile.collector
push: ${{ github.event_name != 'pull_request' }} push: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
# cache-from: type=gha cache-from: type=gha
# cache-to: type=gha,mode=max cache-to: type=gha,mode=max
+12 -7
View File
@@ -67,6 +67,11 @@ See [docs/TROUBLESHOOTING_DEVICE_COLLECTOR.md](./docs/TROUBLESHOOTING_DEVICE_COL
## Docker ## Docker
> [!IMPORTANT]
> Using `latest-` tags is dangerous as it can update your image without warning. It is a best practice to pin a specific version. scrutiny pushes releases with semver tags,
> so you can use tags like `v0.8.2-omnibus`, `v0.8-web`, `v0-collector`, etc. For a list of all image tags see
> [scrutiny package versions](https://github.com/AnalogJ/scrutiny/pkgs/container/scrutiny/versions?filters%5Bversion_type%5D=tagged)
If you're using Docker, getting started is as simple as running the following command: If you're using Docker, getting started is as simple as running the following command:
> See [docker/example.omnibus.docker-compose.yml](https://github.com/AnalogJ/scrutiny/blob/master/docker/example.omnibus.docker-compose.yml) for a docker-compose file. > See [docker/example.omnibus.docker-compose.yml](https://github.com/AnalogJ/scrutiny/blob/master/docker/example.omnibus.docker-compose.yml) for a docker-compose file.
@@ -80,23 +85,23 @@ docker run -p 8080:8080 -p 8086:8086 --restart unless-stopped \
--device=/dev/sda \ --device=/dev/sda \
--device=/dev/sdb \ --device=/dev/sdb \
--name scrutiny \ --name scrutiny \
ghcr.io/analogj/scrutiny:master-omnibus ghcr.io/analogj/scrutiny:latest-omnibus
``` ```
- `/run/udev` is necessary to provide the Scrutiny collector with access to your device metadata - `/run/udev` is necessary to provide the Scrutiny collector with access to your device metadata
- `--cap-add SYS_RAWIO` is necessary to allow `smartctl` permission to query your device SMART data - `--cap-add SYS_RAWIO` is necessary to allow `smartctl` permission to query your device SMART data
- NOTE: If you have **NVMe** drives, you must add `--cap-add SYS_ADMIN` as well. See issue [#26](https://github.com/AnalogJ/scrutiny/issues/26#issuecomment-696817130) - NOTE: If you have **NVMe** drives, you must add `--cap-add SYS_ADMIN` as well. See issue [#26](https://github.com/AnalogJ/scrutiny/issues/26#issuecomment-696817130)
- `--device` entries are required to ensure that your hard disk devices are accessible within the container. - `--device` entries are required to ensure that your hard disk devices are accessible within the container.
- `ghcr.io/analogj/scrutiny:master-omnibus` is a omnibus image, containing both the webapp server (frontend & api) as well as the S.M.A.R.T metric collector. (see below) - `ghcr.io/analogj/scrutiny:latest-omnibus` is a omnibus image, containing both the webapp server (frontend & api) as well as the S.M.A.R.T metric collector. (see below)
### Hub/Spoke Deployment ### Hub/Spoke Deployment
In addition to the Omnibus image (available under the `latest` tag) you can deploy in Hub/Spoke mode, which requires 3 In addition to the Omnibus image (available under the `latest` tag) you can deploy in Hub/Spoke mode, which requires 3
other Docker images: other Docker images:
- `ghcr.io/analogj/scrutiny:master-collector` - Contains the Scrutiny data collector, `smartctl` binary and cron-like - `ghcr.io/analogj/scrutiny:latest-collector` - Contains the Scrutiny data collector, `smartctl` binary and cron-like
scheduler. You can run one collector on each server. scheduler. You can run one collector on each server.
- `ghcr.io/analogj/scrutiny:master-web` - Contains the Web UI and API. Only one container necessary - `ghcr.io/analogj/scrutiny:latest-web` - Contains the Web UI and API. Only one container necessary
- `influxdb:2.2` - InfluxDB image, used by the Web container to persist SMART data. Only one container necessary - `influxdb:2.2` - InfluxDB image, used by the Web container to persist SMART data. Only one container necessary
See [docs/TROUBLESHOOTING_INFLUXDB.md](./docs/TROUBLESHOOTING_INFLUXDB.md) See [docs/TROUBLESHOOTING_INFLUXDB.md](./docs/TROUBLESHOOTING_INFLUXDB.md)
@@ -111,7 +116,7 @@ docker run -p 8086:8086 --restart unless-stopped \
docker run -p 8080:8080 --restart unless-stopped \ docker run -p 8080:8080 --restart unless-stopped \
-v `pwd`/scrutiny:/opt/scrutiny/config \ -v `pwd`/scrutiny:/opt/scrutiny/config \
--name scrutiny-web \ --name scrutiny-web \
ghcr.io/analogj/scrutiny:master-web ghcr.io/analogj/scrutiny:latest-web
docker run --restart unless-stopped \ docker run --restart unless-stopped \
-v /run/udev:/run/udev:ro \ -v /run/udev:/run/udev:ro \
@@ -120,7 +125,7 @@ docker run --restart unless-stopped \
--device=/dev/sdb \ --device=/dev/sdb \
-e COLLECTOR_API_ENDPOINT=http://SCRUTINY_WEB_IPADDRESS:8080 \ -e COLLECTOR_API_ENDPOINT=http://SCRUTINY_WEB_IPADDRESS:8080 \
--name scrutiny-collector \ --name scrutiny-collector \
ghcr.io/analogj/scrutiny:master-collector ghcr.io/analogj/scrutiny:latest-collector
``` ```
## Manual Installation (without-Docker) ## Manual Installation (without-Docker)
@@ -157,7 +162,7 @@ Neither file is required, however if provided, it allows you to configure how Sc
## Cron Schedule ## Cron Schedule
Unfortunately the Cron schedule cannot be configured via the `collector.yaml` (as the collector binary needs to be trigged by a scheduler/cron). Unfortunately the Cron schedule cannot be configured via the `collector.yaml` (as the collector binary needs to be trigged by a scheduler/cron).
However, if you are using the official `ghcr.io/analogj/scrutiny:master-collector` or `ghcr.io/analogj/scrutiny:master-omnibus` docker images, However, if you are using the official `ghcr.io/analogj/scrutiny:latest-collector` or `ghcr.io/analogj/scrutiny:latest-omnibus` docker images,
you can use the `COLLECTOR_CRON_SCHEDULE` environmental variable to override the default cron schedule (daily @ midnight - `0 0 * * *`). you can use the `COLLECTOR_CRON_SCHEDULE` environmental variable to override the default cron schedule (daily @ midnight - `0 0 * * *`).
`docker run -e COLLECTOR_CRON_SCHEDULE="0 0 * * *" ...` `docker run -e COLLECTOR_CRON_SCHEDULE="0 0 * * *" ...`
+4 -2
View File
@@ -80,7 +80,8 @@ services:
scrutiny: scrutiny:
restart: unless-stopped restart: unless-stopped
container_name: scrutiny container_name: scrutiny
image: ghcr.io/analogj/scrutiny:master-web # best practice: pin to a specific release instead of latest
image: ghcr.io/analogj/scrutiny:latest-web
ports: ports:
- 8080:8080 - 8080:8080
volumes: volumes:
@@ -169,7 +170,8 @@ services:
collector: collector:
restart: unless-stopped restart: unless-stopped
image: 'ghcr.io/analogj/scrutiny:master-collector' # best practice: pin to a specific release instead of latest
image: 'ghcr.io/analogj/scrutiny:latest-collector'
cap_add: cap_add:
- SYS_RAWIO - SYS_RAWIO
volumes: volumes:
+11 -15
View File
@@ -1,22 +1,18 @@
# Docker Images `master-omnibus` vs `latest` # Docker Images `latest` vs `nightly`
> TL;DR; The `master-omnibus` and `latest` tags are almost semantically identical, as I follow a `golden master` > TL;DR; The `latest-omnibus`, `latest-collector`, and `latest-web` tags point to the most recent release. (`latest` points to `latest-omnibus`)
development process. However if you want to ensure you're only using the latest release, you can change to `latest` > The `nightly-omnibus`, `nightly-collector`, and `nightly-web` tags point to builds that are generated every night from the latest commit on the `master` branch.
The CI script used to orchestrate the docker image builds can be found here: https://github.com/AnalogJ/scrutiny/blob/master/.github/workflows/docker-build.yaml#L166-L184 The CD scripts used to orchestrate the docker image builds can be found here:
* https://github.com/AnalogJ/scrutiny/blob/master/.github/workflows/docker-build.yaml
* https://github.com/AnalogJ/scrutiny/blob/master/.github/workflows/docker-nightly.yaml
In general Scrutiny follows a `golden master` development process, which means that the `master` branch is not directly updated (unless its for documentation changes), In general scrutiny follows a feature branch development process, which means that the `master` branch should ideally always be free of bugs
instead development is done in a feature branch, or committed to the `beta` branch. This is driven by the requirement that every PR be reviewed and pass all tests. Unfortunately, bugs do make it through, especially because of the
enormous number of hard drives that scrutiny must support..
As development progresses, and we're satisfied that a feature is complete, and the quality is acceptable, This means that while the nightly builds should have the latest features and bug fixes, there may be things that sneak through. Unless you need a particular
I merge the changes to `master` and trigger the creation of a new release -- ie, when master is updated, a new release feature or bug fix, we recommend sticking to releases. Also note that using `latest` tags is generally considered a bad practice; pin a specific version instead.
is almost immediately created (and tagged with `latest`)
So changing from `master-omnibus -> latest` will be the same thing for all intents and purposes.
> NOTE: Previously, there was a `automated cron build` that ran on the `master` and `beta` branches.
They used to trigger a `nightly` build, even if nothing has changed on the branch. This has a couple of benefits, but one is to
ensure that there's no broken external dependencies in our (unchanged) code. This `nightly` build no longer updates the `master-omnibus` tag.
# Running Docker `rootless` # Running Docker `rootless`