1
Fork 0
mirror of https://github.com/thegeneralist01/archivr synced 2026-07-21 18:55:36 +02:00

fix: address second round of Docker review issues

Chromium sandbox (P2):
- singlefile.rs: add ARCHIVR_CHROME_ARGS env var (space-separated flags
  appended to Chromium's --browser-args JSON array); Dockerfile sets it
  to --no-sandbox because Chromium refuses to start as root without it

Store-path outside volume (P1):
- README: pass explicit absolute store-path as the second positional arg
  to `archivr init` so the blob store lands on /data instead of the
  container layer (CLI default is ./.archivr/store, resolved from cwd,
  which is / with no WORKDIR set)

ENTRYPOINT vs CMD (P2):
- Dockerfile: switch from ENTRYPOINT to CMD so `docker compose run
  archivr archivr init …` overrides the full command instead of being
  appended to the server invocation

ffmpeg missing (P2):
- Dockerfile: add ffmpeg to the apt-get install block (required by
  yt-dlp --merge-output-format mp4 for bestvideo+bestaudio streams)

Node version (P2):
- Dockerfile: replace Debian bookworm's nodejs (18.x) with Node 20 via
  the NodeSource setup script (single-file-cli declares engines.node >=20)

Build context secrets (P2):
- Add .dockerignore excluding config/ and docker/ from the build context
  so runtime secrets (e.g. twitter-cookies.txt) are never sent to the builder
- Whitelist .dockerignore in .gitignore

docs:
- README: document ARCHIVR_CHROME_ARGS in the Environment Variables section
This commit is contained in:
TheGeneralist 2026-06-30 11:39:42 +02:00
parent 38d3066ee4
commit 93dea9ffbf
Signed by: thegeneralist01
SSH key fingerprint: SHA256:pp9qddbCNmVNoSjevdvQvM5z0DHN7LTa8qBMbcMq/R4
5 changed files with 47 additions and 11 deletions

9
.dockerignore Normal file
View file

@ -0,0 +1,9 @@
# Exclude runtime config and data directories from the Docker build context.
# The config/ directory may contain secrets (e.g. twitter-cookies.txt) that are
# only needed at runtime via a volume mount — they must never reach the builder.
config/
docker/
# Development and VCS noise
.git/
.gitignore

1
.gitignore vendored
View file

@ -20,6 +20,7 @@
!NEXT.md !NEXT.md
!Dockerfile !Dockerfile
!.dockerignore
!docker-compose.yml !docker-compose.yml
!docker/ !docker/
!docker/** !docker/**

View file

@ -44,18 +44,24 @@ FROM debian:bookworm-slim
# Runtime dependencies: # Runtime dependencies:
# chromium used by single-file-cli for full-page archiving # chromium used by single-file-cli for full-page archiving
# nodejs + npm runtime for single-file-cli # nodejs (20+) runtime for single-file-cli (requires Node >=20; Debian
# bookworm ships 18, so we install from the NodeSource repo)
# ffmpeg required by yt-dlp to merge separate audio/video streams
# (e.g. YouTube bestvideo+bestaudio format selection)
# python3 + pip + venv twitter scraper # python3 + pip + venv twitter scraper
# ca-certificates outbound HTTPS from the server # ca-certificates outbound HTTPS from the server and NodeSource HTTPS
# libssl3 OpenSSL linked by the Rust binary # libssl3 OpenSSL linked by the Rust binary
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
ca-certificates \
&& curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y --no-install-recommends \
chromium \ chromium \
nodejs \ nodejs \
npm \ ffmpeg \
python3 \ python3 \
python3-pip \ python3-pip \
python3-venv \ python3-venv \
ca-certificates \
libssl3 \ libssl3 \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
@ -88,10 +94,13 @@ ENV ARCHIVR_STATIC_DIR=/usr/share/archivr-server/static \
ARCHIVR_SINGLE_FILE=/usr/local/bin/single-file \ ARCHIVR_SINGLE_FILE=/usr/local/bin/single-file \
ARCHIVR_TWEET_PYTHON=/opt/archivr-venv/bin/python3 \ ARCHIVR_TWEET_PYTHON=/opt/archivr-venv/bin/python3 \
ARCHIVR_TWEET_SCRAPER=/usr/local/lib/archivr/scrape_user_tweet_contents.py \ ARCHIVR_TWEET_SCRAPER=/usr/local/lib/archivr/scrape_user_tweet_contents.py \
ARCHIVR_YT_DLP=/opt/archivr-venv/bin/yt-dlp ARCHIVR_YT_DLP=/opt/archivr-venv/bin/yt-dlp \
ARCHIVR_CHROME_ARGS=--no-sandbox
EXPOSE 8080 EXPOSE 8080
# Expects the TOML config at /config/archivr-server.toml (mount a volume). # Expects the TOML config at /config/archivr-server.toml (mount a volume).
# Copy docker/config.example.toml as a starting point. # Copy docker/config.example.toml as a starting point.
ENTRYPOINT ["archivr-server", "/config/archivr-server.toml"] # Using CMD (not ENTRYPOINT) so `docker compose run archivr archivr init …`
# can override the whole command for first-time archive initialisation.
CMD ["archivr-server", "/config/archivr-server.toml"]

View file

@ -68,10 +68,22 @@ fn save_with(
// without a writable user-data-dir. Using a subdirectory of temp_dir // without a writable user-data-dir. Using a subdirectory of temp_dir
// keeps it isolated and it gets cleaned up with the rest of the temp dir. // keeps it isolated and it gets cleaned up with the rest of the temp dir.
let chrome_data_dir = temp_dir.join("chrome-data"); let chrome_data_dir = temp_dir.join("chrome-data");
let browser_args = format!( // Build the browser-args JSON array. Start with the flags always required,
"[\"--disable-web-security\",\"--user-data-dir={}\"]", // then append any extra flags from ARCHIVR_CHROME_ARGS (space-separated).
chrome_data_dir.display() // Docker containers running as root need "--no-sandbox" here because
); // Chromium refuses to start as root without it.
let mut chrome_flags = vec![
"--disable-web-security".to_string(),
format!("--user-data-dir={}", chrome_data_dir.display()),
];
if let Ok(extra) = std::env::var("ARCHIVR_CHROME_ARGS") {
chrome_flags.extend(extra.split_whitespace().filter(|s| !s.is_empty()).map(str::to_string));
}
let quoted: Vec<String> = chrome_flags
.iter()
.map(|f| format!("\"{}\"", f.replace('\\', "\\\\").replace('"', "\\\"")))
.collect();
let browser_args = format!("[{}]", quoted.join(","));
let out = Command::new(single_file) let out = Command::new(single_file)
.arg(url) .arg(url)

View file

@ -209,7 +209,7 @@ A `Dockerfile` and `docker-compose.yml` are provided for self-hosting without Ni
The image includes the `archivr` CLI for this purpose: The image includes the `archivr` CLI for this purpose:
```sh ```sh
docker compose run --rm archivr archivr init /data/archives/main --name "Main Archive" docker compose run --rm archivr archivr init /data/archives/main /data/archives/main/.archivr/store --name "Main Archive"
``` ```
This creates `/data/archives/main/.archivr/` with the metadata the server requires. This creates `/data/archives/main/.archivr/` with the metadata the server requires.
@ -300,6 +300,11 @@ dependencies (Chromium, Node.js, Python) land in the final layer.
- `ARCHIVR_CHROME` - `ARCHIVR_CHROME`
- Optional. - Optional.
- Overrides the Chromium/Chrome executable passed to `single-file` via `--browser-executable-path`. Set automatically by the Nix wrapper and the Docker image. Default: `chromium`. - Overrides the Chromium/Chrome executable passed to `single-file` via `--browser-executable-path`. Set automatically by the Nix wrapper and the Docker image. Default: `chromium`.
- `ARCHIVR_CHROME_ARGS`
- Optional.
- Space-separated extra flags appended to Chromium's `--browser-args`. The Docker
image sets this to `--no-sandbox` because Chromium refuses to run as root without
it. Leave unset when running natively (Nix, Linux desktop).
- `ARCHIVR_TWITTER_CREDENTIALS_FILE` - `ARCHIVR_TWITTER_CREDENTIALS_FILE`
- Required for tweet/thread scraping inputs such as `tweet:ID` and `x:thread:ID`. - Required for tweet/thread scraping inputs such as `tweet:ID` and `x:thread:ID`.
- Must point to a cookies file for the vendored scraper. - Must point to a cookies file for the vendored scraper.