This commit is contained in:
6
.dockerignore
Normal file
6
.dockerignore
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
.git
|
||||||
|
.upstream-open-stage-control
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
data
|
||||||
|
config
|
||||||
114
.gitea/workflows/docker-publish.yml
Normal file
114
.gitea/workflows/docker-publish.yml
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
name: Build & Push Docker
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ["main"]
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: "@weekly"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Resolve latest Open Stage Control release
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
python3 <<'PY'
|
||||||
|
import json
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
url = "https://framagit.org/api/v4/projects/jean-emmanuel%2Fopen-stage-control/releases"
|
||||||
|
with urllib.request.urlopen(url) as response:
|
||||||
|
releases = json.load(response)
|
||||||
|
|
||||||
|
if not releases:
|
||||||
|
raise SystemExit("No releases returned by upstream API")
|
||||||
|
|
||||||
|
latest = releases[0]
|
||||||
|
tag = latest["tag_name"]
|
||||||
|
version = tag[1:] if tag.startswith("v") else tag
|
||||||
|
|
||||||
|
with open("release.env", "w", encoding="utf-8") as f:
|
||||||
|
f.write(f"OSC_TAG={tag}\n")
|
||||||
|
f.write(f"OSC_VERSION={version}\n")
|
||||||
|
PY
|
||||||
|
|
||||||
|
cat release.env >> "$GITHUB_ENV"
|
||||||
|
|
||||||
|
- name: Set image names
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
REPOSITORY: ${{ gitea.repository }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
OWNER="${REPOSITORY%/*}"
|
||||||
|
REPO="${REPOSITORY#*/}"
|
||||||
|
echo "IMAGE_LATEST=git.f-40.com/${OWNER}/${REPO}:latest" >> "$GITHUB_ENV"
|
||||||
|
echo "IMAGE_VERSIONED=git.f-40.com/${OWNER}/${REPO}:${OSC_VERSION}" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
|
- name: Login to Gitea Container Registry
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
REGISTRY_USER: ${{ secrets.USER }}
|
||||||
|
REGISTRY_TOKEN: ${{ secrets.TOKEN }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
echo "$REGISTRY_TOKEN" | docker login git.f-40.com -u "$REGISTRY_USER" --password-stdin
|
||||||
|
|
||||||
|
- name: Decide whether a build is needed
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
EVENT_NAME: ${{ gitea.event_name }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [ "$EVENT_NAME" = "push" ] || [ "$EVENT_NAME" = "workflow_dispatch" ]; then
|
||||||
|
echo "SHOULD_BUILD=true" >> "$GITHUB_ENV"
|
||||||
|
echo "BUILD_REASON=repository change or manual run" >> "$GITHUB_ENV"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if docker manifest inspect "$IMAGE_VERSIONED" >/dev/null 2>&1; then
|
||||||
|
echo "SHOULD_BUILD=false" >> "$GITHUB_ENV"
|
||||||
|
echo "BUILD_REASON=version ${OSC_VERSION} already exists in registry" >> "$GITHUB_ENV"
|
||||||
|
else
|
||||||
|
echo "SHOULD_BUILD=true" >> "$GITHUB_ENV"
|
||||||
|
echo "BUILD_REASON=new upstream release ${OSC_TAG}" >> "$GITHUB_ENV"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [ "${SHOULD_BUILD}" != "true" ]; then
|
||||||
|
echo "Skipping build: ${BUILD_REASON}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Building ${OSC_TAG} because ${BUILD_REASON}"
|
||||||
|
docker build \
|
||||||
|
--build-arg OPEN_STAGE_CONTROL_VERSION="${OSC_VERSION}" \
|
||||||
|
-t "${IMAGE_LATEST}" \
|
||||||
|
-t "${IMAGE_VERSIONED}" \
|
||||||
|
.
|
||||||
|
|
||||||
|
- name: Push
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [ "${SHOULD_BUILD}" != "true" ]; then
|
||||||
|
echo "Skipping push: ${BUILD_REASON}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker push "${IMAGE_VERSIONED}"
|
||||||
|
docker push "${IMAGE_LATEST}"
|
||||||
20
.gitignore
vendored
Normal file
20
.gitignore
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# OS / editor
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# Temp / logs
|
||||||
|
*.log
|
||||||
|
*.tmp
|
||||||
|
|
||||||
|
# Docker app data
|
||||||
|
config/
|
||||||
|
data/
|
||||||
|
|
||||||
|
# Local upstream inspection clones
|
||||||
|
.upstream-open-stage-control/
|
||||||
|
|
||||||
|
# Node / build artifacts
|
||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
42
Dockerfile
Normal file
42
Dockerfile
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
FROM debian:bookworm-slim AS downloader
|
||||||
|
|
||||||
|
ARG OPEN_STAGE_CONTROL_VERSION=1.30.3
|
||||||
|
ARG OPEN_STAGE_CONTROL_BASE_URL=https://openstagecontrol.ammd.net/packages
|
||||||
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends ca-certificates curl unzip \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /tmp
|
||||||
|
|
||||||
|
RUN curl -fsSLo open-stage-control.zip \
|
||||||
|
"${OPEN_STAGE_CONTROL_BASE_URL}/open-stage-control_${OPEN_STAGE_CONTROL_VERSION}_node.zip" \
|
||||||
|
&& unzip -q open-stage-control.zip -d extracted \
|
||||||
|
&& mv extracted/open-stage-control_${OPEN_STAGE_CONTROL_VERSION}_node /open-stage-control
|
||||||
|
|
||||||
|
FROM node:20-bookworm-slim
|
||||||
|
|
||||||
|
LABEL org.opencontainers.image.title="Open Stage Control"
|
||||||
|
LABEL org.opencontainers.image.description="Container image for the Open Stage Control node-only release"
|
||||||
|
LABEL org.opencontainers.image.source="https://framagit.org/jean-emmanuel/open-stage-control"
|
||||||
|
|
||||||
|
ENV OSC_PORT=8080
|
||||||
|
ENV OSC_OSC_PORT=8080
|
||||||
|
ENV OSC_CACHE_DIR=/config
|
||||||
|
ENV OSC_REMOTE_ROOT=/data
|
||||||
|
|
||||||
|
WORKDIR /opt
|
||||||
|
|
||||||
|
COPY --from=downloader /open-stage-control /opt/open-stage-control
|
||||||
|
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
|
||||||
|
|
||||||
|
RUN chmod +x /usr/local/bin/docker-entrypoint.sh \
|
||||||
|
&& mkdir -p /config /data
|
||||||
|
|
||||||
|
VOLUME ["/config", "/data"]
|
||||||
|
|
||||||
|
EXPOSE 8080/tcp
|
||||||
|
EXPOSE 8080/udp
|
||||||
|
|
||||||
|
ENTRYPOINT ["docker-entrypoint.sh"]
|
||||||
|
CMD []
|
||||||
87
README.md
87
README.md
@@ -1,3 +1,88 @@
|
|||||||
# OSC-Docker
|
# OSC-Docker
|
||||||
|
|
||||||
A docker image for Open Stage Control
|
Docker image for the Open Stage Control node-only release.
|
||||||
|
|
||||||
|
This image uses the upstream release artifact instead of building Electron from source. I verified on May 10, 2026 that Framagit's current release is `v1.30.3`, and that it publishes a `Node.js` package at:
|
||||||
|
|
||||||
|
`https://openstagecontrol.ammd.net/packages/open-stage-control_1.30.3_node.zip`
|
||||||
|
|
||||||
|
Source project:
|
||||||
|
|
||||||
|
`https://framagit.org/jean-emmanuel/open-stage-control`
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -t open-stage-control .
|
||||||
|
```
|
||||||
|
|
||||||
|
To target a different upstream release:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build \
|
||||||
|
--build-arg OPEN_STAGE_CONTROL_VERSION=1.30.3 \
|
||||||
|
-t open-stage-control .
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run --rm \
|
||||||
|
-p 8080:8080/tcp \
|
||||||
|
-p 8080:8080/udp \
|
||||||
|
-v "${PWD}/config:/config" \
|
||||||
|
-v "${PWD}/data:/data" \
|
||||||
|
open-stage-control
|
||||||
|
```
|
||||||
|
|
||||||
|
Then open:
|
||||||
|
|
||||||
|
`http://localhost:8080`
|
||||||
|
|
||||||
|
## Docker Compose
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up --build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Gitea Actions
|
||||||
|
|
||||||
|
The repo includes a Gitea Actions workflow at `.gitea/workflows/docker-publish.yml`.
|
||||||
|
|
||||||
|
It will:
|
||||||
|
|
||||||
|
- build on pushes to `main`
|
||||||
|
- allow manual runs with `workflow_dispatch`
|
||||||
|
- poll the upstream Open Stage Control releases API once a week
|
||||||
|
- build and push a new image only when a new upstream release tag is found
|
||||||
|
|
||||||
|
Required repository secrets:
|
||||||
|
|
||||||
|
- `USER`: registry username
|
||||||
|
- `TOKEN`: registry token or PAT for `git.f-40.com`
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
- `OSC_PORT`: HTTP port. Default `8080`.
|
||||||
|
- `OSC_OSC_PORT`: OSC UDP input port. Default `8080`.
|
||||||
|
- `OSC_TCP_PORT`: Optional OSC TCP input port.
|
||||||
|
- `OSC_CACHE_DIR`: Config/cache path inside the container. Default `/config`.
|
||||||
|
- `OSC_REMOTE_ROOT`: File browser root inside the container. Default `/data`.
|
||||||
|
- `OSC_LOAD`: Optional session file to auto-load.
|
||||||
|
- `OSC_STATE`: Optional state file to auto-load.
|
||||||
|
- `OSC_CUSTOM_MODULE`: Optional custom module path.
|
||||||
|
- `OSC_THEME`: Optional theme path or theme name.
|
||||||
|
- `OSC_AUTHENTICATION`: Optional `user:password`.
|
||||||
|
- `OSC_CLIENT_OPTIONS`: Optional single `key=value` client option. For multiple client options, pass extra CLI args after the image name.
|
||||||
|
- `OSC_READ_ONLY`: Set to `true` to disable editing/saving.
|
||||||
|
- `OSC_USE_SSL`: Set to `true` to enable HTTPS.
|
||||||
|
- `OSC_DEBUG`: Set to `true` to log OSC traffic.
|
||||||
|
- `OSC_NO_QRCODE`: Set to `true` to suppress QR output.
|
||||||
|
|
||||||
|
## Extra CLI Arguments
|
||||||
|
|
||||||
|
You can still pass native Open Stage Control arguments after the image name:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run --rm -p 8080:8080/tcp -p 8080:8080/udp open-stage-control --send 192.168.1.50:9000
|
||||||
|
```
|
||||||
|
|||||||
17
compose.yaml
Normal file
17
compose.yaml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
services:
|
||||||
|
open-stage-control:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
args:
|
||||||
|
OPEN_STAGE_CONTROL_VERSION: 1.30.3
|
||||||
|
ports:
|
||||||
|
- "8080:8080/tcp"
|
||||||
|
- "8080:8080/udp"
|
||||||
|
environment:
|
||||||
|
OSC_PORT: 8080
|
||||||
|
OSC_OSC_PORT: 8080
|
||||||
|
OSC_REMOTE_ROOT: /data
|
||||||
|
OSC_CACHE_DIR: /config
|
||||||
|
volumes:
|
||||||
|
- ./config:/config
|
||||||
|
- ./data:/data
|
||||||
56
docker-entrypoint.sh
Normal file
56
docker-entrypoint.sh
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
node /opt/open-stage-control \
|
||||||
|
--no-gui \
|
||||||
|
--cache-dir "${OSC_CACHE_DIR:-/config}" \
|
||||||
|
--remote-root "${OSC_REMOTE_ROOT:-/data}" \
|
||||||
|
--port "${OSC_PORT:-8080}" \
|
||||||
|
--osc-port "${OSC_OSC_PORT:-${OSC_PORT:-8080}}"
|
||||||
|
|
||||||
|
if [ -n "${OSC_TCP_PORT:-}" ]; then
|
||||||
|
set -- "$@" --tcp-port "${OSC_TCP_PORT}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "${OSC_LOAD:-}" ]; then
|
||||||
|
set -- "$@" --load "${OSC_LOAD}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "${OSC_STATE:-}" ]; then
|
||||||
|
set -- "$@" --state "${OSC_STATE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "${OSC_CUSTOM_MODULE:-}" ]; then
|
||||||
|
set -- "$@" --custom-module "${OSC_CUSTOM_MODULE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "${OSC_THEME:-}" ]; then
|
||||||
|
set -- "$@" --theme "${OSC_THEME}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "${OSC_CLIENT_OPTIONS:-}" ]; then
|
||||||
|
set -- "$@" --client-options "${OSC_CLIENT_OPTIONS}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "${OSC_AUTHENTICATION:-}" ]; then
|
||||||
|
set -- "$@" --authentication "${OSC_AUTHENTICATION}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${OSC_READ_ONLY:-false}" = "true" ]; then
|
||||||
|
set -- "$@" --read-only
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${OSC_USE_SSL:-false}" = "true" ]; then
|
||||||
|
set -- "$@" --use-ssl
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${OSC_DEBUG:-false}" = "true" ]; then
|
||||||
|
set -- "$@" --debug
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${OSC_NO_QRCODE:-false}" = "true" ]; then
|
||||||
|
set -- "$@" --no-qrcode
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$@"
|
||||||
Reference in New Issue
Block a user