The .dockerignore has 'target' which excludes the target/
directory from the docker build context. The Dockerfile was
COPYing the binary from target/, so docker build failed with
'file not found in build context or excluded by .dockerignore'.
Fix: copy the binary to build-output/ (a non-excluded path)
before docker build, and update the Dockerfile to copy from
build-output/.
- Add 'Stage binary for Docker' step that does:
mkdir -p build-output
cp target/shot-crafter-calculator-1.0.0-runner build-output/
- Dockerfile COPY now reads build-output/shot-crafter-calculator-1.0.0-runner
- build-output/ is not in .dockerignore -> only the binary
(~117MB) ships in the build context, not the whole target/
tree (~200MB with classes, generated-sources, node binaries, etc.)
act (the runner the user is running) auto-mounts the docker
socket via volume `GITEA-ACTIONS-TASK-...-env Target:/var/run/act`.
Declaring volumes: in the workflow causes a duplicate mount
(once via the volumes block, once via act's auto-mount):
Binds:[/var/run/docker.sock:/var/run/docker.sock
/var/run/docker.sock:/var/run/docker.sock]
failed to create container:
'Error response from daemon: Duplicate mount point'
Drop the explicit volumes block. The socket is already there.
The docker CLI inside the container can talk to the host daemon
via the already-mounted socket.
The container doesn't have docker, so docker build/docker push
fails with 'docker: not found'. Fix:
- Add docker.io to the apt-get install step (inside the container)
- Mount the host's docker.sock into the container via volumes:
so the in-container docker CLI talks to the host's docker daemon
(same model as Docker-in-Docker but using the host socket).
The runner has the docker label, so the host socket is available.
Now the whole pipeline (build native binary, build container image,
push to registry) runs in a single job without any artifact
upload/download between jobs.
The runner (runner-lxc-quarkus, using act) fails to upload the
117MB native binary via actions/upload-artifact@v4 with exit code 1
after 3 minutes. Avoid the artifact transfer entirely by collapsing
build-native and docker-native into a single job: build native
binary, then build the Docker image directly from the working tree
in the same container.
The container has the binary at target/shot-crafter-calculator-1.0.0-runner
and the Dockerfile expects it at the same path, so the build
chain works without any artifact download/upload.
Push only happens on push to main (not on PRs).
The upload-artifact step failed with exit code 1 but no details.
The most likely cause is that the binary file does not exist
at the expected path `target/shot-crafter-calculator-1.0.0-runner`
because the native build may have failed silently.
Add a 'Verify native binary' step that runs `ls -la target/` and
`file target/shot-crafter-calculator-1.0.0-runner` so the next
log shows exactly what's in target/ and what type the runtime
sees the binary as. Also make the upload's 'if-no-files-found'
explicit so the failure mode is unambiguous.
Native-image was OOM-killed (exit 137) during inlining phase. The
runner has no implicit memory limit on container jobs, so native-image
probed all available memory and got killed by the host OOM killer.
Fix:
- Set container options: --memory=8g (hard cap for the build container)
- Pass -Dquarkus.native.native-image-xmx=4g to mvn (limits the
native-image JVM heap to 4g, leaves 4g headroom for the rest
of the toolchain: GraalVM, glibc, Maven, etc.)
GraalVM native-image requires a C compiler (gcc) and zlib dev
headers to compile native binaries. The maven:3.9.6-eclipse-temurin-21
image is JDK-only and lacks these build tools, causing the build
to fail with:
Error: Default native-compiler executable 'gcc' not found via PATH
Extend the install step with build-essential (gcc, g++, make)
and zlib1g-dev so the native-image pipeline has the required
toolchain.
Gitea Actions run actions as JavaScript via `node` inside the
job container. The maven:3.9.6-eclipse-temurin-21 image has no
node, so action post steps (e.g. Checkout cleanup) fail with
'exec: "node": executable file not found in $PATH'.
Extend the install step to add git AND node 22 via NodeSource
apt repo, so the runner can complete every action's pre/post step.
The runner lacks git even though it has Docker access. The
maven:3.9.6-eclipse-temurin-21 image is Ubuntu-based without
git installed, which broke actions/checkout.
- Remove build-jvm entirely (it was failing too, and the JMV
artifact is not needed for the native pipeline)
- Add 'Install git and basic tools' step inside build-native
(apt-get update + apt-get install -y git ca-certificates)
- docker-native job unchanged: still depends on build-native,
builds the image with the pre-built native binary
Runner has no Maven or JDK installed. Instead of installing
both manually each job, run the jobs inside the official
maven:3.9.6-eclipse-temurin-21 image which has both pre-installed.
- Drop actions/setup-java (image has JDK 21)
- Drop 'Install Maven' step (image has Maven 3.9.6)
- Add 'container: image: maven:3.9.6-eclipse-temurin-21' to each job
- Add cache for ~/.m2/repository (key on pom.xml hash)
- Keep graalvm/setup-graalvm only for the native job (adds GraalVM
inside the container)
- docker-native job unchanged: uses the runner's docker daemon
directly to build the image with the pre-built native binary
The runner has Java (via setup-java) but no Maven. Add an
Install Maven step to build-jvm and build-native that downloads
Maven 3.9.6 from Apache to runner.workspace/.maven and adds it
to the PATH via $GITHUB_PATH. Idempotent: the if-guard skips
redownload if the binary already exists on the runner.
The Quarkus image (docker.io/quarkusio/quarkus-images:tooling-21)
cannot be pulled by the runner (access denied). Replace the
container: block with the standard actions/setup-java (Temurin 21)
and graalvm/setup-graalvm (with native-image component) actions
so the jobs run on the host directly.
Adds:
- Dockerfile based on quarkus-micro-image:2.0 (~50MB base)
Runs the native binary as non-root user 1001, exposes 8080
- .dockerignore to exclude build artifacts
- Gitea Actions workflow with 3 parallel jobs:
- build-jvm: standard JAR (mvn package)
- build-native: GraalVM native binary (mvn package -Pnative)
- docker-native: takes the native binary artifact, builds
the container image and pushes to
gitea.danielarroyo.cl/proyectos/shot-crafter-calculator
with tags 'latest' and short SHA
Triggers: push to main and PRs (docker job only on push).
Required secrets: GITEA_USERNAME, GITEA_TOKEN (write:packages).