Running PhotoPrism with Kubernetes¶
While we believe this contributed content may be helpful to advanced users, we have not yet thoroughly reviewed it. If you have suggestions for improvement, please let us know by clicking to submit a change request.
At a minimum, you can just define a Kubernetes Service
and a StatefulSet
and be up and running. For more real-world usage, you'll probably want to at least include persistent storage, and possibly some Ingress
rules for exposing PhotoPrism outside your cluster.
Before you proceed, please ensure that your server has at least 4 GB of swap configured and avoid setting a hard memory limit as this can cause unexpected restarts when the indexer temporarily needs more memory to process large files. Indexing RAW images and high-resolution panoramas may require additional swap space and/or physical memory beyond the recommended minimum.
For those familiar with Helm, a PhotoPrism Helm chart is available.
Once you've got PhotoPrism deployed, you can exec
into the running container and photoprism import
your photos.
Here's an example of a YAML file that creates the following Kubernetes objects:
Namespace
Service
exposing PhotoPrism on port 80StatefulSet
with persistent NFS volumesSecret
which stores the database DSN and admin passwordIngress
rule for a Kubernetes ingress controller- Annotations for a Kubernetes
Certificate Manager
apiVersion: v1
kind: Namespace
metadata:
name: photoprism
---
apiVersion: v1
kind: Secret
metadata:
name: photoprism-secrets
namespace: photoprism
stringData:
PHOTOPRISM_ADMIN_PASSWORD: <your admin password here>
PHOTOPRISM_DATABASE_DSN: username:password@tcp(db-server-address:3306)/dbname?charset=utf8mb4,utf8&parseTime=true
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: photoprism
namespace: photoprism
spec:
selector:
matchLabels:
app: photoprism
serviceName: photoprism
replicas: 1
template:
metadata:
labels:
app: photoprism
spec:
containers:
- name: photoprism
image: photoprism/photoprism:latest
env:
- name: PHOTOPRISM_DEBUG
value: "true"
- name: PHOTOPRISM_DATABASE_DRIVER
value: mysql
- name: PHOTOPRISM_HTTP_HOST
value: 0.0.0.0
- name: PHOTOPRISM_HTTP_PORT
value: "2342"
# Load database DSN & admin password from secret
envFrom:
- secretRef:
name: photoprism-secrets
optional: false
ports:
- containerPort: 2342
name: http
volumeMounts:
- mountPath: /photoprism/originals
name: originals
- mountPath: /photoprism/import
name: import
- mountPath: /photoprism/storage
name: storage
readinessProbe:
httpGet:
path: /api/v1/status
port: http
volumes:
- name: originals
nfs:
path: /originals
# readOnly: true # Disables import and upload!
server: my.nas.host
- name: import
nfs:
path: /import
server: my.nas.host
- name: storage
nfs:
path: /storage
server: my.nas.host
---
apiVersion: v1
kind: Service
metadata:
name: photoprism
namespace: photoprism
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
selector:
app: photoprism
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
# For nginx ingress controller:
kubernetes.io/ingress.class: nginx
# Default is very low so most photo uploads will fail:
nginx.ingress.kubernetes.io/proxy-body-size: "512M"
# If using cert-manager:
cert-manager.io/cluster-issuer: letsencrypt-prod
kubernetes.io/tls-acme: "true"
name: photoprism
namespace: photoprism
spec:
rules:
- host: photoprism.my.domain
http:
paths:
- backend:
service:
name: photoprism
port:
name: http
path: /
pathType: Prefix
tls:
- hosts:
- photoprism.my.domain
secretName: photoprism-cert
To run this locally, you can use minikube or a similar local cluster deployer.
Once your cluster is up and running with your kubectl
commands. Simply copy the above YAML
markup to a file, make the necessary changes, and use the kubectl
CLI command to deploy:
kubectl create -f photoprism.yaml
If you prefer to use helm, see p80n/photoprism-helm.