From 85c1e52b061ea2b4ee24ecca9113922230ca460a Mon Sep 17 00:00:00 2001 From: Googol Lee Date: Mon, 2 Sep 2024 18:35:45 +0200 Subject: [PATCH] Use alpine as base images. (#1033) --- .github/workflows/build.yml | 12 ++-- Dockerfile | 34 +++++----- README.md | 19 +++--- dev-compose.yaml | 5 +- scripts/apt/debian-testing.sources | 13 ---- scripts/apt/default.pref | 11 ---- scripts/install_build_dependencies.sh | 43 ++----------- scripts/install_runtime_dependencies.sh | 13 ++-- scripts/set_compiler_env.sh | 84 ------------------------- 9 files changed, 47 insertions(+), 187 deletions(-) delete mode 100644 scripts/apt/debian-testing.sources delete mode 100644 scripts/apt/default.pref delete mode 100755 scripts/set_compiler_env.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d7601a42..5dd576c5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,14 +1,15 @@ name: Docker builds on: - pull_request: - branches: [master] push: branches: [master] tags: - v* + pull_request: + branches: [master] env: + IS_PUSHING_IMAGES: ${{ github.event_name != 'pull_request' && github.repository == 'photoview/photoview' }} DOCKER_USERNAME: viktorstrate DOCKER_IMAGE: viktorstrate/photoview DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} @@ -20,9 +21,6 @@ jobs: runs-on: ubuntu-latest steps: - - name: Delete huge unnecessary tools folder - run: rm -rf /opt/hostedtoolcache - - name: Checkout uses: actions/checkout@v4 @@ -36,7 +34,7 @@ jobs: uses: docker/setup-buildx-action@v3 - name: Docker Login - if: success() && github.event_name != 'pull_request' && github.repository == 'photoview/photoview' + if: ${{ env.IS_PUSHING_IMAGES == 'true' }} uses: docker/login-action@v3 with: username: ${{ env.DOCKER_USERNAME }} @@ -64,7 +62,7 @@ jobs: context: . platforms: ${{ env.PLATFORMS }} pull: true - push: ${{ github.event_name != 'pull_request' && github.repository == 'photoview/photoview' }} + push: ${{ env.IS_PUSHING_IMAGES }} tags: ${{ steps.docker_meta.outputs.tags }} labels: ${{ steps.docker_meta.outputs.labels }} cache-from: type=gha diff --git a/Dockerfile b/Dockerfile index 36efb44d..15080f9f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ ### Build UI ### -FROM --platform=${BUILDPLATFORM:-linux/amd64} node:18 AS ui +FROM --platform=${BUILDPLATFORM:-linux/amd64} node:18-alpine AS ui # See for details: https://github.com/hadolint/hadolint/wiki/DL4006 -SHELL ["/bin/bash", "-euo", "pipefail", "-c"] +SHELL ["/bin/sh", "-euo", "pipefail", "-c"] ARG REACT_APP_API_ENDPOINT ENV REACT_APP_API_ENDPOINT=${REACT_APP_API_ENDPOINT} @@ -36,11 +36,11 @@ RUN if [ "${BUILD_DATE}" = "undefined" ]; then \ npm run build -- --base=$UI_PUBLIC_URL ### Build API ### -FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.22-bookworm AS api +FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.22-alpine AS api ARG TARGETPLATFORM # See for details: https://github.com/hadolint/hadolint/wiki/DL4006 -SHELL ["/bin/bash", "-euo", "pipefail", "-c"] +SHELL ["/bin/sh", "-euo", "pipefail", "-c"] WORKDIR /app/api @@ -49,43 +49,41 @@ ENV PATH="${GOPATH}/bin:${PATH}" ENV CGO_ENABLED=1 # Download dependencies -COPY scripts/apt/debian-testing.sources /etc/apt/sources.list.d/ -COPY scripts/set_compiler_env.sh /app/scripts/ COPY scripts/install_build_dependencies.sh /app/scripts/ COPY scripts/install_runtime_dependencies.sh /app/scripts/ RUN chmod +x /app/scripts/*.sh \ && /app/scripts/install_build_dependencies.sh \ + && mv $(go env GOPATH)/bin/reflex /usr/bin/ \ && /app/scripts/install_runtime_dependencies.sh COPY api/go.mod api/go.sum /app/api/ -RUN source /app/scripts/set_compiler_env.sh \ - && go env \ +RUN go env \ && go mod download \ # Patch go-face && sed -i 's/-march=native//g' ${GOPATH}/pkg/mod/github.com/!kagami/go-face*/face.go \ # Build dependencies that use CGO - && go install \ - github.com/mattn/go-sqlite3 \ - github.com/Kagami/go-face + && go install github.com/mattn/go-sqlite3 github.com/Kagami/go-face COPY api /app/api -RUN source /app/scripts/set_compiler_env.sh \ - && go build -v -o photoview . +RUN go build -v -o photoview . ### Build release image ### -FROM --platform=${BUILDPLATFORM:-linux/amd64} debian:testing-slim AS release +FROM --platform=${BUILDPLATFORM:-linux/amd64} alpine:latest AS release ARG TARGETPLATFORM # See for details: https://github.com/hadolint/hadolint/wiki/DL4006 -SHELL ["/bin/bash", "-euo", "pipefail", "-c"] +SHELL ["/bin/sh", "-euo", "pipefail", "-c"] COPY scripts/install_runtime_dependencies.sh /app/scripts/ RUN chmod +x /app/scripts/install_runtime_dependencies.sh \ # Create a user to run Photoview server - && groupadd -g 999 photoview \ - && useradd -r -u 999 -g photoview -m photoview \ + && addgroup -g 9999 photoview \ + && adduser -u 9999 -G photoview -D photoview \ # Required dependencies - && /app/scripts/install_runtime_dependencies.sh + && /app/scripts/install_runtime_dependencies.sh \ + # Remove build dependencies and cleanup + && apk cache clean \ + && rm -rf /var/cache/apk/* WORKDIR /home/photoview diff --git a/README.md b/README.md index 23b1cddf..2f82a717 100644 --- a/README.md +++ b/README.md @@ -91,11 +91,11 @@ All the photo galleries can do a lot of what I need, but no single one can do it > `7zz` should be installed in case, you'd like to use it in scope of the backup scenario instead of the default .tar.xz format. Read the comment in the `Makefile`, located on top of the `backup` section for more details. 1. Download the content of the `docker-compose example` folder to the folder on your server, where you expect to host the Photoview internal data (database and cache files). - + Please note that this folder contains 2 versions of the docker-compose file: - `docker-compose.example.yml` - the fully-functional and recommended for the most cases config - `docker-compose.minimal.example.yml` - the minimal and simple config for those, who find the previous one too complex and difficult to understand and manage - + When downloading files, you need to choose only one of them. 2. Rename downloaded files and remove the `example` from their names (so, you need to have `.env`, `docker-compose.yml`, and `Makefile` files). If you choose the `docker-compose.minimal.example.yml` on previous step, make sure to rename it to the `docker-compose.yml`. 3. Open these files in a text editor and read them. Modify where needed according to the documentation comments to properly match your setup. There are comments of 2 types: those, starting with `##`, are explanations and examples, which should not be uncommented; those, starting with `#`, are optional or alternative configuration parts, which might be uncommented in certain circumstances, described in corresponding explanations. It is better to go through the files in the next order: `.env`, `docker-compose.yml`, and `Makefile`. @@ -107,10 +107,12 @@ All the photo galleries can do a lot of what I need, but no single one can do it If command(s) return `Permission denied` error, run them under the user, owning corresponding files and folders. Alternatively, run them adding `sudo ` before the command: this will switch the execution context to `root` user and ask for the root password. You have to have permission to run `sudo` in the system. + NOTE: GID and UID was changed to 9999. If it's different from your local files, please update your files. + If you don't want to give required permissions to `others` group for your files, alternatively, you can: - - create a group on your host with GID=999 and make all the files and folders inside volumes of the `photoview` service being owned by this group; then set the appropriate permissions to the `group` section. - - create on your host a group with GID=999 and a user in this group with UID=999; then change the ownership of all the files and folders inside volumes of the `photoview` service to this user; then set the appropriate permissions to the `user` section. + - create a group on your host with GID=9999 and make all the files and folders inside volumes of the `photoview` service being owned by this group; then set the appropriate permissions to the `group` section. + - create on your host a group with GID=9999 and a user in this group with UID=9999; then change the ownership of all the files and folders inside volumes of the `photoview` service to this user; then set the appropriate permissions to the `user` section. If you configured other mounts with media files from other locations on the host (like HOST_PHOTOVIEW_MEDIA_FAMILY or anything else), you need to run the same commands, as in the `Makefile` `readable` target, for each media root folder on your host manually: copy each command to your shell and replace the variable with the absolute path to an additional media root folder without the trailing `/`. Run both commands for each additional root folder. 5. In case, you don't have `make` installed in your system or don't want to use it for the Photoview management activities, you could use the same commands from the `Makefile` and run them in your shell directly, or create your own scripts. Make sure to apply or replace the variables from your `.env` first in this case. `Makefile` is provided just for your convenience and simplicity, but is optional. @@ -233,8 +235,13 @@ The site can now be accessed at [localhost:1234](http://localhost:1234). ## Set up local development environment +In Linux, we recommend to use [Docker Compose or Docker](https://github.com/googollee/photoview?tab=readme-ov-file#set-up-docker-development-environment) as a local development environment. + +We can't keep verifying below commands on each environment. People may need to solve dependencies by their own. + ### Install dependencies + - API - Required packages: - `golang` >= 1.22 @@ -245,7 +252,7 @@ The site can now be accessed at [localhost:1234](http://localhost:1234). - `dlib` - `libjpeg` - `libblas` - - `libcblas`, recommended using `libatlas-base` + - `libcblas`, recommended using `libatlas-base` in Debian. - `liblapack` - Optional tools during developing: - [`reflex`](https://github.com/cespare/reflex): a source code monitoring tool, which automatically rebuilds and restarts the server, running from the code in development. @@ -297,8 +304,6 @@ You can install `node` with other package manager if you like. Then run the following commands: ```bash -# Optional: Set the compiler environment in Debian/Ubuntu -$ source ./scripts/set_compiler_env.sh # Set the compiler environment with `homebrew` $ export CPLUS_INCLUDE_PATH="$(brew --prefix)/opt/jpeg/include:$(brew --prefix)/opt/dlib/include" $ export LD_LIBRARY_PATH="$(brew --prefix)/opt/jpeg/lib:$(brew --prefix)/opt/dlib/lib" diff --git a/dev-compose.yaml b/dev-compose.yaml index 20150cab..d3678a3e 100644 --- a/dev-compose.yaml +++ b/dev-compose.yaml @@ -13,7 +13,7 @@ services: ports: - 1234:1234 command: - - /bin/bash + - /bin/sh - -c - | npm ci @@ -36,10 +36,9 @@ services: ports: - 4001:4001 command: - - /bin/bash + - /bin/sh - -c - | - source /app/scripts/set_compiler_env.sh reflex -g '*.go' -s -- go run . mariadb: diff --git a/scripts/apt/debian-testing.sources b/scripts/apt/debian-testing.sources deleted file mode 100644 index 34b25445..00000000 --- a/scripts/apt/debian-testing.sources +++ /dev/null @@ -1,13 +0,0 @@ -Types: deb -# http://snapshot.debian.org/archive/debian/20240722T000000Z -URIs: http://deb.debian.org/debian -Suites: testing testing-updates -Components: main -Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg - -Types: deb -# http://snapshot.debian.org/archive/debian-security/20240722T000000Z -URIs: http://deb.debian.org/debian-security -Suites: testing-security -Components: main -Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg diff --git a/scripts/apt/default.pref b/scripts/apt/default.pref deleted file mode 100644 index 270d1029..00000000 --- a/scripts/apt/default.pref +++ /dev/null @@ -1,11 +0,0 @@ -Package: * -Pin: release n=bookworm -Pin-Priority: 700 - -Package: * -Pin: release n=bookworm-updates -Pin-Priority: 700 - -Package: * -Pin: release n=bookworm-security -Pin-Priority: 700 diff --git a/scripts/install_build_dependencies.sh b/scripts/install_build_dependencies.sh index 2e0ca591..81d54aa7 100755 --- a/scripts/install_build_dependencies.sh +++ b/scripts/install_build_dependencies.sh @@ -1,42 +1,11 @@ -#!/bin/bash +#!/bin/sh set -euo pipefail -if [ "$TARGETPLATFORM" == "linux/arm64" ]; then - dpkg --add-architecture arm64 - DEBIAN_ARCH='arm64' -elif [ "$TARGETPLATFORM" == "linux/arm/v6" ] || [ "$TARGETPLATFORM" == "linux/arm/v7" ]; then - dpkg --add-architecture armhf - DEBIAN_ARCH='armhf' -else - dpkg --add-architecture amd64 - DEBIAN_ARCH='amd64' -fi +apk update -apt-get update - -# Install G++/GCC cross compilers -if [ "$DEBIAN_ARCH" == "arm64" ]; then - apt-get install -y \ - g++-aarch64-linux-gnu \ - libc6-dev-arm64-cross -elif [ "$DEBIAN_ARCH" == "armhf" ]; then - apt-get install -y \ - g++-arm-linux-gnueabihf \ - libc6-dev-armhf-cross -else - apt-get install -y \ - g++-x86-64-linux-gnu \ - libc6-dev-amd64-cross -fi - -# Install go-face dependencies and libheif for HEIF media decoding -apt-get install -y \ - libdlib-dev:${DEBIAN_ARCH} \ - libblas-dev:${DEBIAN_ARCH} \ - libatlas-base-dev:${DEBIAN_ARCH} \ - liblapack-dev:${DEBIAN_ARCH} \ - libjpeg-dev:${DEBIAN_ARCH} \ - libheif-dev:${DEBIAN_ARCH} +apk add go g++ blas-dev cblas lapack-dev jpeg-dev libheif-dev +apk add dlib-dev --repository=https://dl-cdn.alpinelinux.org/alpine/edge/testing # Install tools for development -apt-get install -y reflex sqlite3 +apk add sqlite +go install github.com/cespare/reflex@latest diff --git a/scripts/install_runtime_dependencies.sh b/scripts/install_runtime_dependencies.sh index e798b293..ff426429 100755 --- a/scripts/install_runtime_dependencies.sh +++ b/scripts/install_runtime_dependencies.sh @@ -1,10 +1,9 @@ -#!/bin/bash +#!/bin/sh set -euo pipefail -apt-get update -apt-get install -y curl libdlib19.2 ffmpeg exiftool libheif1 imagemagick +apk update -# Remove build dependencies and cleanup -apt-get autoremove -y -apt-get clean -rm -rf /var/lib/apt/lists/* +apk add curl libheif lapack cblas exiftool +apk add ffmpeg ffmpeg-libs ffmpeg-libavcodec ffmpeg-libavformat +apk add imagemagick imagemagick-libs imagemagick-heic imagemagick-jpeg imagemagick-raw imagemagick-tiff imagemagick-webp imagemagick-svg imagemagick-jxl +apk add dlib --repository=https://dl-cdn.alpinelinux.org/alpine/edge/testing diff --git a/scripts/set_compiler_env.sh b/scripts/set_compiler_env.sh deleted file mode 100755 index a7744e6b..00000000 --- a/scripts/set_compiler_env.sh +++ /dev/null @@ -1,84 +0,0 @@ -#!/bin/sh - -# Script to configure environment variables for Go compiler -# to allow cross compilation - -: ${TARGETPLATFORM=} -: ${TARGETOS=} -: ${TARGETARCH=} -: ${TARGETVARIANT=} - -CGO_ENABLED="$(go env CGO_ENABLED)" -GOARCH="$(go env GOARCH)" -GOOS="$(go env GOOS)" -GOARM="$(go env GOARM)" -GOBIN="$(go env GOBIN)" - -set -eu - -if [ ! -z "$TARGETPLATFORM" ]; then - TARGETOS="$(echo $TARGETPLATFORM | cut -d"/" -f1)" - TARGETARCH="$(echo $TARGETPLATFORM | cut -d"/" -f2)" - TARGETVARIANT="$(echo $TARGETPLATFORM | cut -d"/" -f3)" -fi - -if [ ! -z "$TARGETOS" ]; then - export GOOS="$TARGETOS" -fi - -if [ ! -z "$TARGETARCH" ]; then - export GOARCH="$TARGETARCH" -fi - -if [ "$TARGETARCH" = "arm" ]; then - if [ ! -z "$TARGETVARIANT" ]; then - case "$TARGETVARIANT" in - "v5") - export GOARM="5" - ;; - "v6") - export GOARM="6" - ;; - *) - export GOARM="7" - ;; - esac - else - export GOARM="7" - fi -fi - -if [ "$CGO_ENABLED" = "1" ]; then - case "$GOARCH" in - "amd64") - export COMPILER_ARCH="x86_64-linux-gnu" - ;; - "ppc64le") - export COMPILER_ARCH="powerpc64le-linux-gnu" - ;; - "s390x") - export COMPILER_ARCH="s390x-linux-gnu" - ;; - "arm64") - export COMPILER_ARCH="aarch64-linux-gnu" - ;; - "arm") - case "$GOARM" in - "5") - export COMPILER_ARCH="arm-linux-gnueabi" - ;; - *) - export COMPILER_ARCH="arm-linux-gnueabihf" - ;; - esac - ;; - esac -fi - -export CC="${COMPILER_ARCH}-gcc" -export CXX="${COMPILER_ARCH}-g++" -export PKG_CONFIG_PATH="/usr/lib/${COMPILER_ARCH}/pkgconfig/" - -if [ -z "$GOBIN" ] && [ -n "$GOPATH" ] && [ -n "$GOARCH" ] && [ -n "$GOOS" ]; then - export PATH=${GOPATH}/bin/${GOOS}_${GOARCH}:${PATH} -fi