ci(docker): add Docker publishing workflow and Dockerfile #157

Manually merged
jabber.developer merged 1 commits from ci/docker-hub-publishing into master 2026-07-11 21:38:11 +00:00

Introduce GitHub Actions workflow for automated Docker image publishing to Docker Hub.

Fixes #140

Introduce GitHub Actions workflow for automated Docker image publishing to Docker Hub. Fixes #140
jabber.developer added 1 commit 2026-07-05 15:43:45 +00:00
ci(docker): add Docker publishing workflow and Dockerfile
All checks were successful
CI Code / Check spelling (pull_request) Successful in 13s
CI Code / Check coding style (pull_request) Successful in 23s
Publish Docker image / Push Docker image to Docker Hub (push) Successful in 9m1s
CI Code / Linux (ubuntu) (pull_request) Successful in 8m53s
CI Code / Linux (debian) (pull_request) Successful in 9m13s
CI Code / Code Coverage (pull_request) Successful in 9m19s
CI Code / Linux (arch) (pull_request) Successful in 12m39s
9a69ede91b
Introduce GitHub Actions workflow for automated Docker image
publishing to Docker Hub, along with a dedicated Dockerfile in
the ci directory to streamline container builds.
jabber.developer force-pushed ci/docker-hub-publishing from 9a69ede91b to 2bad80b015 2026-07-05 15:54:55 +00:00 Compare
Collaborator

Runtime image may not be usable as-is

A local build of ci/Dockerfile completes fine, but the resulting image doesn't seem to start — ldd on the installed binary reports a couple of missing shared libraries:

$ docker run --rm --entrypoint ldd <image> /usr/local/bin/profanity | grep 'not found'
	libpython3.14.so.1.0 => not found
	libstrophe.so.0 => not found

$ docker run --rm <image> -v
profanity: error while loading shared libraries: libpython3.14.so.1.0: cannot open shared object file

Two things appear to be going on:

  • libstrophe is built from source in the builder stage (into /usr/lib/libstrophe.so.0.14.0), but it doesn't look like it's carried over into the runtime stage — the COPY --from=builder block only pulls the binary, libprofanity*, the header and share/. Since it's not an Ubuntu package, the runtime apt-get install can't cover it either.
  • libpython3.14 seems to be pulled in by --enable-python-plugins (the binary links -lpython3.14), but the runtime installs only python3, which may not bring the shared library along.

One possible fix:

# add to the runtime apt-get install:
    libpython3.14 \

# after the COPY block:
COPY --from=builder /usr/lib/libstrophe.so* /usr/lib/
RUN ldconfig

It might also be worth running ldd on the final binary as a build step, since other hand-pinned runtime packages could hide similar gaps. Worth noting that docker build exits 0 here regardless — nothing actually runs the image — so a green build alone may not confirm it works.

Workflow tag conditions might not behave as intended

docker/metadata-action doesn't appear to have an enable-if-ref attribute — the supported one seems to be enable (with helpers like {{is_default_branch}}). If that's right, enable-if-ref would be silently ignored and every tag would apply unconditionally, so a push to master could end up tagged latest, and a release could pick up dev / nightly-<sha>. Something along these lines might match the intent more closely:

type=raw,value=dev,enable={{is_default_branch}}
type=sha,prefix=nightly-,enable={{is_default_branch}}
type=ref,event=tag
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/') }}

Smaller things

  • actions/checkout@v7 — the rest of the repo pins @v4, and v7 may not exist as a tag, so this step could fail to resolve. Pinning to @v4 (or a SHA, to match the other actions here) might be safer.
  • permissions: packages: write looks like it's aimed at GHCR; since the push targets Docker Hub via DOCKER_USERNAME/DOCKER_PASSWORD, contents: read alone may be enough.
  • No build cache — every run rebuilds libstrophe + profanity from source. cache-from/cache-to: type=gha could cut that down considerably.
  • There's no .dockerignore, so COPY . . seems to drag the whole .git and any local build artifacts into the context.
  • Minor: the workflow file ends on a trailing-space line with no final newline.

Since docker-publish.yml only triggers on push-to-master / release, none of the above would show up on the PR checks — the first real exercise would be after merge, which is why it might be worth verifying manually first.

