diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f5c9cc6 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +.git +.github +node_modules +dist +coverage +*.log diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..fa6f35b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,34 @@ +ARG NODE_IMAGE=docker.io/library/node:24-bookworm-slim + +FROM ${NODE_IMAGE} AS build + +WORKDIR /opt/torlink + +COPY . . +RUN npm ci \ + && npm run build \ + && npm prune --omit=dev + +FROM ${NODE_IMAGE} AS runtime + +ENV NODE_ENV=production \ + HOME=/home/node \ + TORLINK_STATE_DIR=/state \ + TORLINK_NO_UPDATE_CHECK=1 + +WORKDIR /opt/torlink + +COPY --from=build --chown=node:node /opt/torlink/package.json ./package.json +COPY --from=build --chown=node:node /opt/torlink/dist ./dist +COPY --from=build --chown=node:node /opt/torlink/node_modules ./node_modules + +# Keep writable paths usable when the runtime assigns an arbitrary UID in GID 0. +RUN install -d -o 1000 -g 0 /state /home/node/Downloads/torlink \ + && chmod -R g=u /state /home/node/Downloads/torlink + +USER 1000 + +VOLUME ["/state", "/home/node/Downloads/torlink"] +EXPOSE 9160 9161 + +ENTRYPOINT ["node", "/opt/torlink/dist/cli.cjs"] diff --git a/README.md b/README.md index 7320c50..147a8bd 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,47 @@ torlink also runs without the TUI, for servers and seedboxes: Add `--daemon` to keep watch, serve, or files running after you log out; `torlnk --help` has the full list of modes and flags. +## Container with Docker + +Build the image: + +```sh +docker build -t torlink . +``` + +Run it with persistent state and downloads: + +```sh +mkdir -p "$HOME/.local/share/torlink" "$HOME/Downloads/torlink" +docker run --rm -it \ + -v "$HOME/.local/share/torlink:/state" \ + -v "$HOME/Downloads/torlink:/home/node/Downloads/torlink" \ + torlink +``` + +The multi-stage image uses Node 24 LTS and runs torlink as an unprivileged user. + +## Container with Podman + +Build the image: + +```sh +podman build -t torlink . +``` + +Run it with persistent state and downloads. `--userns=keep-id` makes files created in the bind mounts belong to your host user: + +```sh +mkdir -p "$HOME/.local/share/torlink" "$HOME/Downloads/torlink" +podman run --rm -it \ + --userns=keep-id \ + -v "$HOME/.local/share/torlink:/state:Z" \ + -v "$HOME/Downloads/torlink:/home/node/Downloads/torlink:Z" \ + torlink +``` + +The `:Z` suffix gives the bind mounts a private SELinux label. It can be omitted on systems without SELinux. + ## Contributing To run or work on torlink locally: