# Docker Mode After the [DD Photos desktop app↗](https://github.com/dougdonohoe/ddphotos-app/blob/main/README.md), the next easiest way to run `ddphotos` is via Docker — no complicated developer tool installation is required. ## Quick Start ### 1. Install Docker If you don't have Docker installed, click on the **Download Docker Desktop** button at the [Docker Getting Started↗](https://www.docker.com/get-started/) page to download the appropriate installer for your machine. Install it and then start _Docker.app_ (Mac) or _Docker Desktop_ (Windows/Linux). ### 1w. Windows Setup Windows users also need to install [Git For Windows↗](https://git-scm.com/download/win). This is so that the internal `ddphotos` bash and linux-style commands work. **NOTE**: It is perfectly **OK** to just accept all the default options (there are a lot of screens!). To adapt these docs for Windows: * Run commands in the `Terminal` app running `Windows PowerShell` * In place of `~` use `$HOME` (`~` works for some things, but not always) ### 2. Initialize Scaffolding Initialize a dedicated working directory that contains both the `ddphotos` script and a starter config: ```bash mkdir $HOME/my-ddphotos # Mac/Linux docker run --rm -v $HOME/my-ddphotos:/ddphotos dougdonohoe/ddphotos init # Windows - also installs `ddphotos.cmd` wrapper docker run --rm -v $HOME/my-ddphotos:/ddphotos dougdonohoe/ddphotos init --windows ``` ### 3. Generate, run, build, and serve the starter site ```bash cd ~/my-ddphotos ./ddphotos photogen # resize images and create index files ./ddphotos run # run dev server at http://localhost:5173 ./ddphotos build # build static site ./ddphotos serve # serve static site via Apache at http://localhost:8000 ``` ### 4. Build your own site 1. Edit `config/albums.yaml` to define your albums (see [Configuration](CONFIGURATION.md) for details) 2. Repeat: `photogen` → `run` / `build` → `serve` ### 5. Deploy **Quick option #1 — [Cloudflare Pages↗](https://pages.cloudflare.com)** - free, unlimited bandwidth (requires a [Cloudflare account](https://dash.cloudflare.com/login); `wrangler` is bundled — no local install needed): ```bash # One-time login (opens browser; credentials cached for future deploys) ./ddphotos wrangler login # Export and deploy ./ddphotos export --cloudflare ./ddphotos wrangler pages deploy --project-name my-unique-site export/my-photos ``` The site will be at https://my-unique-site.pages.dev. **Quick option #2 — [Surge↗](https://surge.sh)** - free, one command, no server required (`surge` is bundled — no local install needed): ```bash # Export and deploy (prompts for login on first run) ./ddphotos export --copy ./ddphotos surge --domain my-unique-site.surge.sh export/my-photos ``` The site will be at https://my-unique-site.surge.sh. **Production option** — configure `config/site.env` for rsync or S3 (see [site.env](CONFIGURATION.md#siteenv)), then: ```bash ./ddphotos deploy ``` See [Deployment](DEPLOY.md) for full setup details. ### 6. Install the `ddphotos` wrapper script Advanced users can install just the wrapper script into a directory on their `PATH`: ```bash # Into ~/.local/bin (common on Linux/Mac) docker run --rm -v ~/.local/bin:/ddphotos dougdonohoe/ddphotos init --script-only # Or into ~/bin docker run --rm -v ~/bin:/ddphotos dougdonohoe/ddphotos init --script-only ``` Once the script is on your `PATH`, you can create a starter site (config scaffold) in any directory by passing `--dir`: ```bash mkdir ~/my-ddphotos ddphotos --dir ~/my-ddphotos init ``` This scaffolds `config/albums.yaml` and friends into `~/my-ddphotos`, the same as the full `init` in [Initialize Scaffolding](#2-initialize-scaffolding). Pass `--site-id` to set a custom site ID. From then on, use `--dir ~/my-ddphotos` (or `cd ~/my-ddphotos`) with the other commands. If you have `ddphotos` on the path and the `ddphotos` repo checked out under `~/work`, you can use the script to photogen and run the [sample site↗](https://ddphotos.donohoe.info/): ```bash ddphotos --dir ~/work/ddphotos --config-dir ~/work/ddphotos/sample/config photogen ddphotos --dir ~/work/ddphotos --config-dir ~/work/ddphotos/sample/config run ``` --- ## `ddphotos` Usage: ```text ddphotos [options] [command] [args] ``` --- ### Pre-Command Options These flags go before the command name and apply to all commands that need them: | Flag | Description | |---------------------|------------------------------------------------------------------------------------------------------------| | `--dir DIR` | Directory containing your `config` and `albums` dirs (default: same directory as the `ddphotos` script) | | `--config-dir DIR` | Path to a config directory other than `/config` | | `--site-id ID` | Override the site ID (normally read from `config/albums.yaml`) | | `--site-env FILE` | Path to a `site.env` file other than `/site.env` | | `--non-interactive` | Run `serve` and `run` without a TTY (no `-it` flag) — useful for scripted/CI contexts | | `--show-mounts` | Print the Docker volume mounts before running the command — useful for debugging mount issues | | `--dev` | Use the locally-built `ddphotos` image instead of the pinned release tag — useful for testing local builds | Example — using a separate source repo as the albums dir: ```bash ddphotos --dir ~/work/ddphotos --config-dir ~/work/ddphotos/sample/config photogen ddphotos --dir ~/work/ddphotos --site-id sample build ``` --- ## Commands | Command | Description | |---------------------------------|-------------------------------------------------------------------| | [`init`](#init) | Create config scaffold and install the `ddphotos` wrapper script. | | [`photogen`](#photogen) | Resize photos to WebP and generate JSON index files. | | [`run`](#run) | Start a Vite dev server at http://localhost:5173. | | [`build`](#build) | Build the static site into `build/`. | | [`serve`](#serve) | Serve the built site via Apache at http://localhost:8000. | | [`export`](#export) | Export the built site to `export//` for static hosting. | | [`deploy`](#deploy) | Sync the built site to a remote host via rsync or S3. | | [`decode`](#decode) | Decrypt an `.enc.json` file and print the plaintext JSON. | | [`search-cover`](#search-cover) | Find the original filename for a photo given its URL. | | [`upgrade`](#upgrade) | Update the local `ddphotos` wrapper script to match the image. | | [`version`](#version) | Print script location, image tag, and config paths. | ### `init` Creates the config scaffold and installs the `ddphotos` wrapper script. ```bash # Full init (script + config) docker run --rm -v ~/my-ddphotos:/ddphotos dougdonohoe/ddphotos init # Set a custom site ID (written into config/albums.yaml; default: my-photos) docker run --rm -v ~/my-ddphotos:/ddphotos dougdonohoe/ddphotos init --site-id my-site # Script only (no config scaffold) docker run --rm -v ~/.local/bin:/ddphotos dougdonohoe/ddphotos init --script-only # Using an already-installed script (e.g. after --script-only) to scaffold a new site dir ddphotos --dir ~/my-ddphotos init ``` | Flag | Description | |-----------------|-----------------------------------------------------------------------------------| | `--site-id ID` | Site ID written into `config/albums.yaml` as `settings.id` (default: `my-photos`) | | `--script-only` | Install just the `ddphotos` wrapper script; skip config scaffold | If `ddphotos` is already on your `PATH` (for example, installed via `--script-only`), run `ddphotos --dir init` to scaffold a starter config into `` without a raw `docker run`. See [Install the `ddphotos` wrapper script](#6-install-the-ddphotos-wrapper-script). ### `photogen` Resizes source photos to WebP and generates JSON index files. Must be run before `build`, `run`, or `deploy`. ```bash ddphotos photogen ``` By default, this uses `-resize -index -clean -doit`. To define your own flags, use `--`: ```bash ddphotos photogen -- -hero-only ``` See [photogen CLI Flags](PHOTOGEN.md#cli-flags) for all `photogen` flags. ### `run` Starts a Vite dev server at http://localhost:5173. Live-reloads on template/CSS changes. ```bash ddphotos run ``` ### `build` Builds the static site output into `build/`. ```bash ddphotos build ``` If your `config` directory has a `static` sub-directory, any files in there are copied to the root of the build. This is useful for files like `humans.txt` or `llms.txt`. ### `serve` Serves the built static site via Apache at http://localhost:8000. Good for testing the final output before deploying. ```bash ddphotos serve ``` ### `export` Exports the built site into `export//` — a directory of relative symlinks or real files that any static file server can read. Useful for serving with `python3 -m http.server` or uploading to a static hosting service. ```bash ddphotos export ``` Serve the exported directory with Python: ```bash python3 -m http.server 8000 --directory export/my-photos ``` See [Local Testing with Python](DEPLOYMENT-SERVERS.md#local-testing-with-python) for notes on limitations and usage. Use `--copy` to produce real files instead of symlinks — required for services like [Surge↗](https://surge.sh) that don't follow symlinks: ```bash ddphotos export --copy ddphotos surge --domain my-unique-site.surge.sh export/my-photos ``` Use `--cloudflare` for [Cloudflare Pages↗](https://pages.cloudflare.com) — adds a `_worker.js` for photo permalink routing (symlinks are followed, so `--copy` is not needed): ```bash ddphotos export --cloudflare ddphotos wrangler pages deploy --project-name my-unique-site export/my-photos ``` See [Cloudflare Pages Worker](DEPLOYMENT-SERVERS.md#cloudflare-pages-worker) for details. Use `--export-site-id` to write the export to a different subdirectory name instead of `export//`: ```bash ddphotos export --export-site-id my-alternate-name ``` ### `deploy` Syncs the built site and album data to a remote host via rsync or S3. Requires `config/site.env`. ```bash ddphotos deploy ``` Extra flags pass through to the underlying deploy script. For example, to select a named AWS profile from `~/.aws` instead of relying on `AWS_*` environment variables: ```bash ddphotos deploy --aws-profile my-profile ``` See [Deployment](DEPLOY.md) for full setup details. ### `decode` Decrypts an `.enc.json` file produced by `photogen` and prints the plaintext JSON. Useful for inspecting what an encrypted album or site index contains — for example, to find a photo's original filename from its UUID so you can set it as a cover. ```bash ddphotos decode albums/my-photos/secret/index.enc.json ddphotos decode albums/my-photos/albums.enc.json ``` The passwords file path is embedded in every `.enc.json` by `photogen`, so no extra flags are needed in normal use. If the embedded path is unreachable, pass it explicitly: ```bash ddphotos decode --passwords config/passwords.yaml albums/my-photos/secret/index.enc.json ``` Paths are resolved relative to the `--dir` directory (default: the `ddphotos` script location). Files outside that directory are mounted automatically. ### `search-cover` Finds the original filename for a photo given its URL — useful for setting a cover image in `albums.yaml`. Pass any photo URL from your site (full-size or grid thumbnail): ```bash ddphotos search-cover https://my-site.example.com/albums/banff-2002/full/0918bedf-2f7d-dedc-9e89-b99ec5bb2752.webp ``` Output: ``` Searching... Album: banff-2002 Index: /ddphotos/albums/my-photos/banff-2002/index.json Source: full/0918bedf-2f7d-dedc-9e89-b99ec5bb2752.webp Found: id: 0918bedf-2f7d-dedc-9e89-b99ec5bb2752 sourcePath: /photos/banff-2002/IMG_1234.jpg fileName: IMG_1234.jpg Use for cover: cover: IMG_1234.jpg ``` Use the `--site-id` flag to search a different site: ```bash ddphotos --site-id other-site search-cover ``` ### `upgrade` Updates the local `ddphotos` wrapper script to match the image. Run this when an update notice appears to install the newer version, or to fix a script/image mismatch. ```bash ddphotos upgrade ``` ### `version` Prints the script location, image tag, and config paths. Runs locally — no Docker required. ```bash ddphotos version ``` ``` Script: /Users/anseladams/.local/bin/ddphotos Image: dougdonohoe/ddphotos:v1.2.0 DD Photos dir: /Users/anseladams/my-ddphotos Config dir: /Users/anseladams/my-ddphotos/config Site ID: my-photos State dir: /Users/anseladams/.config/ddphotos ``` Add `--image` to also query the image for its build details: ```bash ddphotos version --image ``` ``` Script: /Users/anseladams/.local/bin/ddphotos Image: dougdonohoe/ddphotos:v1.2.0 Version: v1.2.0 Git: v1.2.0-0-gabcdef1 DD Photos dir: /Users/anseladams/my-ddphotos Config dir: /Users/anseladams/my-ddphotos/config Site ID: my-photos State dir: /Users/anseladams/.config/ddphotos ``` The `--dir`, `--config-dir`, and `--site-id` pre-command flags also work with `version`, making it useful for confirming which config a given invocation would use. --- ## Directory Layout After `init`, your ddphotos directory looks like this: ``` my-ddphotos/ ddphotos ← wrapper script config/ albums.yaml ← album definitions, site settings, and descriptions custom.css ← optional CSS overrides passwords.yaml ← optional password protection site.env ← deploy credentials albums/ ← photogen output (generated, not edited) build/ ← static site output (generated, not edited) export/ ← export output (generated, not edited) ``` --- ## Version Check and Upgrade ### Automatic update check Each time you run `ddphotos`, it checks Docker Hub for a newer release — at most once per day, and only when the script is pinned to a versioned release (not a `dev` build). State is stored in `~/.config/ddphotos/` (created automatically on first run). If a newer version is available, a notice prints to stderr on every subsequent run: ``` Update available: v1.3.0 - run 'ddphotos upgrade' to update ``` Run `ddphotos upgrade` to pull and install it. The notice is cleared automatically once the installed version matches the latest. ### Script/image mismatch check Every command (except `init`, `upgrade`, and `version`) also checks that your local `ddphotos` script matches the running image. In normal use with a tagged release this should never fire — the automatic update check keeps things in sync. It is primarily relevant for `dev` builds, or in the unlikely event you manually edit the `ddphotos` script. If they differ, a warning is printed and the command continues normally: ``` WARNING: The local 'ddphotos' script does not match the image. Run: 'ddphotos upgrade' to fix this. ``` Run `ddphotos upgrade` to bring the script back in sync.