### Runtime image may not be usable as-is A local build of `ci/Dockerfile` completes fine, but the resulting image doesn't seem to start — `ldd` on the installed binary reports a couple of missing shared libraries: ``` $ docker run --rm --entrypoint ldd <image> /usr/local/bin/profanity | grep 'not found' libpython3.14.so.1.0 => not found libstrophe.so.0 => not found $ docker run --rm <image> -v profanity: error while loading shared libraries: libpython3.14.so.1.0: cannot open shared object file ``` Two things appear to be going on: - **libstrophe** is built from source in the builder stage (into `/usr/lib/libstrophe.so.0.14.0`), but it doesn't look like it's carried over into the runtime stage — the `COPY --from=builder` block only pulls the binary, `libprofanity*`, the header and `share/`. Since it's not an Ubuntu package, the runtime `apt-get install` can't cover it either. - **libpython3.14** seems to be pulled in by `--enable-python-plugins` (the binary links `-lpython3.14`), but the runtime installs only `python3`, which may not bring the shared library along. One possible fix: ```dockerfile # add to the runtime apt-get install: libpython3.14 \ # after the COPY block: COPY --from=builder /usr/lib/libstrophe.so* /usr/lib/ RUN ldconfig ``` It might also be worth running `ldd` on the final binary as a build step, since other hand-pinned runtime packages could hide similar gaps. Worth noting that `docker build` exits 0 here regardless — nothing actually runs the image — so a green build alone may not confirm it works. ### Workflow tag conditions might not behave as intended `docker/metadata-action` doesn't appear to have an `enable-if-ref` attribute — the supported one seems to be `enable` (with helpers like `{{is_default_branch}}`). If that's right, `enable-if-ref` would be silently ignored and every tag would apply unconditionally, so a push to `master` could end up tagged `latest`, and a release could pick up `dev` / `nightly-<sha>`. Something along these lines might match the intent more closely: ```yaml type=raw,value=dev,enable={{is_default_branch}} type=sha,prefix=nightly-,enable={{is_default_branch}} type=ref,event=tag type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/') }} ``` ### Smaller things - `actions/checkout@v7` — the rest of the repo pins `@v4`, and v7 may not exist as a tag, so this step could fail to resolve. Pinning to `@v4` (or a SHA, to match the other actions here) might be safer. - `permissions: packages: write` looks like it's aimed at GHCR; since the push targets Docker Hub via `DOCKER_USERNAME`/`DOCKER_PASSWORD`, `contents: read` alone may be enough. - No build cache — every run rebuilds libstrophe + profanity from source. `cache-from`/`cache-to: type=gha` could cut that down considerably. - There's no `.dockerignore`, so `COPY . .` seems to drag the whole `.git` and any local build artifacts into the context. - Minor: the workflow file ends on a trailing-space line with no final newline. Since `docker-publish.yml` only triggers on push-to-master / release, none of the above would show up on the PR checks — the first real exercise would be after merge, which is why it might be worth verifying manually first.
jabber.developer added 1 commit 2026-07-07 13:01:41 +00:00
Fix issues, add .dockerignore
Some checks failed
CI Code / Linux (ubuntu) (pull_request) Failing after 7s
CI Code / Check spelling (pull_request) Successful in 13s
CI Code / Check coding style (pull_request) Successful in 23s
Publish Docker image / Push Docker image to Docker Hub (push) Failing after 3m35s
CI Code / Linux (debian) (pull_request) Failing after 4m7s
CI Code / Linux (arch) (pull_request) Failing after 7m1s
CI Code / Code Coverage (pull_request) Failing after 7m12s
3dc5f4df16
jabber.developer force-pushed ci/docker-hub-publishing from 3dc5f4df16 to 41c9a9777c 2026-07-08 16:22:27 +00:00 Compare
jabber.developer force-pushed ci/docker-hub-publishing from 41c9a9777c to e282bf9f36 2026-07-11 17:31:09 +00:00 Compare
jabber.developer force-pushed ci/docker-hub-publishing from e282bf9f36 to 5906c009d8 2026-07-11 17:31:42 +00:00 Compare
jabber.developer added 1 commit 2026-07-11 17:34:53 +00:00
test-publish
Some checks failed
Publish Docker image / Push Docker image to Docker Hub (push) Failing after 18s
CI Code / Check spelling (pull_request) Successful in 22s
CI Code / Check coding style (pull_request) Successful in 30s
CI Code / Code Coverage (pull_request) Successful in 3m49s
CI Code / Linux (ubuntu) (pull_request) Successful in 5m7s
CI Code / Linux (arch) (pull_request) Has been cancelled
CI Code / Linux (debian) (pull_request) Has been cancelled
e302430c08
jabber.developer force-pushed ci/docker-hub-publishing from e302430c08 to b665f6060e 2026-07-11 17:43:25 +00:00 Compare
jabber.developer force-pushed ci/docker-hub-publishing from b665f6060e to 2be16df905 2026-07-11 21:12:20 +00:00 Compare
jabber.developer manually merged commit 2be16df905 into master 2026-07-11 21:38:11 +00:00
Sign in to join this conversation.
No description provided.