diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml index 67c1e13..6056e8d 100644 --- a/.github/workflows/docker-build.yaml +++ b/.github/workflows/docker-build.yaml @@ -1,7 +1,6 @@ name: Docker on: push: - branches: [ master, beta ] # Publish semver tags as releases. tags: [ 'v*.*.*' ] @@ -18,20 +17,17 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 - with: - fetch-depth: 0 + uses: actions/checkout@v6 - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 with: platforms: 'arm64,arm' - 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 # https://github.com/docker/login-action - name: Log into registry ${{ env.REGISTRY }} - if: github.event_name != 'pull_request' - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} @@ -40,30 +36,30 @@ jobs: # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v5 with: flavor: | - latest=false + latest=true + suffix=-collector,onlatest=true tags: | - type=ref,enable=true,event=branch,suffix=-collector - type=semver,pattern=v{{major}}.{{minor}}.{{patch}},suffix=-collector - type=semver,pattern=v{{major}}.{{minor}},suffix=-collector - type=semver,pattern=v{{major}},suffix=-collector + type=semver,pattern=v{{major}}.{{minor}}.{{patch}} + type=semver,pattern=v{{major}}.{{minor}} + type=semver,pattern=v{{major}} 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 - name: Build and push Docker image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v6 with: platforms: linux/amd64,linux/arm64,linux/arm/v7 context: . file: docker/Dockerfile.collector - push: ${{ github.event_name != 'pull_request' }} + push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} -# cache-from: type=gha -# cache-to: type=gha,mode=max + cache-from: type=gha + cache-to: type=gha,mode=max web: runs-on: ubuntu-latest @@ -73,20 +69,19 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v6 - name: "Populate frontend version information" run: "cd webapp/frontend && ./git.version.sh" - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 with: platforms: 'arm64,arm' - 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 # https://github.com/docker/login-action - name: Log into registry ${{ env.REGISTRY }} - if: github.event_name != 'pull_request' - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} @@ -95,29 +90,31 @@ jobs: # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v5 with: flavor: | - latest=false + latest=true + suffix=-web,onlatest=true tags: | - type=ref,enable=true,event=branch,suffix=-web - type=semver,pattern=v{{major}}.{{minor}}.{{patch}},suffix=-web - type=semver,pattern=v{{major}}.{{minor}},suffix=-web - type=semver,pattern=v{{major}},suffix=-web + type=semver,pattern=v{{major}}.{{minor}}.{{patch}} + type=semver,pattern=v{{major}}.{{minor}} + type=semver,pattern=v{{major}} 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 - name: Build and push Docker image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v6 with: platforms: linux/amd64,linux/arm64,linux/arm/v7 context: . - file: docker/Dockerfile.web - push: ${{ github.event_name != 'pull_request' }} + file: docker/Dockerfile.collector + push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} -# cache-from: type=gha -# cache-to: type=gha,mode=max + cache-from: type=gha + cache-to: type=gha,mode=max + omnibus: runs-on: ubuntu-latest permissions: @@ -126,20 +123,19 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v6 - name: "Populate frontend version information" run: "cd webapp/frontend && ./git.version.sh" - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 with: platforms: 'arm64,arm' - 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 # https://github.com/docker/login-action - name: Log into registry ${{ env.REGISTRY }} - if: github.event_name != 'pull_request' - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} @@ -148,24 +144,29 @@ jobs: # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v5 with: + flavor: | + latest=true + # tag latest and latest-omnibus + suffix=-omnibus,onlatest=false tags: | - type=ref,enable=true,event=branch,suffix=-omnibus - type=semver,pattern=v{{major}}.{{minor}}.{{patch}},suffix=-omnibus - type=semver,pattern=v{{major}}.{{minor}},suffix=-omnibus - type=semver,pattern=v{{major}},suffix=-omnibus + type=raw,value=latest + type=semver,pattern=v{{major}}.{{minor}}.{{patch}} + type=semver,pattern=v{{major}}.{{minor}} + type=semver,pattern=v{{major}} 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 - name: Build and push Docker image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v6 with: - platforms: linux/amd64,linux/arm64 + platforms: linux/amd64,linux/arm64,linux/arm/v7 context: . - file: docker/Dockerfile - push: ${{ github.event_name != 'pull_request' }} + file: docker/Dockerfile.collector + push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} -# cache-from: type=gha -# cache-to: type=gha,mode=max + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/README.md b/README.md index c85a470..6a1c893 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,11 @@ See [docs/TROUBLESHOOTING_DEVICE_COLLECTOR.md](./docs/TROUBLESHOOTING_DEVICE_COL ## 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: > 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/sdb \ --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 - `--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) - `--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 In addition to the Omnibus image (available under the `latest` tag) you can deploy in Hub/Spoke mode, which requires 3 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. -- `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 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 \ -v `pwd`/scrutiny:/opt/scrutiny/config \ --name scrutiny-web \ - ghcr.io/analogj/scrutiny:master-web + ghcr.io/analogj/scrutiny:latest-web docker run --restart unless-stopped \ -v /run/udev:/run/udev:ro \ @@ -120,7 +125,7 @@ docker run --restart unless-stopped \ --device=/dev/sdb \ -e COLLECTOR_API_ENDPOINT=http://SCRUTINY_WEB_IPADDRESS:8080 \ --name scrutiny-collector \ - ghcr.io/analogj/scrutiny:master-collector + ghcr.io/analogj/scrutiny:latest-collector ``` ## Manual Installation (without-Docker) @@ -157,7 +162,7 @@ Neither file is required, however if provided, it allows you to configure how Sc ## 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). -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 * * *`). `docker run -e COLLECTOR_CRON_SCHEDULE="0 0 * * *" ...` diff --git a/docs/INSTALL_HUB_SPOKE.md b/docs/INSTALL_HUB_SPOKE.md index c2f9939..f5541ff 100644 --- a/docs/INSTALL_HUB_SPOKE.md +++ b/docs/INSTALL_HUB_SPOKE.md @@ -80,7 +80,8 @@ services: scrutiny: restart: unless-stopped 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: - 8080:8080 volumes: @@ -169,7 +170,8 @@ services: collector: 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: - SYS_RAWIO volumes: diff --git a/docs/TROUBLESHOOTING_DOCKER.md b/docs/TROUBLESHOOTING_DOCKER.md index 9b3fc26..99b2ed8 100644 --- a/docs/TROUBLESHOOTING_DOCKER.md +++ b/docs/TROUBLESHOOTING_DOCKER.md @@ -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` -development process. However if you want to ensure you're only using the latest release, you can change to `latest` +> TL;DR; The `latest-omnibus`, `latest-collector`, and `latest-web` tags point to the most recent release. (`latest` points to `latest-omnibus`) +> 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), -instead development is done in a feature branch, or committed to the `beta` branch. +In general scrutiny follows a feature branch development process, which means that the `master` branch should ideally always be free of bugs +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, -I merge the changes to `master` and trigger the creation of a new release -- ie, when master is updated, a new release -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. +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 +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. # Running Docker `rootless`