Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-arch Linux containers #1874

Merged
merged 12 commits into from
Jun 7, 2024
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
72 changes: 30 additions & 42 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@ on:
env:
DOTNET_NOLOGO: true
jobs:
release:
windows-standalone:
if: ${{ github.actor != 'dependabot[bot]' }}
runs-on: windows-2022
outputs:
version: ${{ steps.save-version.outputs.version }}
steps:
- name: Check for secrets
env:
Expand All @@ -38,18 +36,9 @@ jobs:
- name: Build Frontend
run: .\build.ps1
working-directory: src/ServicePulse.Host
- name: Run component tests
run: npm run test:component
working-directory: src/Frontend
- name: Run application tests
run: npm run test:application
working-directory: src/Frontend
# .NET Build and sign
- name: Build
run: dotnet build src --configuration Release
- id: save-version
name: Save version
run: echo "version=${{env.MinVerVersion}}" >> $env:GITHUB_OUTPUT
- name: Sign NuGet packages
uses: Particular/sign-nuget-packages-action@v1.0.0
with:
Expand Down Expand Up @@ -107,19 +96,9 @@ jobs:
uses: Particular/push-octopus-package-action@main
with:
octopus-deploy-api-key: ${{ secrets.OCTOPUS_DEPLOY_API_KEY }}
docker:
needs: release
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: windows-2019
image-name: servicepulse-windows
dockerfile: dockerfile.iis
- os: ubuntu-20.04
image-name: servicepulse
dockerfile: dockerfile.nginx
fail-fast: false
linux-container:
if: ${{ github.actor != 'dependabot[bot]' }}
runs-on: ubuntu-22.04
steps:
- name: Check for secrets
env:
Expand All @@ -130,30 +109,39 @@ jobs:
uses: actions/checkout@v4.1.6
with:
fetch-depth: 0
- name: Install MinVer CLI
run: dotnet tool install --global minver-cli
- name: Determine version
run: echo "MinVerVersion=$(minver)" >> $GITHUB_ENV
- name: Set up Node.js
uses: actions/setup-node@v4.0.2
with:
node-version: 21.6.x
# Build Frontend
- name: Build Frontend
run: .\build.ps1
shell: pwsh
working-directory: src/ServicePulse.Host
- name: Update app.constants.js
shell: pwsh
- name: Update app.constants.js with MinVerVersion
run: |
$filename = "src/ServicePulse.Host/app/js/app.constants.js"
(Get-Content $filename).replace("1.2.0", "${{ needs.release.outputs.version }}") | Set-Content $filename
(Get-Content $filename).replace("1.2.0", "${{ env.MinVerVersion }}") | Set-Content $filename
shell: pwsh
- name: Build Docker image
if: ${{ matrix.image-name == 'servicepulse' || (github.event_name == 'push' && github.ref_type == 'tag') }}
run: docker build -t particular/${{ matrix.image-name }}:${{ needs.release.outputs.version }} -f ${{ matrix.dockerfile }} .
working-directory: src
- name: Login to Docker Hub
if: ${{ github.event_name == 'push' && github.ref_type == 'tag' }}
uses: docker/login-action@v3.1.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Push Docker image
if: ${{ github.event_name == 'push' && github.ref_type == 'tag' }}
run: docker push particular/${{ matrix.image-name }}:${{ needs.release.outputs.version }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.3.0
- name: Pull nginx:stable-alpine and determine digest
run: |
docker pull nginx:stable-alpine
echo "NGINX_DIGEST=$(docker inspect -f json nginx:stable-alpine | jq -r .[0].RepoDigests[0] | cut -d@ -f2)" >> $GITHUB_ENV
- name: Log in to GitHub container registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Build & inspect image
env:
TAG_NAME: ${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.number) || env.MinVerVersion }}
run: |
docker buildx build --push --tag ghcr.io/particular/servicepulse:${{ env.TAG_NAME }} --file src/Container/Dockerfile \
--build-arg NGINX_TAGORDIGEST="@${{ env.NGINX_DIGEST }}" \
--build-arg VERSION=${{ env.MinVerVersion }} \
--build-arg GITHUB_SHA=${{ github.sha }} \
--build-arg GITHUB_REF_NAME=${{ github.ref.name }} \
--platform linux/arm64,linux/arm,linux/amd64 .
docker buildx imagetools inspect ghcr.io/particular/servicepulse:${{ env.TAG_NAME }}
32 changes: 2 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,34 +135,6 @@ ServicePulse is supported on the following desktop browser versions:
- Firefox ESR [current version](https://www.mozilla.org/en-US/firefox/enterprise/)
- Safari [latest major version](https://developer.apple.com/safari/)

## Docker image deployment
## Container image development

Dockerfiles for ServicePulse resides within the [`src`](https://github.com/Particular/ServicePulse/tree/master/src) folder. There are 2 docker files:

- 1 for a [Windows image](https://github.com/Particular/ServicePulse/blob/master/src/dockerfile.iis)
- 1 for a [Linux image](https://github.com/Particular/ServicePulse/blob/master/src/dockerfile.nginx)

### Building & staging docker images

The docker files are all built as part of the [release workflow](https://github.com/Particular/ServicePulse/blob/master/.github/workflows/release.yml), pushed to the Docker hub, and tagged with the version of ServicePulse being deployed. More details are available in the [documentation](https://docs.particular.net/servicepulse/containerization/).

For example, If we were deploying version 1.30.1 of ServicePulse, the build configurations after the Deploy step will build the following 2 containers for ServicePulse and tag them `1.30.1`:

- `particular/servicepulse:1.30.1`
- `particular/servicepule-windows:1.30.1`

These images are tagged with the specific version of ServicePulse being built and pushed to the corresponding public `particular/servicepulse{-os}` repositories. At this point, the docker images are considered staged. If someone is watching the feed directly, they can install the staged images by explicitly specifying the exact tag, e.g., `docker pull particular/servicepulse:1.30.1`.

### Promoting docker images to production

When a ServicePulse release is promoted to production, one of the steps is to take the staged images and re-tag them as the following:

- `particular/servicepulse:1.30.1` => `particular/servicepulse:1`
- This is so that customers interested in updates within a major can install the specific major only and not worry about breaking changes between major versions being automatically rolled out. Useful for auto-upgrading containers in a _production_ environment.
- `particular/servicepulse:1.30.1` => `particular/servicepulse:latest`
- Primarily for developers wanting to use the latest version (`docker-compose up -d --build --force-recreate --renew-anon-volumes`
- This is only true if the release's major version is the same as the current latest major version.
- If a fix is being backported to a previous major, then the `:latest` tag will not be updated.
- If a release targets the current latest major or is a new major after the previous latest, then the `:latest` tag is updated to match the version being released.

Once the tagging has been completed, the images are considered to be publicly released.
A Dockerfile for ServicePulse resides within the [`src/Container`](https://github.com/Particular/ServicePulse/tree/master/src/Container) folder. The container images are all built as part of the [release workflow](https://github.com/Particular/ServicePulse/blob/master/.github/workflows/release.yml) and staged in the [Github Container Registry](https://github.com/Particular/ServicePulse/pkgs/container/servicepulse). For branches with PRs the image will be tagged with the pr number, e.g. `pr-1234`.
39 changes: 39 additions & 0 deletions src/Container/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
ARG NGINX_TAGORDIGEST=":stable-alpine"
FROM nginx$NGINX_TAGORDIGEST

ARG VERSION
ARG GITHUB_SHA
ARG GITHUB_REF_NAME

LABEL org.opencontainers.image.title="ServicePulse" \
org.opencontainers.image.description="ServicePulse provides real-time production monitoring for distributed applications. It monitors the health of a system's endpoints, detects processing errors, sends failed messages for reprocessing, and ensures the specific environment's needs are met, all in one consolidated dashboard." \
org.opencontainers.image.authors="Particular Software" \
org.opencontainers.image.vendor="Particular Software" \
org.opencontainers.image.source="https://github.com/particular/servicepulse" \
org.opencontainers.image.documentation="https://github.com/Particular/ServicePulse/blob/master/src/Container/README.md" \
org.opencontainers.image.licenses="Commercial OR RPL-1.5" \
org.opencontainers.image.version=$VERSION \
org.opencontainers.image.revision=$GITHUB_SHA \
org.opencontainers.image.base.digest=$NGINX_TAGORDIGEST \
org.opencontainers.image.base.name="nginx:stable-alpine" \
com.particular.github.ref.name=$GITHUB_REF_NAME \
com.particular.support.url="https://particular.net/support" \
maintainer="Particular Software"

ENV SERVICECONTROL_URL="http://localhost:33333/api/"
ENV MONITORING_URLS="['http://localhost:33633/']"
ENV BASE_URL="/"

COPY /src/ServicePulse.Host/app /usr/share/nginx/html

RUN mv /usr/share/nginx/html/js/app.constants.js /usr/share/nginx/html/js/app.constants.template &&\
sed -i \
-e "s,http://localhost:33333/api/,\$SERVICECONTROL_URL,g" \
-e "s,\['http://localhost:33633/'\],\$MONITORING_URLS,g" \
-e "s,'/','\$BASE_URL',g" \
/usr/share/nginx/html/js/app.constants.template

ADD /src/Container/nginx.conf /etc/nginx/
ADD --chown=root:root --chmod=755 /src/Container/updateconstants.sh /docker-entrypoint.d/40-update-servicepulse-constants.sh

EXPOSE 90
80 changes: 80 additions & 0 deletions src/Container/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# ServicePulse

This document describes basic usage and information related to the ServicePulse image. The complete documentation of ServicePulse the application can be found on the [Particular Software documentation site](https://docs.particular.net/servicepulse/).

## Usage

The following is the most basic way to create a ServicePulse container using [Docker](https://www.docker.com/):

```shell
docker run -p 9090:90 particular/servicepulse:latest
```

### Environment Variables

- **`SERVICECONTROL_URL`**: _Default_: `http://localhost:33333/api/`. The url to your ServiceControl instance
- **`MONITORING_URLS`**: _Default_: `['http://localhost:33633/']`. A JSON array of URLs to your monitoring instances
- **`BASE_URL`**: _Default_ `'/'`. The base path to your ServicePulse install, for reverse proxy installations.

It may be desireable to run the ServiceControl services in an isolated network. When doing so ServicePulse must be configured to connect to those services using environment variables:

```shell
docker run -p 9090:90 -e SERVICECONTROL_URL="http://servicecontrol:33333/api/" -e MONITORING_URLS="['http://servicecontrol-monitoring:33633']" particular/servicepulse:latest
```

Or as part of a https://docs.docker.com/compose/compose-file/05-services/:

```yaml
services:
servicepulse:
ports:
- 9090:90
environment:
- SERVICECONTROL_URL=http://servicecontrol:33333/api/
- MONITORING_URLS=['http://servicecontrol-monitoring:33633']
image: particular/servicepulse:latest
```

### Image tagging

#### `latest` tag

This tag is primarily for developers wanting to use the latest version, e.g. `docker-compose up -d --build --force-recreate --renew-anon-volumes`.

If a release targets the current latest major or is a new major after the previous latest, then the `:latest` tag applied to the image pushed to [Docker Hub](https://hub.docker.com/r/particular/servicepulse).

If the release is a patch release to a previous major, then the `:latest` tag will not be added to the image pushed to Docker Hub.

The `:latest` tag is never added to images pushed to [the GitHub Container Registry](https://github.com/Particular/ServicePulse/pkgs/container/servicepulse).

#### Version tags

We use [SemVer](http://semver.org/) for versioning. Release images pushed to [Docker Hub](https://hub.docker.com/r/particular/servicepulse) will be tagged with the release version. Staged images pushed to [the GitHub Container Registry](https://github.com/Particular/ServicePulse/pkgs/container/servicepulse) will not have a version tag.

#### Pull request tag

Pre-release image versions generated from [GitHub pull requests](https://github.com/Particular/ServicePulse/pulls) will only be available in the GitHub Container Registry and are tagged using the pull request number using the following convention: `pr-1234`. The pull request tag is only added to images pushed to [the GitHub Container Registry](https://github.com/Particular/ServicePulse/pkgs/container/servicepulse) and are not added to images pushed to [Docker Hub](https://hub.docker.com/r/particular/servicepulse).

#### Major version tag

The latest release within a major version will be tagged with the major version number only on images pushed to [Docker Hub](https://hub.docker.com/r/particular/servicepulse). This allows users to target a specific major version to help avoid the risk of incurring breaking changes between major versions. Useful for auto-upgrading containers in a _production_, for instance:

If `particular/servicepulse:1.30.1` is the latest release in the version 1 major release, the image will also be tagged `particular/servicepulse:1`.

The major version tag is never added to images pushed to [the GitHub Container Registry](https://github.com/Particular/ServicePulse/pkgs/container/servicepulse).

## Built With

This image is built from the stable Alpine version of the [nginx official Docker image](https://hub.docker.com/_/nginx/).

## Contributing

Please read [our documentation](https://docs.particular.net/platform/contributing) for details on how to contribute to Particular Software projects.

## Authors

This software, including this container image, is built and maintained by the team at [Particular Software](https://particular.net). See also the list of [contributors](https://github.com/Particular/ServicePulse/graphs/contributors) who participated in this project.

## License

This project is licensed under the Reciprocal Public License 1.5 (RPL1.5) and commercial licenses are available - see the [LICENSE.md](https://github.com/Particular/ServicePulse/blob/master/LICENSE.md) file for details.
File renamed without changes.
6 changes: 6 additions & 0 deletions src/Container/updateconstants.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh

if [ ! -f /usr/share/nginx/html/js/app.constants.js ]
then
envsubst < /usr/share/nginx/html/js/app.constants.template > /usr/share/nginx/html/js/app.constants.js
fi
8 changes: 0 additions & 8 deletions src/builddockerimages.ps1

This file was deleted.

15 changes: 0 additions & 15 deletions src/dockerfile.iis

This file was deleted.

19 changes: 0 additions & 19 deletions src/dockerfile.nginx

This file was deleted.

17 changes: 0 additions & 17 deletions src/iis.config

This file was deleted.