diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..0af5e72 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,75 @@ +variables: + GIT_SUBMODULE_STRATEGY: none + CI_DISPOSABLE_ENVIRONMENT: "true" + DOCKER_HOST: tcp://docker:2375 + DOCKER_TLS_CERTDIR: "" + DOCKER_BUILDKIT: 1 + +default: + image: docker:27 + services: + - name: docker:27-dind + command: ["dockerd", "--host=tcp://0.0.0.0:2375"] + alias: "docker" + before_script: + - echo "$DOCKERHUB_PW" | docker login -u $DOCKERHUB_USER --password-stdin + - docker info + - | + docker buildx create \ + --driver=docker-container \ + --name=buildkit-builder \ + --use \ + --platform linux/amd64,linux/arm64 + tags: + - cloud + retry: + max: 2 + when: + - runner_system_failure + - unknown_failure + - stuck_or_timeout_failure + +stages: + - build + +.build:docker:plugin: + stage: build + script: + - | + VERSION="${CI_COMMIT_TAG#*/}" + IMAGE="blockstream/cln-plugins-${PLUGIN_NAME}" + + echo "Plugin: ${PLUGIN_NAME}" + echo "Version: ${VERSION}" + echo "Image: ${IMAGE}:${VERSION}" + + docker buildx build \ + --platform linux/amd64,linux/arm64 \ + --push \ + --build-arg PLUGIN_NAME="${PLUGIN_NAME}" \ + -t "${IMAGE}:${VERSION}" \ + . + +build:docker:event-plugin: + extends: .build:docker:plugin + variables: + PLUGIN_NAME: event-plugin + rules: + - if: '$CI_COMMIT_TAG =~ /^event-plugin\/v[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?$/' + - when: never + +build:docker:metrics-plugin: + extends: .build:docker:plugin + variables: + PLUGIN_NAME: metrics-plugin + rules: + - if: '$CI_COMMIT_TAG =~ /^metrics-plugin\/v[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?$/' + - when: never + +build:docker:rpc-log-plugin: + extends: .build:docker:plugin + variables: + PLUGIN_NAME: rpc-log-plugin + rules: + - if: '$CI_COMMIT_TAG =~ /^rpc-log-plugin\/v[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?$/' + - when: never diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..9ca6485 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,41 @@ +ARG RUST_VERSION=1.92 +ARG PLUGIN_NAME + +FROM rust:${RUST_VERSION}-bookworm AS builder + +ARG PLUGIN_NAME + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + clang \ + libsqlite3-dev \ + libssl-dev \ + pkg-config \ + sqlite3 \ + protobuf-compiler \ + libprotobuf-dev \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /src + +COPY . . + +RUN cargo build \ + --release \ + --locked \ + -p "${PLUGIN_NAME}" \ + --bin "${PLUGIN_NAME}" + +FROM debian:bookworm-slim AS installer + +ARG PLUGIN_NAME +ENV PLUGIN_NAME=${PLUGIN_NAME} + +COPY --from=builder /src/target/release/${PLUGIN_NAME} /opt/${PLUGIN_NAME} + +ENV TARGET_UID=0 \ + TARGET_GID=0 \ + TARGET_MODE=0755 \ + TARGET_PATH=/plugins/${PLUGIN_NAME} + +CMD ["sh", "-c", "install -o \"$TARGET_UID\" -g \"$TARGET_GID\" -m \"$TARGET_MODE\" \"/opt/$PLUGIN_NAME\" \"$TARGET_PATH\""] \ No newline at end of file diff --git a/README.md b/README.md index 1f43ccd..3f0b7aa 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,88 @@ You can also build only the plugin you need: cargo build --release --package metrics-plugin ``` +## Docker installer images +The image does not run the plugin itself. Instead, it copies the compiled plugin binary into a directory mounted from the host or another container. This is useful when Core Lightning and its plugins are deployed with Docker or Docker Compose and the plugin binary needs to be installed into a shared volume. + +Images are published using the following naming convention: + +``` +blockstream/cln-plugins-: +``` + +For example: +``` +blockstream/cln-plugins-rpc-log-plugin:v1.2.3 +blockstream/cln-plugins-event-plugin:v1.2.3 +blockstream/cln-plugins-metrics-plugin:v1.2.3 +``` + +### Install a plugin + +Mount the directory where the plugin should be installed as `/plugins`: +```bash +docker run --rm \ + -v /path/to/plugins:/plugins \ + blockstream/cln-plugins-rpc-log-plugin:v1.2.3 +``` + +By default, the plugin is installed as: +``` +0:0 755 /plugins/rpc-log-plugin +``` + +### Installer configuration + +The installer can be configured through environment variables: + +| Variable | Default | Description | +|---|---|---| +| TARGET_UID | 0 | UID assigned to the installed binary | +| TARGET_GID | 0 | GID assigned to the installed binary | +| TARGET_MODE | 0755 | File permissions assigned to the installed binary | +| TARGET_PATH | `/plugins/` | Destination path of the installed binary | + +For example: +```bash +docker run --rm \ + -v /path/to/plugins:/plugins \ + -e TARGET_UID=1000 \ + -e TARGET_GID=1000 \ + -e TARGET_MODE=0750 \ + blockstream/cln-plugins-rpc-log-plugin:v1.2.3 +``` + +To install the binary under a custom path: +```bash +docker run --rm \ + -v /path/to/plugins:/plugins \ + -e TARGET_PATH=/plugins/custom-rpc-log-plugin \ + blockstream/cln-plugins-rpc-log-plugin:v1.2.3 +``` +The installer container must have permission to change the ownership and mode of files in the mounted destination. In particular, setting arbitrary `TARGET_UID` or `TARGET_GID` generally requires running the installer as root. + +### Docker Compose + +Installer images can also be used as one-shot services in Docker Compose with a shared volume: + +```yaml +services: + rpc-log-plugin-installer: + image: blockstream/cln-plugins-rpc-log-plugin:v1.2.3 + volumes: + - plugins:/plugins + + lightning: + # Your Core Lightning image + volumes: + - plugins:/plugins + +volumes: + plugins: +``` + +This allows the installer container to place the plugin binary into the shared volume before Core Lightning uses it. + ## Development Run the standard checks from the repository root: