Initial commit: EDGE Ignition gateway docker-compose build

Custom Dockerfile-based build for an Ignition Edge gateway with
pre-baked base gwbk, module registration, and admin password
provisioning, backed by MariaDB.
This commit is contained in:
2026-07-22 10:31:20 -05:00
commit 1911a4960f
15 changed files with 764 additions and 0 deletions

124
CHANGES.md Normal file
View File

@@ -0,0 +1,124 @@
# EDGE docker-compose build/runtime fixes — 2026-07-22
## Starting problem
`docker compose -f EDGE/docker-compose.yml up -d --build` failed. The custom
`gw-build/Dockerfile` (patterned after
https://github.com/thirdgen88/ignition-examples/tree/main/iiot) referenced four
helper scripts that did not exist anywhere in `gw-build/` or on disk:
- `retrieve-modules.sh`
- `register-module.sh`
- `register-password.sh`
- `docker-entrypoint-shim.sh`
Build cache masked this initially — earlier `RUN` layers that *used* these
scripts showed `CACHED` from a prior successful build, while the `COPY` steps
that needed the actual files on disk failed with "not found".
## What was checked
- Searched the whole filesystem (`~/git`, home directory) for the four
filenames — not found anywhere, including in the sibling `BAT/` repo (which
uses the stock Ignition image directly, no custom Dockerfile).
- Checked for any previously-built `edge-ignition` image, container, or volume
that might have the files baked in — none existed; this build has never
succeeded on this machine.
- User confirmed the reference source: the `iiot` example in
`thirdgen88/ignition-examples`, which contains all four scripts plus a
matching `Dockerfile`.
## Changes made
### 1. Copied the four missing scripts from the reference repo
Fetched from `thirdgen88/ignition-examples` (`iiot/gw-build/`) into
`EDGE/gw-build/`, marked executable (0755):
- `retrieve-modules.sh`
- `register-module.sh`
- `register-password.sh`
- `docker-entrypoint-shim.sh` — this one already existed locally, identical to
upstream, so no change was needed there.
Note: a stray `register-modules.sh` (plural) was found already sitting in
`gw-build/` — an exact duplicate of `retrieve-modules.sh`'s content under the
wrong filename, unreferenced by the Dockerfile. Left in place, not deleted
(flagged to user).
### 2. Dropped `mqttdistributor`/`mqttengine` from the build (user decision)
The reference `Dockerfile` defines `ARG` pairs
(`SUPPLEMENTAL_MQTTENGINE_DOWNLOAD_URL`/`_SHA256`,
`SUPPLEMENTAL_MQTTDISTRIBUTOR_DOWNLOAD_URL`/`_SHA256`) that our local
Dockerfile was missing, even though `docker-compose.yml` requested
`SUPPLEMENTAL_MODULES: "mqttdistributor mqttengine"`. User said they don't
want those modules, so instead of adding the missing ARGs, the module list in
`docker-compose.yml` was changed to:
```yaml
SUPPLEMENTAL_MODULES: ""
```
### 3. Fixed `retrieve-modules.sh` invocation for the empty-module case
`retrieve-modules.sh`'s `main()` is written to silently no-op when
`SUPPLEMENTAL_MODULES` is empty, but its own `getopts` argument-validation
block rejects `-m ""` before `main()` ever runs (`exit 1` with a usage
message). This is a bug in the vendored script itself, inherited from the
reference repo — not something introduced here.
Rather than edit the vendored script (to keep it matching upstream), the
Dockerfile's `RUN` line was changed to skip calling the script at all when
there are no modules to fetch:
```dockerfile
# before
RUN ./retrieve-modules.sh \
-m "${SUPPLEMENTAL_MODULES:-}"
# after
RUN if [ -n "${SUPPLEMENTAL_MODULES:-}" ]; then ./retrieve-modules.sh -m "${SUPPLEMENTAL_MODULES}"; fi
```
### 4. Fixed `BASE_GWBK_NAME` mismatch
`docker-compose.yml` passed `BASE_GWBK_NAME: gateway.gwbk` as a build arg, but
the actual gateway backup file in `gw-build/` is named `base.gwbk` (matching
the Dockerfile's own default `ARG BASE_GWBK_NAME="base.gwbk"`). This mismatch
didn't hard-fail the build immediately — it caused `unzip` inside the
module/password-registration `RUN` step to silently fail-and-fallback
("cannot find or open gateway.gwbk" / "skipping password registration"),
masking the real problem until the final `COPY --from=prep .../${BASE_GWBK_NAME}`
step errored with "not found".
Fixed by correcting the compose arg to match the real filename:
```yaml
BASE_GWBK_NAME: base.gwbk
```
This also means admin password registration now actually runs during the
build (previously it was silently skipped due to the filename mismatch).
### 5. Fixed a runtime crash loop after the image built successfully
Once the image built, the `EDGE` container crash-looped with:
```
ERROR: Gateway Public HTTP/HTTPS/Address must be specified together:
- HTTPS Port not specified or is invalid
```
The compose `command:` for the `ignition` service set `-a
gateway.localtest.me` (public address) and `-h 8088` (HTTP port) but no `-s`
(HTTPS port). Ignition's entrypoint requires all three (address, HTTP port,
HTTPS port) to be set together or none at all — this is just gateway
public-address metadata used for URL generation, not a request to actually
expose HTTPS. Fixed by adding the conventional Ignition default HTTPS port:
```yaml
command: >
-n FW-DST-SEN
-m 512
-a gateway.localtest.me
-h 8088
-s 8043
```
No compose port mapping was added for 8043 — it isn't published, only used
for the internal public-address config.
## Result
`docker compose -f EDGE/docker-compose.yml up -d --build` now completes
successfully. Both `EDGE` (Ignition gateway) and `EDGE-db` (MariaDB)
containers reach `healthy` status. Gateway is reachable at
`http://gateway.localtest.me:8088` (or `http://localhost:8088`).
## Open item for follow-up
- Confirm whether the stray `gw-build/register-modules.sh` (plural, unused
duplicate) should be deleted.