PhotoStructure for Docker
These are instructions for advanced users, wanting to run PhotoStructure for Servers via Docker.
Background reading #
-
You should read the pros and cons of both Docker and Node editions before continuing.
-
Docker-compose may be easier to use than these instructions, which use
docker
directly, because:- upgrades are automatic
- adding and removing volumes to scan into your library is easy
The downside is that it’s one more software package that you need to install, and it may not be available on your host machine. The instructions for docker-compose are here.
-
If you want imported volumes in your library to be portable across machines, please read what’s a “volume?” (hint: skip to the last section and create
.uuid
files for all the volumes you import).
System requirements #
The docker images run under linux x64 Docker hosts.
PhotoStructure containers require at least 2GB of RAM during imports. You’ll see
ENOMEM
errors if you run within a 1GB container. PhotoStructure imports run
faster when more RAM and more CPU are allocated to the container.
The docker image is built on a recent CPU with SSE4
and AVX
extensions: CPUs
that are less than a decade old should work fine, but if your server is running
an older processor (like an AMD Phenom II), the image may not spin up.
Install Docker #
Follow these instructions for docker. If you’re on Ubuntu, follow these steps.
Note you need to use either Docker or Docker Compose: don’t use both simultaneously.
Docker volume setup #
PhotoStructure writes into 4 directories that must be mounted via docker volumes.
The following examples set up PhotoStructure to scan both a mounted external
hard drive at /mnt/Photos backup
and all files found in $HOME/Pictures
.
You’ll want to edit these examples to be relevant to your setup.
/ps/library
#
This is where your PhotoStructure Library will be stored. It must be readable and writable by the PhotoStructure container, and have sufficient free space.
/ps/tmp
#
This is PhotoStructure’s “scratch” directory.
/ps/tmp
must be on a local disk.- This volume should have at least 16-32 GB free.
- If you’ve got an SSD, use that: this directory will see a lot of reads and writes.
- If you can pick (or create) a volume that doesn’t have data integrity protection, on-the-fly compression, or on-the-fly file de-duplication. This will make imports faster as well as reduce system load.
- PhotoStructure automatically prunes old and unused files from the scratch directory: it shouldn’t take much space unless an import is running.
/ps/config
#
This is where PhotoStructure stores system settings.
/ps/logs
#
This is where PhotoStructure stores logfiles. Normally PhotoStructure should be
mostly quiet, unless you “send recent logs,” or set
PS_LOG_LEVEL
to something like info
.
PhotoStructure deletes logfiles older than 1 week automatically.
Directories to import #
-
To add directories you want to import into your PhotoStructure library, simply add them as bind volumes to your container. The following example configurations include a couple examples.
-
If you would like to ensure that PhotoStructure doesn’t change anything in the directories you import, you can mount these volumes read-only, with 2 caveats:
-
You will need to drop a .uuid file in the root of these volumes if you want your library to be portable.
-
This will prevent PhotoStructure from being able to write sidecars next to your originals to save metadata changes you make from within the UI.
-
Directories to omit #
PhotoStructure will import all mounted directories recursively. PhotoStructure
respects NoMedia
files, and will exclude those directories from being
imported. (learn more)
Advanced settings #
PhotoStructure has a bunch of settings that are only configurable outside of the PhotoStructure UI.
Docker users may find it’s easiest to use environment variables to override settings. Read more about PhotoStructure’s use of environment variables.
Running PhotoStructure for Docker as a non-root user #
Why not run as root? #
Dockerized applications run as root by default. If PhotoStructure runs as root, the files in your library will be owned by root, which can cause permission issues with the original files that PhotoStructure copies into your library.
Running PhotoStructure as a non-root user is also considered more secure.
How do I specify the userid and groupid? #
PhotoStructure uses linuxserver.io-style PUID
/PGID
environment
variables.
Required permissions #
The host system user and group specified by $PUID
/$PGID
must be able to
read and write to
/ps/library
/ps/tmp
/ps/config
, and/ps/logs
.
Read-only volumes #
It’s OK for bind mounts that contain photos and videos to be read-only, but you probably want to add a .uuid file.
Default PUID/PGID values #
If $PUID
or $PGID
is not set, PhotoStructure tries to be clever and looks
at the current owner of the system settings.toml
or library settings.toml
.
If both of those are missing, we default to 1000
for both $PUID
and
$PGID
, which are the default userid and groupid given to the first
non-system user (at least in Ubuntu and Fedora).
Run as root #
If you want PhotoStructure to run as root, set PUID=0
and PGID=0
.
Why is PhotoStructure running as node
? #
Rather than creating a new user in PhotoStructure’s container, we just change the
userid and groupid of node
to match $PUID
and PGID
.
chown
on startup #
PhotoStructure’s docker-entrypoint.sh
script will chown -R
your
library support directories if the current owner doesn’t match $PUID
, so
that after we drop root privileges to be node
, we still can read and write to your library.
Disable these chown
calls by setting the environment variable PS_NO_PUID_CHOWN=1
.
More PUID/PGID info #
Read more about this feature request in the forum.
See how PUID/PGID affects running CLI tooling
Networking setup #
-
The
PS_HTTP_PORT
environment variable defaults to 1787 but can be changed to a different port to suit. -
If you set up a reverse HTTPS proxy via nginx and find that dynamic updates (like the progress status) aren’t showing up, add this to your nginx config:
proxy_http_version 1.1;
proxy_set_header Connection "";
Example Docker setup #
This bash shell script can be saved to make future upgrades easier. See the docker documentation for more details.
#!/bin/bash
# Howdy, and welcome to PhotoStructure!
# Please review every "CHANGE THIS LINE" below.
# For more details, check out
# <https://photostructure.com/server/photostructure-for-docker/>
PSLIBRARY="$HOME/PhotoStructure" # < CHANGE THIS LINE
mkdir -p "$PSLIBRARY"
# This must be a fast, local disk (preferably an SSD) with many gigabytes free.
# It doesn't have to be in /tmp.
PSTMP="/tmp/ps-$USER"
mkdir -p -m 0700 "$PSTMP"
# This directory stores your "system settings". This directory must not be
# the same as the one used by PhotoStructure for Desktops.
PSCONFIG="$HOME/.config/PhotoStructure-docker"
mkdir -p "$PSCONFIG"
# This directory stores PhotoStructure logfiles.
PSLOGS="$HOME/.config/PhotoStructure/logs"
mkdir -p "$PSLOGS"
# TZ is only used as a backstop.
# Using `tzselect` might be helpful if you don't have TZ set.
TZ=${TZ:-$(cat /etc/timezone)}
# The userid to run PhotoStructure as. See <https://phstr.com/go/puid>
PUID=$(id -u) # < "id -u" will run PhotoStructure as the current user's userid.
# The groupid to run PhotoStructure as. See <https://phstr.com/go/pgid>
PGID=$(id -g) # < "id -g" will run PhotoStructure as the current user's groupid.
docker run \
--name photostructure \
--detach \
--restart unless-stopped `# < optional: see https://docs.docker.com/compose/compose-file/#restart` \
--stop-timeout 120 `# < gives PhotoStructure 2 minutes to shut down cleanly.` \
--publish 1787:1787 \
-e TZ="$TZ" \
-e PUID="$PUID" \
-e PGID="$PGID" \
-v "$PSLIBRARY":/ps/library \
-v "$PSTMP":/ps/tmp \
-v "$PSCONFIG":/ps/config \
-v "$PSLOGS":/ps/logs \
-v "$HOME"/Pictures:/pictures/ `# < CHANGE THIS LINE` \
photostructure/server:stable
Note that :alpha
, :beta
, and :stable
releases are available: read the
forum for
details.
In case of error #
If the PhotoStructure doesn’t spin up successfully, try replacing the
--detach
line with these lines:
-e PS_LOG_LEVEL=info \
-e PS_TAIL_LOGS=1
This runs PhotoStructure in --verbose
mode. Note that this can be pretty
chatty, but good for debugging why PhotoStructure is grumpy. Use
PS_LOG_LEVEL=warn
for less output, and PS_LOG_LEVEL=debug
for more output.
Still stuck? Hop onto the forum or discord and we’ll help diagnose what’s amiss.
Once you’ve fixed the issue, replace these lines back to --detach
.
Welcome to PhotoStructure! #
Open http://localhost:1787
in a browser to complete installation.
Firefox, Chrome, and Safari are supported.
While you wait for your import to complete, check out these getting-started tips!
How to stop PhotoStructure #
docker stop photostructure
(replace photostructure
with the name of your PhotoStructure docker container)
If you’re wondering why it’s taking a while to shut down, this is why.
How to restart PhotoStructure #
docker start photostructure
How to upgrade PhotoStructure #
Automatic upgrades via Watchtower (recommended) #
If you don’t mind all of your Docker containers to be upgraded automatically, use Watchtower:
docker run -d \
--name watchtower \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower
If you only want your PhotoStructure container to be upgraded automatically,
refer to the Watchtower
documentation, and how
the watchtower
container is set up with
docker-compose.
Manual upgrade process #
Step 1: Pull the new image #
docker pull photostructure/server:stable
Step 2: Shut down the outdated container #
Select “Shutdown” from the nav menu within the PhotoStructure, or run:
docker stop -t 60 photostructure
Step 3: Rename the outdated container #
docker rename photostructure photostructure_old
Step 4: Start a new container #
docker run \
--name photostructure \
--volumes-from photostructure_old \
`# <copy and paste all the non-volume options you set in step 3, like --user, --expose and -e >`
photostructure/server
Step 5: Remove the outdated container #
docker rm photostructure_old
Uninstalling PhotoStructure #
docker rm --force photostructure
- As you see fit, remove your
LIBRARY
,CONFIG
,LOG
, andTMP
directories, but take care not to delete photos and videos you want to keep! If you want to keep the originals in your library, but remove PhotoStructure’s preview images and videos, you can delete the$LIBRARY/.photostructure/previews
directory.
Portainer instructions #
Portainer CE is an open-source docker management GUI that can be used instead of running docker
on the command-line.
Installation instructions for Linux are here, and, here’s a video walkthrough:
Thanks to forum member @avdp for recording this!
Synology docker instructions #
PhotoStructure’s docker image runs happily on intel x64 compatible Synology NAS
devices. First install the Docker package via Main Menu > Package Center
.
Install on Synology #
Unfortunately, Synology DSM’s Docker interface doesn’t support running
containers with --user
. This results in your library files being owned by
root
. It also is less secure to run PhotoStructure as root (even within a Docker container).
Because of these two issues, we recommend setting up the docker container via ssh rather than via the pointy-clicky Synology DSM interface.
Via ssh #
- Enable ssh on your NAS
- Set up the above instructions, but change
docker run
tosudo docker run
.
Via Synology DSM #
- Click
Main Menu > Docker
- Click the
Image
tab - Click
Add > Add from URL
- Enter
https://hub.docker.com/r/photostructure/server
- Pick
latest
- Wait for the image to download (it’s 300MB, it may take a minute). You’ll see a system notification when it’s done.
- Click
Launch
- Do not select high privilege. You can select resource limitation, but give PhotoStructure at least 2GB.
- Click
Advanced Settings
. - You may want to enable auto-start under the
Advanced Settings
tab. - Click the
Volume
tab. Read about the required volumes, and then add entries for/ps/library
/ps/tmp
/ps/logs
/ps/config
- and any existing directories you want to import into your library.
- Configure the network port as you’d like it. You can just map port 1787 directly.
- Click the Network tab, select “bridge”, click “Manage”, click “Add”, then select “PhotoStructure”.
- Launch the new container by clicking the power switch to the right, and wait for it to start successfully. If it fails, check under the Log tab. Email us if you need help!
Extra credit: if you click on the Container tab, double-click photostructure
,
and then click the Terminal tab, you can type --status
(and hit return) to
have PhotoStructure run health checks. (You can also run --pause
, --resume
,
and --exit
).
Upgrade on Synology #
Consider using Watchtower, which will upgrade all your docker images automatically: just ssh into your NAS, and run this:
sudo docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower
(Click “remove container” in the DSM Docker interface to uninstall watchtower).
If you’d rather upgrade manually, it’s a simple 16 step process:
- Click
Main Menu > Docker
- Click the
Container
tab - Click your PhotoStructure container to select it
- Click
Settings > Export
- Select
Export container settings
(you don’t need to store the container contents). - The export should be a small JSON file. Store it locally or on your NAS.
- With your PhotoStructure container still selected, make sure it isn’t running. If it is, select
Action > Stop
. - Click
Action > Delete
. (this is scary, but as long as you correctly mounted/ps/library
, your library will be on your NAS, not inside this container). - Click the
Image
tab - Click
Add > Add from URL
- Enter
https://hub.docker.com/r/photostructure/server
- Pick
latest
- Wait for the image to download (it’s 300MB, it may take a minute). You’ll see a system notification when it’s done.
- Return to the Container tab, and click
Settings > Import
- Import the JSON file you exported in step 6.
- Launch the new container by clicking the power switch to the right
Edit history #
July 13, 2022 #
- Added new Portainer section
- Deleted QNAP instructions, which is not supported.
January 3 3, 2022 #
- Updated the shell script to include a shebang and more comments around TZ, PUID, and PGID.
August 22, 2021 #
-
Make all image names use
photostructure/server:info
-
Add
container_name
to QNAP’s docker-compose.yml
August 12, 2021 #
- Replace
--user
references with v1.0’sPUID
/PGID
November 17, 2020 #
- Added QNAP instructions
September 22, 2020 #
- Switched to
--restart on-failure
- Added
--stop-timeout 120
August 7, 2020 #
- Set up
--user
instructions - Normal users don’t have read/write to docker volumes, so
/ps/log
and/ps/cache
defaults are bind mounts in the example now.
August 4, 2020 #
- Added more detail about the different volumes
- Removed
--init
from thedocker run
command, as v0.8.3 doesn’t require it anymore - Added section for docker on Synology
- Pulled docker-compose instructions into new doc
July 31, 2020 #
- Systemd start-on-boot configurations were replaced with docker’s built-in
restart: unless-stopped
functionality. - Added config fix for https reverse proxy issues with Server-side events.
- Clarified when
.uuid
files were needed (only for imported volumes, not the library itself).
July 20, 2020 #
- If you used versions prior to 0.8, these instructions have changed. We simplified the instructions to be vanilla Docker,although you’re free to use docker-compose if you prefer.