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
68 changes: 50 additions & 18 deletions .github/workflows/dockit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,20 @@ jobs:

outputs:
timestamp: ${{ steps.timestamp.outputs.timestamp }}
preset: ${{ steps.timestamp.outputs.preset }}
jobs: ${{ steps.timestamp.outputs.jobs }}

steps:
- name: Collect timestamp
id: timestamp
run: |
echo "timestamp=$(date +'%Y%m%dT%H%M%S')" >> $GITHUB_OUTPUT
echo "preset=linux.gcc.serveronly.relwithdebinfo" >> $GITHUB_OUTPUT
echo "jobs=4" >> $GITHUB_OUTPUT

# Create the ecflow package
#
# Create the ecflow package, per image variant
#
package:
name: package
name: package (${{ matrix.image }})
needs: bootstrap
if: ${{ !github.event.pull_request.head.repo.fork && github.event.action != 'labeled' || github.event.label.name == 'approved-for-docker' }}

Expand All @@ -38,6 +38,21 @@ jobs:

timeout-minutes: 60

strategy:
fail-fast: false
max-parallel: 1
matrix:
preset:
- linux.gcc.serveronly.relwithdebinfo
- linux.gcc.all.relwithdebinfo
include:
- preset: linux.gcc.serveronly.relwithdebinfo
image: ecflow-serveronly-dev
context: ecflow-server
- preset: linux.gcc.all.relwithdebinfo
image: ecflow-all-dev
context: ecflow-all

outputs:
version: ${{ steps.vars.outputs.version }}

Expand Down Expand Up @@ -88,48 +103,65 @@ jobs:
id: configure-ecflow
run: |
cd ${GITHUB_WORKSPACE}/ecflow
cmake --preset ${{ needs.bootstrap.outputs.preset }} \
cmake --preset ${{ matrix.preset }} \
-DCUSTOM_DEBIAN_PACKAGE_VERSION=${{ steps.vars.outputs.version }}

- name: Build ecflow
run: |
cd ${GITHUB_WORKSPACE}/ecflow
cmake --build \
--preset ${{ needs.bootstrap.outputs.preset }} \
--preset ${{ matrix.preset }} \
--jobs ${{ needs.bootstrap.outputs.jobs }} \
--target all

- name: Package ecflow
run: |
cd ${GITHUB_WORKSPACE}/ecflow
cmake --build \
--preset ${{ needs.bootstrap.outputs.preset }} \
--preset ${{ matrix.preset }} \
--target package

- name: Upload ecflow debian package
uses: actions/upload-artifact@v7
with:
name: ecflow-debian-package
path: ecflow/.deploy/build/${{ needs.bootstrap.outputs.preset }}/ecflow-*.deb
name: ecflow-debian-package-${{ matrix.image }}
path: ecflow/.deploy/build/${{ matrix.preset }}/ecflow-*.deb
if-no-files-found: error

# - name: Test ecflow
# run: |
# cd ${{ github.workspace }}/ecflow
# ctest --preset ${{ needs.bootstrap.outputs.preset }} \
# ctest --preset ${{ matrix.preset }} \
# --jobs ${{ needs.bootstrap.outputs.jobs }} \
# --output-on-failure \
# -L nightly

# Create ecflow docker image
#
# Create the ecflow docker image
#
dockerize:
name: dockerize
name: dockerize (${{ matrix.image }})
needs: [ bootstrap, package ]

runs-on: ubuntu-latest

timeout-minutes: 60

strategy:
fail-fast: false
max-parallel: 1
matrix:
preset:
- linux.gcc.serveronly.relwithdebinfo
- linux.gcc.all.relwithdebinfo
include:
- preset: linux.gcc.serveronly.relwithdebinfo
image: ecflow-serveronly-dev
context: ecflow-server
- preset: linux.gcc.all.relwithdebinfo
image: ecflow-all-dev
context: ecflow-all

