Set up docker image

This commit is contained in:
Alan Grainger
2025-08-06 21:04:36 +02:00
parent f89d112973
commit c8ab2c6f98
13 changed files with 107 additions and 20 deletions
+1
View File
@@ -0,0 +1 @@
/app/node_modules/
+58
View File
@@ -0,0 +1,58 @@
name: Publish docker image
on:
workflow_dispatch:
push:
tags:
- 'v*'
env:
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Get version from package.json
run: echo "PACKAGE_VERSION=$(jq -r '.version' app/package.json)" >> $GITHUB_ENV
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3.2.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: Dockerfile
push: true
platforms: linux/amd64,linux/arm64,linux/arm/v7
build-args: |
PACKAGE_VERSION=${{ env.PACKAGE_VERSION }}
tags: |
${{ github.repository }}:${{ env.PACKAGE_VERSION }}
${{ github.repository }}:latest
ghcr.io/${{ github.repository }}:${{ env.PACKAGE_VERSION }}
ghcr.io/${{ github.repository }}:latest
+1 -1
View File
@@ -1,5 +1,5 @@
.idea/ .idea/
.env .env
node_modules/ node_modules/
/data/
config.json config.json
store.json
+22
View File
@@ -0,0 +1,22 @@
FROM node:lts-alpine AS builder
USER node
WORKDIR /app
COPY --chown=node:node app/ ./
RUN npm ci \
&& npx tsc
FROM node:lts-alpine AS runner
USER node
WORKDIR /app
COPY --from=builder --chown=node:node app/ ./
RUN npm ci --omit=dev
ARG PACKAGE_VERSION
ENV APP_VERSION=${PACKAGE_VERSION}
ENV NODE_ENV=production
CMD ["node", "dist/index.js" ]
+10 -13
View File
@@ -10,7 +10,7 @@
"license": "AGPL-3.0", "license": "AGPL-3.0",
"dependencies": { "dependencies": {
"@immich/sdk": "^1.137.3", "@immich/sdk": "^1.137.3",
"dotenv": "^16.4.5", "node-cron": "^4.2.1",
"tslib": "^2.8.1" "tslib": "^2.8.1"
}, },
"bin": { "bin": {
@@ -1078,18 +1078,6 @@
"node": ">=6.0.0" "node": ">=6.0.0"
} }
}, },
"node_modules/dotenv": {
"version": "16.6.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/dunder-proto": { "node_modules/dunder-proto": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -2929,6 +2917,15 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/node-cron": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/node-cron/-/node-cron-4.2.1.tgz",
"integrity": "sha512-lgimEHPE/QDgFlywTd8yTR61ptugX3Qer29efeyWw2rv259HtGBNn1vZVmp8lB9uo9wC0t/AT4iGqXxia+CJFg==",
"license": "ISC",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/object-inspect": { "node_modules/object-inspect": {
"version": "1.13.4", "version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+3 -2
View File
@@ -4,6 +4,7 @@
"scripts": { "scripts": {
"dev": "ts-node src/index.ts", "dev": "ts-node src/index.ts",
"build": "npx tsc", "build": "npx tsc",
"test": "podman build --build-arg PACKAGE_VERSION=$(npm pkg get version | xargs) --format docker -t immich-person-test .. && podman run --init -it -p=3000:3000 -v ../data:/data:Z --restart=always immich-person-test",
"start": "node dist/index.js" "start": "node dist/index.js"
}, },
"author": "Alan Grainger", "author": "Alan Grainger",
@@ -17,8 +18,8 @@
"bin": "dist/index.js", "bin": "dist/index.js",
"dependencies": { "dependencies": {
"tslib": "^2.8.1", "tslib": "^2.8.1",
"dotenv": "^16.4.5", "@immich/sdk": "^1.137.3",
"@immich/sdk": "^1.137.3" "node-cron": "^4.2.1"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^16.18.111", "@types/node": "^16.18.111",
+2 -3
View File
@@ -1,8 +1,7 @@
import { Link, Config } from './types' import { Link, Config } from './types'
import { addAssetsToAlbum, searchAssets } from '@immich/sdk' import { addAssetsToAlbum, searchAssets } from '@immich/sdk'
import store from './store' import store from './store'
import path from 'path'
// require('dotenv').config()
export class PersonToAlbum { export class PersonToAlbum {
config: Config config: Config
@@ -20,7 +19,7 @@ export class PersonToAlbum {
// Attempt to parse docker-compose config string into JSON (if specified) // Attempt to parse docker-compose config string into JSON (if specified)
this.config = JSON.parse(process.env.CONFIG) this.config = JSON.parse(process.env.CONFIG)
} else { } else {
const configJson = require('../config.json') const configJson = require(path.resolve('../data/config.json'))
if (typeof configJson === 'object') this.config = configJson if (typeof configJson === 'object') this.config = configJson
} }
} catch (e) { } catch (e) {
View File
+1 -1
View File
@@ -7,7 +7,7 @@ export class JSONKeyValueStore<T = any> {
cache: Map<string, T> cache: Map<string, T>
constructor () { constructor () {
this.filePath = path.resolve('./data/store.json') this.filePath = path.resolve('../data/store.json')
this.cache = new Map<string, T>() this.cache = new Map<string, T>()
try { try {
const data = fs.readFileSync(this.filePath, 'utf8') const data = fs.readFileSync(this.filePath, 'utf8')
View File
View File
+9
View File
@@ -0,0 +1,9 @@
services:
immich-person-to-album:
image: alangrainger/immich-person-to-album:latest
container_name: immich-person-to-album
restart: always
ports:
- "3000:3000"
volumes:
- ./data:/data