diff --git a/Dockerfile b/Dockerfile index 4b8c51b05..65055ba30 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ FROM photoprism/develop:220225-bullseye # FROM photoprism/develop:impish # Ubuntu 21.10, Codename "Impish Indri" # copy entrypoint script to container -COPY --chown=root:root /docker/develop/entrypoint.sh /entrypoint.sh +COPY --chown=root:root /scripts/dist/entrypoint.sh /entrypoint.sh # define working directory in container WORKDIR "/go/src/github.com/photoprism/photoprism" diff --git a/Makefile b/Makefile index 936924387..5edce485c 100644 --- a/Makefile +++ b/Makefile @@ -78,7 +78,7 @@ install: env TMPDIR="$(BUILD_PATH)" ./scripts/dist/install-tensorflow.sh $(DESTDIR) rm -rf --preserve-root $(DESTDIR)/include (cd $(DESTDIR) && mkdir -p bin scripts lib assets config config/examples) - scripts/build.sh prod $(DESTDIR)/bin/$(BINARY_NAME) + ./scripts/build.sh prod "$(DESTDIR)/bin/$(BINARY_NAME)" [ -f "$(GOBIN)/gosu" ] || go install github.com/tianon/gosu@latest cp $(GOBIN)/gosu $(DESTDIR)/bin/gosu [ ! -f "$(GOBIN)/exif-read-tool" ] || cp $(GOBIN)/exif-read-tool $(DESTDIR)/bin/exif-read-tool @@ -89,7 +89,7 @@ install: chown -R $(INSTALL_USER) $(DESTDIR) chmod -R $(INSTALL_MODE) $(DESTDIR) chmod -R $(INSTALL_MODE_BIN) $(DESTDIR)/bin $(DESTDIR)/lib $(DESTDIR)/scripts/*.sh - echo "PhotoPrism $(BUILD_TAG) has been successfully installed in \"$(DESTDIR)\".\nEnjoy!" + @echo "PhotoPrism $(BUILD_TAG) has been successfully installed in \"$(DESTDIR)\".\nEnjoy!" install-go: sudo scripts/dist/install-go.sh go build -v ./... diff --git a/docker/develop/armv7/Dockerfile b/docker/develop/armv7/Dockerfile index 9dbf23aa5..42cbf49d6 100644 --- a/docker/develop/armv7/Dockerfile +++ b/docker/develop/armv7/Dockerfile @@ -24,7 +24,6 @@ ENV DOCKER_ARCH=$TARGETARCH \ # copy scripts and debian backports sources list COPY --chown=root:root --chmod=755 /scripts/dist/* /root/.local/bin/ COPY --chown=root:root --chmod=644 /docker/develop/bullseye/sources.list /etc/apt/sources.list.d/bullseye.list -COPY --chown=root:root --chmod=755 /docker/develop/entrypoint.sh /entrypoint.sh COPY --chown=root:root --chmod=644 /.my.cnf /etc/my.cnf # update image and install build dependencies @@ -113,6 +112,7 @@ RUN /usr/local/go/bin/go install github.com/tianon/gosu@latest; \ echo "alias ll='ls -alh'" > /root/.bash_aliases && \ echo "ALL ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/all && \ cp /root/.local/bin/heif-convert.sh /usr/local/bin/heif-convert && \ + cp /root/.local/bin/entrypoint.sh /entrypoint.sh && \ chmod -R a+rwX /go # set up project directory @@ -125,7 +125,7 @@ WORKDIR "/go/src/github.com/photoprism/photoprism" # - 40000 (Go Debugger) EXPOSE 2342 2343 9515 40000 -# define container entrypoint script +# set container entrypoint script ENTRYPOINT ["/entrypoint.sh"] # keep container running diff --git a/docker/develop/bullseye-slim/Dockerfile b/docker/develop/bullseye-slim/Dockerfile index d5711a159..836eda304 100644 --- a/docker/develop/bullseye-slim/Dockerfile +++ b/docker/develop/bullseye-slim/Dockerfile @@ -36,6 +36,8 @@ RUN echo 'Acquire::Retries "10";' > /etc/apt/apt.conf.d/80retry && \ wget \ curl \ make \ + sudo \ + bash \ sqlite3 \ tzdata \ libc6 \ @@ -62,6 +64,7 @@ RUN echo 'Acquire::Retries "10";' > /etc/apt/apt.conf.d/80retry && \ /photoprism/storage/config \ /photoprism/storage/cache \ && \ + echo "ALL ALL=(ALL) NOPASSWD: /opt/photoprism/scripts/entrypoint-init.sh" >> /etc/sudoers.d/init && \ cleanup.sh # define default directory and user diff --git a/docker/develop/bullseye/Dockerfile b/docker/develop/bullseye/Dockerfile index fa9690ccf..964a66717 100644 --- a/docker/develop/bullseye/Dockerfile +++ b/docker/develop/bullseye/Dockerfile @@ -24,7 +24,6 @@ ENV DOCKER_ARCH=$TARGETARCH \ # copy scripts and debian backports sources list COPY --chown=root:root --chmod=755 /scripts/dist/* /root/.local/bin/ COPY --chown=root:root --chmod=644 /docker/develop/bullseye/sources.list /etc/apt/sources.list.d/bullseye.list -COPY --chown=root:root --chmod=755 /docker/develop/entrypoint.sh /entrypoint.sh COPY --chown=root:root --chmod=644 /.my.cnf /etc/my.cnf # update image and install build dependencies @@ -124,6 +123,7 @@ RUN /usr/local/go/bin/go install github.com/tianon/gosu@latest && \ echo "alias go=richgo ll='ls -alh'" > /root/.bash_aliases && \ echo "ALL ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/all && \ cp /root/.local/bin/heif-convert.sh /usr/local/bin/heif-convert && \ + cp /root/.local/bin/entrypoint.sh /entrypoint.sh && \ chmod -R a+rwX /go # set up project directory @@ -136,7 +136,7 @@ WORKDIR "/go/src/github.com/photoprism/photoprism" # - 40000 (Go Debugger) EXPOSE 2342 2343 9515 40000 -# define container entrypoint script +# set container entrypoint script ENTRYPOINT ["/entrypoint.sh"] # keep container running diff --git a/docker/develop/buster/Dockerfile b/docker/develop/buster/Dockerfile index 8f8afc715..9bad0775c 100644 --- a/docker/develop/buster/Dockerfile +++ b/docker/develop/buster/Dockerfile @@ -24,7 +24,6 @@ ENV DOCKER_ARCH=$TARGETARCH \ # copy scripts and debian backports sources list COPY --chown=root:root --chmod=755 /scripts/dist/* /root/.local/bin/ COPY --chown=root:root --chmod=644 /docker/develop/buster/sources.list /etc/apt/sources.list.d/buster.list -COPY --chown=root:root --chmod=755 /docker/develop/entrypoint.sh /entrypoint.sh COPY --chown=root:root --chmod=644 /.my.cnf /etc/my.cnf # update image and install build dependencies @@ -123,6 +122,7 @@ RUN /usr/local/go/bin/go install github.com/tianon/gosu@latest && \ echo "alias go=richgo ll='ls -alh'" > /root/.bash_aliases && \ echo "ALL ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/all && \ cp /root/.local/bin/heif-convert.sh /usr/local/bin/heif-convert && \ + cp /root/.local/bin/entrypoint.sh /entrypoint.sh && \ chmod -R a+rwX /go # set up project directory @@ -135,7 +135,7 @@ WORKDIR "/go/src/github.com/photoprism/photoprism" # - 40000 (Go Debugger) EXPOSE 2342 2343 9515 40000 -# define container entrypoint script +# set container entrypoint script ENTRYPOINT ["/entrypoint.sh"] # keep container running diff --git a/docker/develop/entrypoint.sh b/docker/develop/entrypoint.sh deleted file mode 100755 index fdbdc27cb..000000000 --- a/docker/develop/entrypoint.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env bash - -DOCKER_ARCH=${DOCKER_ARCH:-arch} -DOCKER_ENV=${DOCKER_ENV:-unknown} -DOCKER_TAG=${DOCKER_TAG:-unknown} - -if [[ $(id -u) == "0" ]]; then - echo "started as root" - - if [[ ! -e /root/.init ]] && [[ ${PHOTOPRISM_INIT} ]]; then - for target in $PHOTOPRISM_INIT; do - echo "init ${target}..." - make -f /go/src/github.com/photoprism/photoprism/scripts/dist/Makefile "${target}" - done - echo 1 >/root/.init - fi -else - echo "started as uid $(id -u)" -fi - -re='^[0-9]+$' - -# check for alternate umask variable -if [[ -z ${PHOTOPRISM_UMASK} ]] && [[ ${UMASK} =~ $re ]] && [[ ${#UMASK} == 4 ]]; then - PHOTOPRISM_UMASK=${UMASK} -fi - -# set file-creation mode (umask) -if [[ ${PHOTOPRISM_UMASK} =~ $re ]] && [[ ${#PHOTOPRISM_UMASK} == 4 ]]; then - umask "${PHOTOPRISM_UMASK}" -else - umask 0002 -fi - -# show info -echo "image: $DOCKER_ARCH-$DOCKER_ENV" -echo "build: $DOCKER_TAG" -echo "umask: \"$(umask)\" ($(umask -S))" - -# script must run as root to perform changes -if [[ $(id -u) == "0" ]]; then - # check for alternate user ID env variables - if [[ -z ${PHOTOPRISM_UID} ]]; then - if [[ ${UID} =~ $re ]] && [[ ${UID} != "0" ]]; then - PHOTOPRISM_UID=${UID} - elif [[ ${PUID} =~ $re ]] && [[ ${PUID} != "0" ]]; then - PHOTOPRISM_UID=${PUID} - fi - fi - - # check for alternate group ID env variables - if [[ -z ${PHOTOPRISM_GID} ]]; then - if [[ ${GID} =~ $re ]] && [[ ${GID} != "0" ]]; then - PHOTOPRISM_GID=${GID} - elif [[ ${PGID} =~ $re ]] && [[ ${PGID} != "0" ]]; then - PHOTOPRISM_GID=${PGID} - fi - fi - - # check uid and gid env variables - if [[ ${PHOTOPRISM_UID} =~ $re ]] && [[ ${PHOTOPRISM_UID} != "0" ]] && [[ ${PHOTOPRISM_GID} =~ $re ]] && [[ ${PHOTOPRISM_GID} != "0" ]]; then - # RUN AS SPECIFIED USER + GROUP ID - groupadd -g "${PHOTOPRISM_GID}" "group_${PHOTOPRISM_GID}" 2>/dev/null - useradd -o -u "${PHOTOPRISM_UID}" -g "${PHOTOPRISM_GID}" -d /photoprism "user_${PHOTOPRISM_UID}" 2>/dev/null - usermod -g "${PHOTOPRISM_GID}" "user_${PHOTOPRISM_UID}" 2>/dev/null - - if [[ -z ${PHOTOPRISM_DISABLE_CHOWN} ]]; then - echo "updating filesystem permissions..." - echo "PHOTOPRISM_DISABLE_CHOWN: \"true\" disables filesystem permission updates" - chown --preserve-root -Rcf "${PHOTOPRISM_UID}:${PHOTOPRISM_GID}" /go /photoprism /opt/photoprism /tmp/photoprism - chmod --preserve-root -Rcf u+rwX /go/src/github.com/photoprism/photoprism/* /photoprism /opt/photoprism /tmp/photoprism - fi - - echo "switching to uid ${PHOTOPRISM_UID}:${PHOTOPRISM_GID}" - echo "${@}" - - gosu "${PHOTOPRISM_UID}:${PHOTOPRISM_GID}" "$@" & - elif [[ ${PHOTOPRISM_UID} =~ $re ]] && [[ ${PHOTOPRISM_UID} != "0" ]]; then - # RUN AS SPECIFIED USER ID - useradd -o -u "${PHOTOPRISM_UID}" -g 1000 -d /photoprism "user_${PHOTOPRISM_UID}" 2>/dev/null - usermod -g 1000 "user_${PHOTOPRISM_UID}" 2>/dev/null - - if [[ -z ${PHOTOPRISM_DISABLE_CHOWN} ]]; then - echo "updating filesystem permissions..." - echo "PHOTOPRISM_DISABLE_CHOWN: \"true\" disables filesystem permission updates" - chown --preserve-root -Rcf "${PHOTOPRISM_UID}" /go /photoprism /opt/photoprism /tmp/photoprism - chmod --preserve-root -Rcf u+rwX /go/src/github.com/photoprism/photoprism/* /photoprism /opt/photoprism /tmp/photoprism - fi - - echo "switching to uid ${PHOTOPRISM_UID}" - echo "${@}" - - gosu "${PHOTOPRISM_UID}" "$@" & - else - # RUN AS ROOT - echo "running as root" - echo "${@}" - - "$@" & - fi -else - # RUN AS NON-ROOT USER - echo "running as uid $(id -u)" - echo "${@}" - - "$@" & -fi - -PID=$! - -trap "kill $PID" INT TERM -wait diff --git a/docker/develop/impish/Dockerfile b/docker/develop/impish/Dockerfile index 5730a624a..2b68e7c94 100644 --- a/docker/develop/impish/Dockerfile +++ b/docker/develop/impish/Dockerfile @@ -23,7 +23,6 @@ ENV DOCKER_ARCH=$TARGETARCH \ # copy scripts and debian backports sources list COPY --chown=root:root --chmod=755 /scripts/dist/* /root/.local/bin/ -COPY --chown=root:root --chmod=755 /docker/develop/entrypoint.sh /entrypoint.sh COPY --chown=root:root --chmod=644 /.my.cnf /etc/my.cnf # update image and install build dependencies @@ -124,6 +123,7 @@ RUN /usr/local/go/bin/go install github.com/tianon/gosu@latest && \ echo "alias go=richgo ll='ls -alh'" > /root/.bash_aliases && \ echo "ALL ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/all && \ cp /root/.local/bin/heif-convert.sh /usr/local/bin/heif-convert && \ + cp /root/.local/bin/entrypoint.sh /entrypoint.sh && \ chmod -R a+rwX /go # set up project directory @@ -136,7 +136,7 @@ WORKDIR "/go/src/github.com/photoprism/photoprism" # - 40000 (Go Debugger) EXPOSE 2342 2343 9515 40000 -# define container entrypoint script +# set container entrypoint script ENTRYPOINT ["/entrypoint.sh"] # keep container running diff --git a/docker/examples/arm64/docker-compose.yml b/docker/examples/arm64/docker-compose.yml index 085bcae98..22f399c09 100644 --- a/docker/examples/arm64/docker-compose.yml +++ b/docker/examples/arm64/docker-compose.yml @@ -97,7 +97,6 @@ services: # PHOTOPRISM_UID: 1000 # PHOTOPRISM_GID: 1000 # PHOTOPRISM_UMASK: 0000 - HOME: "/photoprism" ## Start as a non-root user (see https://docs.docker.com/engine/reference/run/#user) # user: "1000:1000" ## Share hardware devices with FFmpeg and TensorFlow (optional): diff --git a/docker/examples/armv7/docker-compose.yml b/docker/examples/armv7/docker-compose.yml index 8cde51f69..ebf4e54fc 100644 --- a/docker/examples/armv7/docker-compose.yml +++ b/docker/examples/armv7/docker-compose.yml @@ -90,7 +90,6 @@ services: # PHOTOPRISM_UID: 1000 # PHOTOPRISM_GID: 1000 # PHOTOPRISM_UMASK: 0000 - HOME: "/photoprism" ## Start as a non-root user (see https://docs.docker.com/engine/reference/run/#user) # user: "1000:1000" ## Share hardware devices with FFmpeg and TensorFlow (optional): diff --git a/docker/examples/cloud/docker-compose.yml b/docker/examples/cloud/docker-compose.yml index 5790d7bd5..6d010cd5b 100644 --- a/docker/examples/cloud/docker-compose.yml +++ b/docker/examples/cloud/docker-compose.yml @@ -156,7 +156,6 @@ services: PHOTOPRISM_DATABASE_PASSWORD: "_admin_password_" # MariaDB or MySQL database user password ## Add/update packages (service must be started as root; options: update, gpu, tensorflow, davfs, clean): PHOTOPRISM_INIT: "update tensorflow clean" - HOME: "/photoprism" working_dir: "/photoprism" ## Storage Folders: "~" is a shortcut for your home directory, "." for the current directory volumes: diff --git a/docker/examples/docker-compose.yml b/docker/examples/docker-compose.yml index 612002032..20eeb1df9 100644 --- a/docker/examples/docker-compose.yml +++ b/docker/examples/docker-compose.yml @@ -90,7 +90,6 @@ services: # PHOTOPRISM_UID: 1000 # PHOTOPRISM_GID: 1000 # PHOTOPRISM_UMASK: 0000 - HOME: "/photoprism" ## Start as a non-root user (see https://docs.docker.com/engine/reference/run/#user) # user: "1000:1000" ## Share hardware devices with FFmpeg and TensorFlow (optional): diff --git a/docker/examples/macos/docker-compose.yml b/docker/examples/macos/docker-compose.yml index 9cc7fb0b5..d5d96c398 100644 --- a/docker/examples/macos/docker-compose.yml +++ b/docker/examples/macos/docker-compose.yml @@ -77,7 +77,6 @@ services: PHOTOPRISM_SITE_AUTHOR: "" ## Add/update packages (service must be started as root; options: update, gpu, tensorflow, davfs, clean): # PHOTOPRISM_INIT: "update gpu tensorflow clean" - HOME: "/photoprism" ## Storage Folders: "~" is a shortcut for your home directory, "." for the current directory volumes: # "/host/folder:/photoprism/folder" # example diff --git a/docker/examples/scheduler/docker-compose.yml b/docker/examples/scheduler/docker-compose.yml index f4238a159..c99c6de46 100644 --- a/docker/examples/scheduler/docker-compose.yml +++ b/docker/examples/scheduler/docker-compose.yml @@ -87,7 +87,6 @@ services: # PHOTOPRISM_UID: 1000 # PHOTOPRISM_GID: 1000 # PHOTOPRISM_UMASK: 0000 - HOME: "/photoprism" ## Start as a non-root user (see https://docs.docker.com/engine/reference/run/#user) # user: "1000:1000" working_dir: "/photoprism" diff --git a/docker/examples/sqlite/docker-compose.yml b/docker/examples/sqlite/docker-compose.yml index 1ca8e255a..630180c8c 100644 --- a/docker/examples/sqlite/docker-compose.yml +++ b/docker/examples/sqlite/docker-compose.yml @@ -80,7 +80,6 @@ services: # PHOTOPRISM_UID: 1000 # PHOTOPRISM_GID: 1000 # PHOTOPRISM_UMASK: 0000 - HOME: "/photoprism" ## Start as a non-root user (see https://docs.docker.com/engine/reference/run/#user) # user: "1000:1000" working_dir: "/photoprism" diff --git a/docker/examples/windows/docker-compose.yml b/docker/examples/windows/docker-compose.yml index fb00e0847..3ff5bd622 100644 --- a/docker/examples/windows/docker-compose.yml +++ b/docker/examples/windows/docker-compose.yml @@ -80,7 +80,6 @@ services: PHOTOPRISM_SITE_CAPTION: "AI-Powered Photos App" PHOTOPRISM_SITE_DESCRIPTION: "" PHOTOPRISM_SITE_AUTHOR: "" - HOME: "/photoprism" working_dir: "/photoprism" ## Storage Folders: use "/" not "\" as separator, "~" is a shortcut for C:/user/{username}, "." for the current directory volumes: diff --git a/docker/photoprism/armv7/Dockerfile b/docker/photoprism/armv7/Dockerfile index 40e4fe814..b8145e86c 100644 --- a/docker/photoprism/armv7/Dockerfile +++ b/docker/photoprism/armv7/Dockerfile @@ -96,6 +96,8 @@ RUN echo 'Acquire::Retries "10";' > /etc/apt/apt.conf.d/80retry && \ wget \ curl \ make \ + sudo \ + bash \ mariadb-client \ sqlite3 \ tzdata \ @@ -121,6 +123,8 @@ RUN echo 'Acquire::Retries "10";' > /etc/apt/apt.conf.d/80retry && \ /photoprism/storage/config \ /photoprism/storage/cache \ && \ + echo "ALL ALL=(ALL) NOPASSWD: /opt/photoprism/scripts/entrypoint-init.sh" >> /etc/sudoers.d/init && \ + cp /opt/photoprism/scripts/entrypoint.sh /entrypoint.sh && \ cleanup.sh # define default directory and user @@ -129,8 +133,8 @@ WORKDIR /photoprism # expose default http port 2342 EXPOSE 2342 -# define container entrypoint script -ENTRYPOINT ["/opt/photoprism/scripts/entrypoint.sh"] +# set container entrypoint script +ENTRYPOINT ["/entrypoint.sh"] # start app server CMD ["/opt/photoprism/bin/photoprism", "start"] diff --git a/docker/photoprism/bullseye/Dockerfile b/docker/photoprism/bullseye/Dockerfile index 496657e37..2427a7049 100644 --- a/docker/photoprism/bullseye/Dockerfile +++ b/docker/photoprism/bullseye/Dockerfile @@ -85,9 +85,10 @@ EXPOSE 2342 # copy app dist files and debian backports sources list COPY --from=build /opt/photoprism/ /opt/photoprism +RUN cp /opt/photoprism/scripts/entrypoint.sh /entrypoint.sh -# define container entrypoint script -ENTRYPOINT ["/opt/photoprism/scripts/entrypoint.sh"] +# set container entrypoint script +ENTRYPOINT ["/entrypoint.sh"] # start app server CMD ["/opt/photoprism/bin/photoprism", "start"] diff --git a/docker/photoprism/buster/Dockerfile b/docker/photoprism/buster/Dockerfile index aec0e5116..ffd8bf577 100644 --- a/docker/photoprism/buster/Dockerfile +++ b/docker/photoprism/buster/Dockerfile @@ -96,6 +96,8 @@ RUN echo 'Acquire::Retries "10";' > /etc/apt/apt.conf.d/80retry && \ wget \ curl \ make \ + sudo \ + bash \ mariadb-client \ sqlite3 \ tzdata \ @@ -122,6 +124,8 @@ RUN echo 'Acquire::Retries "10";' > /etc/apt/apt.conf.d/80retry && \ /photoprism/storage/config \ /photoprism/storage/cache \ && \ + echo "ALL ALL=(ALL) NOPASSWD: /opt/photoprism/scripts/entrypoint-init.sh" >> /etc/sudoers.d/init && \ + cp /opt/photoprism/scripts/entrypoint.sh /entrypoint.sh && \ cleanup.sh # define default directory and user @@ -130,8 +134,8 @@ WORKDIR /photoprism # expose default http port 2342 EXPOSE 2342 -# define container entrypoint script -ENTRYPOINT ["/opt/photoprism/scripts/entrypoint.sh"] +# set container entrypoint script +ENTRYPOINT ["/entrypoint.sh"] # start app server CMD ["/opt/photoprism/bin/photoprism", "start"] diff --git a/docker/photoprism/impish/Dockerfile b/docker/photoprism/impish/Dockerfile index 1dd31b035..dd3d7b022 100644 --- a/docker/photoprism/impish/Dockerfile +++ b/docker/photoprism/impish/Dockerfile @@ -95,6 +95,8 @@ RUN echo 'Acquire::Retries "10";' > /etc/apt/apt.conf.d/80retry && \ wget \ curl \ make \ + sudo \ + bash \ mariadb-client \ sqlite3 \ tzdata \ @@ -121,6 +123,8 @@ RUN echo 'Acquire::Retries "10";' > /etc/apt/apt.conf.d/80retry && \ /photoprism/storage/config \ /photoprism/storage/cache \ && \ + echo "ALL ALL=(ALL) NOPASSWD: /opt/photoprism/scripts/entrypoint-init.sh" >> /etc/sudoers.d/init && \ + cp /opt/photoprism/scripts/entrypoint.sh /entrypoint.sh && \ cleanup.sh # define default directory and user @@ -129,8 +133,8 @@ WORKDIR /photoprism # expose default http port 2342 EXPOSE 2342 -# define container entrypoint script -ENTRYPOINT ["/opt/photoprism/scripts/entrypoint.sh"] +# set container entrypoint script +ENTRYPOINT ["/entrypoint.sh"] # start app server CMD ["/opt/photoprism/bin/photoprism", "start"] diff --git a/scripts/build.sh b/scripts/build.sh index b9091b0f5..c1a9ba1d9 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -13,21 +13,28 @@ BUILD_DATE=$(date -u +%y%m%d) BUILD_VERSION=$(git describe --always) BUILD_TAG=${BUILD_DATE}-${BUILD_VERSION} BUILD_ID=${BUILD_TAG}-${BUILD_OS}-${BUILD_ARCH^^} +BUILD_NAME=$(realpath "${2:-photoprism}") +GO_BIN=${GO_BIN:-/usr/local/go/bin/go} echo "Building PhotoPrism ${BUILD_ID} ($1)..." if [[ $1 == "debug" ]]; then - go build -ldflags "-X main.version=${BUILD_ID}-DEBUG" -o $2 cmd/photoprism/photoprism.go - du -h $2 + BUILD_CMD=("$GO_BIN" build -ldflags "-X main.version=${BUILD_ID}-DEBUG" -o "${BUILD_NAME}" cmd/photoprism/photoprism.go) elif [[ $1 == "race" ]]; then - go build -race -ldflags "-X main.version=${BUILD_ID}-DEBUG" -o $2 cmd/photoprism/photoprism.go - du -h $2 + BUILD_CMD=("$GO_BIN" build -race -ldflags "-X main.version=${BUILD_ID}-DEBUG" -o "${BUILD_NAME}" cmd/photoprism/photoprism.go) elif [[ $1 == "static" ]]; then - go build -a -v -ldflags "-linkmode external -extldflags \"-static -L /usr/lib -ltensorflow\" -s -w -X main.version=${BUILD_ID}" -o $2 cmd/photoprism/photoprism.go - du -h $2 + BUILD_CMD=("$GO_BIN" build -a -v -ldflags "-linkmode external -extldflags \"-static -L /usr/lib -ltensorflow\" -s -w -X main.version=${BUILD_ID}" -o "${BUILD_NAME}" cmd/photoprism/photoprism.go) else - go build -ldflags "-extldflags \"-Wl,-rpath -Wl,\$ORIGIN/../lib\" -s -w -X main.version=${BUILD_ID}" -o $2 cmd/photoprism/photoprism.go - du -h $2 + BUILD_CMD=("$GO_BIN" build -ldflags "-extldflags \"-Wl,-rpath -Wl,\$ORIGIN/../lib\" -s -w -X main.version=${BUILD_ID}" -o "${BUILD_NAME}" cmd/photoprism/photoprism.go) fi +# build binary +echo "photoprism-bin: $BUILD_NAME" +echo "command: ${BUILD_CMD[*]}" +$GO_BIN version +"${BUILD_CMD[@]}" + +# show size +du -h "${BUILD_NAME}" + echo "Done." \ No newline at end of file diff --git a/scripts/dist/cleanup.sh b/scripts/dist/cleanup.sh index 1ed1f1a34..63f7727f0 100755 --- a/scripts/dist/cleanup.sh +++ b/scripts/dist/cleanup.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# abort if the user is not root +# abort if not executed as root if [[ $(id -u) != "0" ]]; then echo "Usage: run ${0##*/} as root" 1>&2 exit 1 diff --git a/scripts/dist/dist-upgrade.sh b/scripts/dist/dist-upgrade.sh index 97272e7fb..4099f9ecf 100755 --- a/scripts/dist/dist-upgrade.sh +++ b/scripts/dist/dist-upgrade.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# abort if the user is not root +# abort if not executed as root if [[ $(id -u) != "0" ]]; then echo "Usage: run ${0##*/} as root" 1>&2 exit 1 diff --git a/scripts/dist/entrypoint-init.sh b/scripts/dist/entrypoint-init.sh new file mode 100755 index 000000000..dc04f4c60 --- /dev/null +++ b/scripts/dist/entrypoint-init.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash + +# INITIALIZES CONTAINER PACKAGES AND PERMISSIONS + +# abort if not executed as root +if [[ $(id -u) != "0" ]]; then + echo "Usage: run ${0##*/} as root" 1>&2 + exit 1 +fi + +# regular expressions +re='^[0-9]+$' + +# detect environment +case $DOCKER_ENV in + prod) + INIT_MAKEFILE="/opt/photoprism/scripts/Makefile" + CHOWN_DIRS=("${PHOTOPRISM_HOME}" "${PHOTOPRISM_DIST}") + CHMOD_DIRS=("${PHOTOPRISM_DIST}") + ;; + + develop) + INIT_MAKEFILE="/go/src/github.com/photoprism/photoprism/scripts/dist/Makefile" + CHOWN_DIRS=("/go /photoprism" "/opt/photoprism" "/tmp/photoprism") + CHMOD_DIRS=("/photoprism" "/opt/photoprism" "/tmp/photoprism") + ;; + + *) + echo "unsupported init environment \"$DOCKER_ENV\""; + exit + ;; +esac + +if [[ ${PHOTOPRISM_UID} =~ $re ]] && [[ ${PHOTOPRISM_UID} != "0" ]]; then + if [[ ${PHOTOPRISM_GID} =~ $re ]] && [[ ${PHOTOPRISM_GID} != "0" ]]; then + groupadd -g "${PHOTOPRISM_GID}" "group_${PHOTOPRISM_GID}" 2>/dev/null + useradd -o -u "${PHOTOPRISM_UID}" -g "${PHOTOPRISM_GID}" -d "${PHOTOPRISM_HOME}" "user_${PHOTOPRISM_UID}" 2>/dev/null + usermod -g "${PHOTOPRISM_GID}" "user_${PHOTOPRISM_UID}" 2>/dev/null + + if [[ -z ${PHOTOPRISM_DISABLE_CHOWN} ]]; then + echo "updating filesystem permissions..." + echo "PHOTOPRISM_DISABLE_CHOWN: \"true\" disables filesystem permission updates" + chown --preserve-root -Rcf "${PHOTOPRISM_UID}:${PHOTOPRISM_GID}" "${CHOWN_DIRS[@]}" + chmod --preserve-root -Rcf u+rwX "${CHMOD_DIRS[@]}" + fi + else + useradd -o -u "${PHOTOPRISM_UID}" -g 1000 -d "${PHOTOPRISM_HOME}" "user_${PHOTOPRISM_UID}" 2>/dev/null + usermod -g 1000 "user_${PHOTOPRISM_UID}" 2>/dev/null + + if [[ -z ${PHOTOPRISM_DISABLE_CHOWN} ]]; then + echo "updating filesystem permissions..." + echo "PHOTOPRISM_DISABLE_CHOWN: \"true\" disables filesystem permission updates" + chown --preserve-root -Rcf "${PHOTOPRISM_UID}" "${CHOWN_DIRS[@]}" + chmod --preserve-root -Rcf u+rwX "${CHMOD_DIRS[@]}" + fi + fi +fi + +# do nothing if PHOTOPRISM_INIT was not set +if [[ -z ${PHOTOPRISM_INIT} ]]; then + exit +fi + +INIT_LOCK="/root/.init-lock" + +# execute targets via make +if [[ ! -e ${INIT_LOCK} ]]; then + + + for INIT_TARGET in $PHOTOPRISM_INIT; do + echo "init $INIT_TARGET..." + make -f "$INIT_MAKEFILE" "$INIT_TARGET}" + done + + echo 1 >${INIT_LOCK} +fi diff --git a/scripts/dist/entrypoint.sh b/scripts/dist/entrypoint.sh index 4d25e54e4..d5df5af1f 100755 --- a/scripts/dist/entrypoint.sh +++ b/scripts/dist/entrypoint.sh @@ -1,28 +1,68 @@ #!/usr/bin/env bash -DOCKER_ARCH=${DOCKER_ARCH:-arch} -DOCKER_ENV=${DOCKER_ENV:-unknown} -DOCKER_TAG=${DOCKER_TAG:-unknown} +# regular expressions +re='^[0-9]+$' -if [[ $(id -u) == "0" ]]; then - echo "started as root" +# set env defaults +export DOCKER_ARCH=${DOCKER_ARCH:-arch} +export DOCKER_ENV=${DOCKER_ENV:-unknown} +export DOCKER_TAG=${DOCKER_TAG:-unknown} - if [[ ! -e /opt/photoprism/.init ]] && [[ ${PHOTOPRISM_INIT} ]]; then - for target in $PHOTOPRISM_INIT; do - echo "init ${target}..." - make -f /opt/photoprism/scripts/Makefile "${target}" - done - echo 1 >/opt/photoprism/.init +# detect environment +case $DOCKER_ENV in + prod) + INIT_SCRIPT="/opt/photoprism/scripts/entrypoint-init.sh" + ;; + + develop) + INIT_SCRIPT="/go/src/github.com/photoprism/photoprism/scripts/dist/entrypoint-init.sh" + ;; + + *) + INIT_SCRIPT="" + echo "unknown environment \"$DOCKER_ENV\""; + ;; +esac + +# set home and install path defaults +export PHOTOPRISM_HOME=${PHOTOPRISM_HOME:-/photoprism} +export PHOTOPRISM_DIST=${PHOTOPRISM_DIST:-/opt/photoprism} + +# normalize user and group ID environment variables +if [[ -z ${PHOTOPRISM_UID} ]]; then + if [[ ${UID} =~ $re ]] && [[ ${UID} != "0" ]]; then + export PHOTOPRISM_UID=${UID} + elif [[ ${PUID} =~ $re ]] && [[ ${PUID} != "0" ]]; then + export PHOTOPRISM_UID=${PUID} + fi + if [[ -z ${PHOTOPRISM_GID} ]]; then + if [[ ${GID} =~ $re ]] && [[ ${GID} != "0" ]]; then + export PHOTOPRISM_GID=${GID} + elif [[ ${PGID} =~ $re ]] && [[ ${PGID} != "0" ]]; then + export PHOTOPRISM_GID=${PGID} + fi + fi +fi + +# initialize container packages and permissions +if [[ -f "${INIT_SCRIPT}" ]]; then + if [[ $(id -u) == "0" ]]; then + echo "init as root" + bash -c "${INIT_SCRIPT}" + else + echo "init as uid $(id -u)" + sudo -E "${INIT_SCRIPT}" fi else echo "started as uid $(id -u)" fi -re='^[0-9]+$' +# set explicit home directory +export HOME="${PHOTOPRISM_HOME}" # check for alternate umask variable if [[ -z ${PHOTOPRISM_UMASK} ]] && [[ ${UMASK} =~ $re ]] && [[ ${#UMASK} == 4 ]]; then - PHOTOPRISM_UMASK=${UMASK} + export PHOTOPRISM_UMASK=${UMASK} fi # set file-creation mode (umask) @@ -32,78 +72,37 @@ else umask 0002 fi -# show info -echo "image: $DOCKER_ARCH-$DOCKER_ENV" -echo "build: $DOCKER_TAG" +# show container info +echo "image: $DOCKER_ARCH-$DOCKER_ENV, build $DOCKER_TAG" +echo "home: ${PHOTOPRISM_HOME}" echo "umask: \"$(umask)\" ($(umask -S))" +echo "install-path: ${PHOTOPRISM_DIST}" -# script must run as root to perform changes -if [[ $(id -u) == "0" ]]; then - # check for alternate user ID env variables - if [[ -z ${PHOTOPRISM_UID} ]]; then - if [[ ${UID} =~ $re ]] && [[ ${UID} != "0" ]]; then - PHOTOPRISM_UID=${UID} - elif [[ ${PUID} =~ $re ]] && [[ ${PUID} != "0" ]]; then - PHOTOPRISM_UID=${PUID} - fi - fi - - # check for alternate group ID env variables - if [[ -z ${PHOTOPRISM_GID} ]]; then - if [[ ${GID} =~ $re ]] && [[ ${GID} != "0" ]]; then - PHOTOPRISM_GID=${GID} - elif [[ ${PGID} =~ $re ]] && [[ ${PGID} != "0" ]]; then - PHOTOPRISM_GID=${PGID} - fi - fi - +# change to another user and group on request +if [[ $(id -u) == "0" ]] && [[ ${PHOTOPRISM_UID} =~ $re ]] && [[ ${PHOTOPRISM_UID} != "0" ]]; then # check uid and gid env variables - if [[ ${PHOTOPRISM_UID} =~ $re ]] && [[ ${PHOTOPRISM_UID} != "0" ]] && [[ ${PHOTOPRISM_GID} =~ $re ]] && [[ ${PHOTOPRISM_GID} != "0" ]]; then - # RUN AS SPECIFIED USER + GROUP ID - groupadd -g "${PHOTOPRISM_GID}" "group_${PHOTOPRISM_GID}" 2>/dev/null - useradd -o -u "${PHOTOPRISM_UID}" -g "${PHOTOPRISM_GID}" -d /photoprism "user_${PHOTOPRISM_UID}" 2>/dev/null - usermod -g "${PHOTOPRISM_GID}" "user_${PHOTOPRISM_UID}" 2>/dev/null - - if [[ -z ${PHOTOPRISM_DISABLE_CHOWN} ]]; then - echo "updating filesystem permissions..." - echo "PHOTOPRISM_DISABLE_CHOWN: \"true\" disables filesystem permission updates" - chown --preserve-root -Rcf "${PHOTOPRISM_UID}:${PHOTOPRISM_GID}" /photoprism /opt/photoprism - chmod --preserve-root -Rcf u+rwX /photoprism /opt/photoprism - fi - + if [[ ${PHOTOPRISM_GID} =~ $re ]] && [[ ${PHOTOPRISM_GID} != "0" ]]; then echo "switching to uid ${PHOTOPRISM_UID}:${PHOTOPRISM_GID}" echo "${@}" - gosu "${PHOTOPRISM_UID}:${PHOTOPRISM_GID}" audit.sh && gosu "${PHOTOPRISM_UID}:${PHOTOPRISM_GID}" "$@" & - elif [[ ${PHOTOPRISM_UID} =~ $re ]] && [[ ${PHOTOPRISM_UID} != "0" ]]; then - # RUN AS SPECIFIED USER ID - useradd -o -u "${PHOTOPRISM_UID}" -g 1000 -d /photoprism "user_${PHOTOPRISM_UID}" 2>/dev/null - usermod -g 1000 "user_${PHOTOPRISM_UID}" 2>/dev/null - - if [[ -z ${PHOTOPRISM_DISABLE_CHOWN} ]]; then - echo "updating filesystem permissions..." - echo "PHOTOPRISM_DISABLE_CHOWN: \"true\" disables filesystem permission updates" - chown --preserve-root -Rcf "${PHOTOPRISM_UID}" /photoprism /opt/photoprism - chmod --preserve-root -Rcf u+rwX /photoprism /opt/photoprism - fi - + # run command as uid:gid + ([[ ${DOCKER_ENV} != "prod" ]] || gosu "${PHOTOPRISM_UID}:${PHOTOPRISM_GID}" audit.sh) \ + && gosu "${PHOTOPRISM_UID}:${PHOTOPRISM_GID}" "$@" & + else echo "switching to uid ${PHOTOPRISM_UID}" echo "${@}" - gosu "${PHOTOPRISM_UID}" audit.sh && gosu "${PHOTOPRISM_UID}" "$@" & - else - # RUN AS ROOT - echo "running as root" - echo "${@}" - - audit.sh && "$@" & + # run command as uid + ([[ ${DOCKER_ENV} != "prod" ]] || gosu "${PHOTOPRISM_UID}" audit.sh) \ + && gosu "${PHOTOPRISM_UID}" "$@" & fi else - # RUN AS NON-ROOT USER echo "running as uid $(id -u)" echo "${@}" - audit.sh && "$@" & + # run command + ([[ ${DOCKER_ENV} != "prod" ]] || audit.sh) \ + && "$@" & fi PID=$! diff --git a/scripts/dist/install-chrome.sh b/scripts/dist/install-chrome.sh index a1a512e07..5d3422769 100755 --- a/scripts/dist/install-chrome.sh +++ b/scripts/dist/install-chrome.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# abort if the user is not root +# abort if not executed as root if [[ $(id -u) != "0" ]]; then echo "Usage: run ${0##*/} as root" 1>&2 exit 1 diff --git a/scripts/dist/install-darktable.sh b/scripts/dist/install-darktable.sh index 5f30315cc..ded94b241 100755 --- a/scripts/dist/install-darktable.sh +++ b/scripts/dist/install-darktable.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# abort if the user is not root +# abort if not executed as root if [[ $(id -u) != "0" ]]; then echo "Usage: run ${0##*/} as root" 1>&2 exit 1 diff --git a/scripts/dist/install-davfs.sh b/scripts/dist/install-davfs.sh index 98d04e34a..9b5bd2474 100755 --- a/scripts/dist/install-davfs.sh +++ b/scripts/dist/install-davfs.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# abort if the user is not root +# abort if not executed as root if [[ $(id -u) != "0" ]]; then echo "Usage: run ${0##*/} as root" 1>&2 exit 1 diff --git a/scripts/dist/install-go.sh b/scripts/dist/install-go.sh index 1e93d9c58..7698784f3 100755 --- a/scripts/dist/install-go.sh +++ b/scripts/dist/install-go.sh @@ -4,7 +4,7 @@ GOLANG_VERSION=1.17.7 DESTDIR=$(realpath "${1:-/usr/local}") -# abort if the user is not root +# abort if not executed as root if [[ $(id -u) != "0" ]]; then echo "Usage: run ${0##*/} as root" 1>&2 exit 1 diff --git a/scripts/dist/install-gpu.sh b/scripts/dist/install-gpu.sh index 20257109b..1f8d2a44c 100755 --- a/scripts/dist/install-gpu.sh +++ b/scripts/dist/install-gpu.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# abort if the user is not root +# abort if not executed as root if [[ $(id -u) != "0" ]]; then echo "Error: Run ${0##*/} as root" 1>&2 exit 1 diff --git a/scripts/dist/install-mariadb.sh b/scripts/dist/install-mariadb.sh index 71e399492..5409e49dc 100755 --- a/scripts/dist/install-mariadb.sh +++ b/scripts/dist/install-mariadb.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# abort if the user is not root +# abort if not executed as root if [[ $(id -u) != "0" ]]; then echo "Usage: run ${0##*/} as root" 1>&2 exit 1 diff --git a/scripts/dist/install-nodejs.sh b/scripts/dist/install-nodejs.sh index a4481570a..2d9060ba0 100755 --- a/scripts/dist/install-nodejs.sh +++ b/scripts/dist/install-nodejs.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# abort if the user is not root +# abort if not executed as root if [[ $(id -u) != "0" ]]; then echo "Usage: run ${0##*/} as root" 1>&2 exit 1 diff --git a/scripts/dist/install-tensorflow.sh b/scripts/dist/install-tensorflow.sh index 9f0e82f0f..c130cdc75 100755 --- a/scripts/dist/install-tensorflow.sh +++ b/scripts/dist/install-tensorflow.sh @@ -16,7 +16,7 @@ fi TMPDIR=${TMPDIR:-/tmp} -# abort if the user is not root +# abort if not executed as root if [[ $(id -u) != "0" ]] && [[ $DESTDIR == "/usr" || $DESTDIR == "/usr/local" ]]; then echo "Error: Run ${0##*/} as root to install in a system directory!" 1>&2 exit 1