steps:
- name: Checkout 'ecflow'
uses: actions/checkout@v4
Expand All @@ -139,8 +171,8 @@ jobs:
- name: Download ecflow debian package
uses: actions/download-artifact@v7
with:
name: ecflow-debian-package
path: ecflow/releng/dockit/ecflow-server
name: ecflow-debian-package-${{ matrix.image }}
path: ecflow/releng/dockit/${{ matrix.context }}

- name: Log in to Harbor
uses: docker/login-action@v3
Expand All @@ -158,16 +190,16 @@ jobs:
- name: Build and push Docker image
uses: docker/build-push-action@v7
with:
file: ecflow/releng/dockit/ecflow-server/Dockerfile
context: ecflow/releng/dockit/ecflow-server
file: ecflow/releng/dockit/${{ matrix.context }}/Dockerfile
context: ecflow/releng/dockit/${{ matrix.context }}
build-args: |
ECFLOW_VERSION=${{ needs.package.outputs.version }}
ECFLOW_PACKAGE=ecflow-${{ needs.package.outputs.version }}-Linux_x86_64.deb
platforms: linux/amd64
push: true
tags: |
eccr.ecmwf.int/ecflow-dev-environments/ecflow-serveronly-dev:latest
eccr.ecmwf.int/ecflow-dev-environments/ecflow-serveronly-dev:${{ needs.package.outputs.version }}_${{ needs.bootstrap.outputs.timestamp }}
eccr.ecmwf.int/ecflow-dev-environments/${{ matrix.image }}:latest
eccr.ecmwf.int/ecflow-dev-environments/${{ matrix.image }}:${{ needs.package.outputs.version }}_${{ needs.bootstrap.outputs.timestamp }}
labels: |
org.opencontainers.image.source=${{ github.repositoryUrl }}
org.opencontainers.image.revision=${{ github.sha }}
Expand Down
2 changes: 1 addition & 1 deletion releng/dockit/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
ecflow-*.deb
ecflow-*/*.deb
*.sandbox
94 changes: 84 additions & 10 deletions releng/dockit/INSTRUCTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,17 @@ stated.

## Relationship to the `dockit` GitHub Actions workflow

The action `.github/workflows/dockit.yml` automates the `ecflow-server` image build process described below,
end-to-end, on `workflow_dispatch`:
The action `.github/workflows/dockit.yml` automates both image build processes described below, end-to-end,
on `workflow_dispatch`, as two jobs, each running once per image variant via a build matrix (preset is the
matrix dimension: each leg pairs a preset with the image name and Dockerfile directory it belongs to):

1. The `package` job builds the ecFlow Debian package inside `marcosbento/lumen:debian-13.5`, following the same
checkout/configure/build/package steps as `ecflow-server.build.package.sh`, and uploads the resulting `.deb`
as a build artefact.
1. The `package` job builds the ecFlow Debian package inside `marcosbento/lumen:debian-13.5`, following the
same checkout/configure/build/package steps as `ecflow-server.build.package.sh`, and uploads the resulting
`.deb` as an `ecflow-debian-package-<image>` artefact.

2. The `dockerize` job downloads that artifact into `ecflow-server/` and builds the Docker image from
`ecflow-server/Dockerfile`, passing the same `ECFLOW_VERSION` and `ECFLOW_PACKAGE` build arguments described in the
`ecflow-server` section below, then pushes it to `eccr.ecmwf.int/ecflow-dev-environments/ecflow-serveronly-dev`.
2. The `dockerize` job, using the same matrix, downloads the matching artefact into the matching
`ecflow-server/` or `ecflow-all/` directory and builds the Docker image from that directory's
`Dockerfile`, then pushes it to `eccr.ecmwf.int/ecflow-dev-environments/<image>`.

## Building the images

Expand Down Expand Up @@ -70,13 +71,13 @@ Build the image, passing the package version and filename as build arguments:

```bash
docker build \
--build-arg ECFLOW_VERSION=<version>_<sha> \
--build-arg ECFLOW_PACKAGE=ecflow-<version>_<sha>-Linux_x86_64.deb \
-t ecflow-serveronly-dev:latest \
ecflow-server/
```

Note: provide `.deb` filename explicitly to match the file produced in Step 1. To avoid defining version and package,
Note: provide the `.deb` filename explicitly to match the file produced in Step 1. To avoid defining version and
package,
rename the package to the default name `ecflow-latest-Linux.deb`.

The ecflow ports are configurable via the `ECFLOW_SERVER_PORT` (default `8888`) and `ECFLOW_REST_PORT` (default `8889`)
Expand All @@ -87,3 +88,76 @@ Run the image with, for example:
```bash
docker run --rm -p 8888:8888 -p 8889:8889 ecflow-serveronly-dev:latest
```

### Building the `ecflow-all` image

This section describes the process to build a Docker image capable of running `ecflow_ui`, connected to a remote ecFlow
server (for example on ECMWF's HPC) through a `proxychains4` + SSH SOCKS tunnel opened on the Docker host. Although it
has `ecflow-server`, this image is designed to run `ecflow_ui` only, and does not start a server itself.

#### Step 1 (repeated): Build the ecFlow Debian package

Follow Step 1 above to produce a `.deb`. In this case, because the package must include the ecflow UI, use preset
`linux.gcc.all.relwithdebinfo` for the configuration, for example:

```bash
./ecflow-server.build.package.sh --preset linux.gcc.all.relwithdebinfo --output_dir ecflow-all
```

Ensure this the `.deb` is made available in `ecflow-all/` to support building the Docker image in Step 3.
The `--output_dir` option above copies the package into that directory automatically.

#### Step 3: Build the `ecflow-all` container image

```bash
docker build \
--build-arg ECFLOW_PACKAGE=ecflow-<version>_<sha>-Linux_x86_64.deb \
-t ecflow-all-dev:latest \
ecflow-all/
```

Note: provide the `.deb` filename explicitly to match the file produced in Step 1, or rename the
package to the default name `ecflow-latest-Linux.deb` to avoid defining version and package.

#### Running `ecflow_ui`

The `ecflow_ui` can easily be launched using the `docker_ecflow_ui.sh` script.

This utility script handles all the nitty-gritty details of using Docker to run `ecflow_ui`:

- it forwards X11 to the host,
- mounts and passes `-confd` for the ecflow_ui configuration directory
- applies `xhost +`.

It is self-contained, so it can be run either as a local checkout or fetched and piped straight into `bash`:

```bash
./docker_ecflow_ui.sh
# or
curl -fsSL <url>/docker_ecflow_ui.sh | bash -s -- --proxychains=on
```

Options (`./docker_ecflow_ui.sh --help` for the full list):

| Option | Default | Purpose |
|-------------------------|-----------------------------------------------------------------------------|------------------------------------------------------------------------------------------|
| `-c`, `--cfg DIR` | `~/.ecflow_ui_v5` | ecflow_ui configuration directory (bind-mounted, passed via `-confd`) |
| `-i`, `--image IMAGE` | `ecflow-all-dev:latest` | Docker image to run |
| `--proxychains=on\|off` | `off` | Route connections through proxychains4 + the SSH SOCKS tunnel |
| `--authtokens FILE` | unset (falls back to `ECF_AUTHTOKENS` from the calling environment, if set) | Auth tokens file, bind-mounted read-only and exposed to `ecflow_ui` via `ECF_AUTHTOKENS` |

By default (`--proxychains=off`) the script bypasses the image's own `ENTRYPOINT`(`launch-ecflow_ui.sh`) and runs
`ecflow_ui` directly — appropriate when the target ecFlow server is already reachable without a tunnel.

With `--proxychains=on`, the image's `ENTRYPOINT` resolves the SOCKS proxy host (`host.docker.internal` by default) to
a literal IP address at container start, generates `/etc/proxychains4.conf` from it, and execs `ecflow_ui` under
`proxychains4`. Two things are required on the host side in that case:

1. An SSH SOCKS tunnel to the HPC environment, bound to more than loopback so the container can reach it
through `host.docker.internal`:

```bash
ssh -g -D 9050 user@hpc-gateway
```

2. On macOS, an X server (e.g. XQuartz) running (`docker_ecflow_ui.sh` applies `xhost +` itself).
Loading
Loading