mirror of
https://github.com/immich-app/immich.git
synced 2025-01-28 06:32:44 +01:00
feat: docker compose builder
This commit is contained in:
parent
34ce61d03a
commit
6213617968
19 changed files with 6167 additions and 2 deletions
10
docker/.gitignore
vendored
10
docker/.gitignore
vendored
|
@ -1 +1,9 @@
|
||||||
.env
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
/build
|
||||||
|
/.svelte-kit
|
||||||
|
/dist
|
||||||
|
/package
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
|
1
docker/.npmrc
Normal file
1
docker/.npmrc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
engine-strict=true
|
1
docker/.nvmrc
Normal file
1
docker/.nvmrc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
22.11.0
|
14
docker/.prettierignore
Normal file
14
docker/.prettierignore
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
/build
|
||||||
|
/package
|
||||||
|
/coverage
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
*.md
|
||||||
|
|
||||||
|
# Ignore files for PNPM, NPM and YARN
|
||||||
|
pnpm-lock.yaml
|
||||||
|
package-lock.json
|
||||||
|
yarn.lock
|
9
docker/.prettierrc
Normal file
9
docker/.prettierrc
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"jsonRecursiveSort": true,
|
||||||
|
"organizeImportsSkipDestructiveCodeActions": true,
|
||||||
|
"plugins": ["prettier-plugin-organize-imports", "prettier-plugin-sort-json"],
|
||||||
|
"printWidth": 120,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "all"
|
||||||
|
}
|
86
docker/eslint.config.mjs
Normal file
86
docker/eslint.config.mjs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
import { FlatCompat } from '@eslint/eslintrc';
|
||||||
|
import js from '@eslint/js';
|
||||||
|
import typescriptEslint from '@typescript-eslint/eslint-plugin';
|
||||||
|
import tsParser from '@typescript-eslint/parser';
|
||||||
|
import globals from 'globals';
|
||||||
|
import path from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
const compat = new FlatCompat({
|
||||||
|
baseDirectory: __dirname,
|
||||||
|
recommendedConfig: js.configs.recommended,
|
||||||
|
allConfig: js.configs.all,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
ignores: [
|
||||||
|
'**/.DS_Store',
|
||||||
|
'**/node_modules',
|
||||||
|
'dist',
|
||||||
|
'lib/docker-compose/types.ts',
|
||||||
|
'build',
|
||||||
|
'package',
|
||||||
|
'**/.env',
|
||||||
|
'**/.env.*',
|
||||||
|
'!**/.env.example',
|
||||||
|
'**/pnpm-lock.yaml',
|
||||||
|
'**/package-lock.json',
|
||||||
|
'**/yarn.lock',
|
||||||
|
'eslint.config.mjs',
|
||||||
|
'vite.config.js',
|
||||||
|
'coverage',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
...compat.extends('eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:unicorn/recommended'),
|
||||||
|
{
|
||||||
|
ignores: ['src/**'],
|
||||||
|
plugins: {
|
||||||
|
'@typescript-eslint': typescriptEslint,
|
||||||
|
},
|
||||||
|
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.browser,
|
||||||
|
...globals.node,
|
||||||
|
NodeJS: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
parser: tsParser,
|
||||||
|
ecmaVersion: 2022,
|
||||||
|
sourceType: 'module',
|
||||||
|
|
||||||
|
parserOptions: {
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
project: ['./tsconfig.json'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-unused-vars': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
argsIgnorePattern: '^_$',
|
||||||
|
varsIgnorePattern: '^_$',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
curly: 2,
|
||||||
|
'unicorn/no-useless-undefined': 'off',
|
||||||
|
'unicorn/prefer-spread': 'off',
|
||||||
|
'unicorn/no-null': 'off',
|
||||||
|
'unicorn/prevent-abbreviations': 'off',
|
||||||
|
'unicorn/no-nested-ternary': 'off',
|
||||||
|
'unicorn/consistent-function-scoping': 'off',
|
||||||
|
'unicorn/prefer-top-level-await': 'off',
|
||||||
|
'unicorn/import-style': 'off',
|
||||||
|
'@typescript-eslint/await-thenable': 'error',
|
||||||
|
'@typescript-eslint/no-floating-promises': 'error',
|
||||||
|
'@typescript-eslint/no-misused-promises': 'error',
|
||||||
|
'@typescript-eslint/require-await': 'error',
|
||||||
|
'object-shorthand': ['error', 'always'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
82
docker/lib/build.ts
Normal file
82
docker/lib/build.ts
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
import { dump as dumpYaml } from 'js-yaml';
|
||||||
|
import { ComposeBuilder, ServiceBuilder } from 'lib/docker-compose/builder';
|
||||||
|
import { GeneratorOptions } from 'lib/types';
|
||||||
|
import { asQueryParams, getImmichEnvironment, getImmichVolumes, isExternalDatabase, isExternalRedis } from 'lib/utils';
|
||||||
|
|
||||||
|
const RELEASE_VERSION = 'v1.122.0';
|
||||||
|
const postgresHealthCheck = [
|
||||||
|
'pg_isready --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" || exit 1;',
|
||||||
|
`Chksum="$$(psql --dbname="$\${POSTGRES_DB}" --username="$\${POSTGRES_USER}" --tuples-only --no-align`,
|
||||||
|
`--command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')";`,
|
||||||
|
'echo "checksum failure count is $$Chksum";',
|
||||||
|
`[ "$$Chksum" = '0' ] || exit 1\n`,
|
||||||
|
].join(' ');
|
||||||
|
const postgresCommand = [
|
||||||
|
`postgres`,
|
||||||
|
`-c shared_preload_libraries=vectors.so`,
|
||||||
|
`-c 'search_path="$$user", public, vectors'`,
|
||||||
|
`-c logging_collector=on`,
|
||||||
|
`-c max_wal_size=2GB`,
|
||||||
|
`-c shared_buffers=512MB`,
|
||||||
|
`-c wal_compression=on`,
|
||||||
|
].join(' ');
|
||||||
|
|
||||||
|
const build = (options: GeneratorOptions) => {
|
||||||
|
const healthchecksEnabled = options.healthchecks;
|
||||||
|
|
||||||
|
const immichService = ServiceBuilder.create('immich-server')
|
||||||
|
.setImage(`ghcr.io/immich-app/immich-server:${RELEASE_VERSION}`)
|
||||||
|
.setRestartPolicy('always')
|
||||||
|
.setHealthcheck(healthchecksEnabled)
|
||||||
|
.setEnvironment(getImmichEnvironment(options))
|
||||||
|
.addExposedPort(2283)
|
||||||
|
.addVolumes(getImmichVolumes(options));
|
||||||
|
|
||||||
|
const machineLearningEnabled = options.machineLearning;
|
||||||
|
const modelCacheVolume = 'model-cache';
|
||||||
|
const machineLearningService =
|
||||||
|
machineLearningEnabled &&
|
||||||
|
ServiceBuilder.create('immich-machine-learning')
|
||||||
|
.setImage(`ghcr.io/immich-app/immich-machine-learning:${RELEASE_VERSION}-cuda`)
|
||||||
|
.setRestartPolicy('always')
|
||||||
|
.setHealthcheck(healthchecksEnabled)
|
||||||
|
.addVolume(`${modelCacheVolume}:/cache`);
|
||||||
|
|
||||||
|
const redisService = isExternalRedis(options)
|
||||||
|
? false
|
||||||
|
: ServiceBuilder.create('redis')
|
||||||
|
.setImage('docker.io/redis:6.2-alpine')
|
||||||
|
.setRestartPolicy('always')
|
||||||
|
.setHealthcheck(healthchecksEnabled && 'redis-cli ping || exit 1');
|
||||||
|
|
||||||
|
const databaseService = isExternalDatabase(options)
|
||||||
|
? false
|
||||||
|
: ServiceBuilder.create('database')
|
||||||
|
.setImage('docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0')
|
||||||
|
.setRestartPolicy('always')
|
||||||
|
.setEnvironment({
|
||||||
|
POSTGRES_PASSWORD: options.databasePassword,
|
||||||
|
POSTGRES_USER: options.databaseUser,
|
||||||
|
POSTGRES_DB: options.databaseName,
|
||||||
|
POSTGRES_INITDB_ARGS: '--data-checksums',
|
||||||
|
})
|
||||||
|
.setHealthcheck(healthchecksEnabled && postgresHealthCheck)
|
||||||
|
.setCommand(postgresCommand)
|
||||||
|
.addVolume(`${options.databaseLocation}:/var/lib/postgresql/data`);
|
||||||
|
|
||||||
|
const domain = 'https://get.immich.app';
|
||||||
|
const url = `${domain}/compose?${asQueryParams(options)}`;
|
||||||
|
|
||||||
|
return ComposeBuilder.create('immich')
|
||||||
|
.addComment(`This docker compose file was originally generated by https://get.immich.app/compose`)
|
||||||
|
.addComment(url)
|
||||||
|
.addComment(`${dumpYaml({ options }, { indent: 2 })}`)
|
||||||
|
.addService(immichService.addDependsOn(redisService).addDependsOn(databaseService))
|
||||||
|
.addService(machineLearningService)
|
||||||
|
.addService(redisService)
|
||||||
|
.addService(databaseService)
|
||||||
|
.addVolume(modelCacheVolume, machineLearningEnabled && {});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const buildSpec = (options: GeneratorOptions) => build(options).asSpec();
|
||||||
|
export const buildYaml = (options: GeneratorOptions) => build(options).asYaml();
|
198
docker/lib/docker-compose/builder.ts
Normal file
198
docker/lib/docker-compose/builder.ts
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
import { dump as dumpYaml } from 'js-yaml';
|
||||||
|
import {
|
||||||
|
Command,
|
||||||
|
ComposeSpecification,
|
||||||
|
DefinitionsService,
|
||||||
|
DefinitionsVolume,
|
||||||
|
ListOfStrings,
|
||||||
|
} from 'lib/docker-compose/types';
|
||||||
|
|
||||||
|
type ServiceNameAccessor = { getName: () => string };
|
||||||
|
type ServiceBuildAccessor = { build: () => DefinitionsService };
|
||||||
|
|
||||||
|
const withNewLines = (yaml: string) =>
|
||||||
|
yaml.replaceAll(/(?<leading>[^:]\n)(?<key>[ ]{0,2}\S+:)$/gm, '$<leading>\n$<key>');
|
||||||
|
|
||||||
|
export class ComposeBuilder {
|
||||||
|
private spec: ComposeSpecification = {};
|
||||||
|
private comments: string[] = [];
|
||||||
|
|
||||||
|
private constructor(projectName?: string) {
|
||||||
|
if (projectName) {
|
||||||
|
this.setProjectName(projectName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static create(projectName?: string) {
|
||||||
|
return new ComposeBuilder(projectName);
|
||||||
|
}
|
||||||
|
|
||||||
|
setProjectName(name: string) {
|
||||||
|
this.spec.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addComment(comment: string) {
|
||||||
|
this.comments.push(comment + '\n');
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addService(spec: false | (ServiceNameAccessor & ServiceBuildAccessor)) {
|
||||||
|
if (!spec) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.spec.services) {
|
||||||
|
this.spec.services = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.spec.services[spec.getName()] = spec.build();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addVolume(name: string, volume: false | DefinitionsVolume) {
|
||||||
|
if (volume === false) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.spec.volumes) {
|
||||||
|
this.spec.volumes = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.spec.volumes[name] = volume;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
asSpec() {
|
||||||
|
return this.spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
asYaml() {
|
||||||
|
let prefix = '';
|
||||||
|
if (this.comments.length > 0) {
|
||||||
|
const comments =
|
||||||
|
this.comments
|
||||||
|
.flatMap((comment) => comment.split('\n'))
|
||||||
|
.join('\n')
|
||||||
|
.trim()
|
||||||
|
.split('\n')
|
||||||
|
.map((comment) => `# ${comment}`)
|
||||||
|
.join('\n') + '\n\n';
|
||||||
|
|
||||||
|
prefix += comments;
|
||||||
|
}
|
||||||
|
|
||||||
|
const spec = withNewLines(dumpYaml(this.spec, { indent: 2, lineWidth: 140 })).trim();
|
||||||
|
|
||||||
|
return prefix + spec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ServiceBuilder {
|
||||||
|
private spec: DefinitionsService = {};
|
||||||
|
|
||||||
|
private constructor(private name: string) {}
|
||||||
|
|
||||||
|
static create(name: string) {
|
||||||
|
return new ServiceBuilder(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
setImage(image: string) {
|
||||||
|
this.spec.image = image;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addExposedPort(port: number | { internal: number; external: number }) {
|
||||||
|
if (typeof port === 'number') {
|
||||||
|
port = { internal: port, external: port };
|
||||||
|
}
|
||||||
|
|
||||||
|
const { internal, external } = port;
|
||||||
|
|
||||||
|
if (!this.spec.ports) {
|
||||||
|
this.spec.ports = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.spec.ports.push(`${external}:${internal}`);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addDependsOn(service: false | string | ServiceNameAccessor) {
|
||||||
|
if (service === false) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
let serviceName = service as string;
|
||||||
|
if ('getName' in (service as ServiceNameAccessor)) {
|
||||||
|
serviceName = (service as ServiceNameAccessor).getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.spec.depends_on) {
|
||||||
|
this.spec.depends_on = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
(this.spec.depends_on as ListOfStrings).push(serviceName);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRestartPolicy(restart: string) {
|
||||||
|
this.spec.restart = restart;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
setEnvironment(env: Record<string, string | number | undefined>) {
|
||||||
|
this.spec.environment = env;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
setHealthcheck(test: boolean | string) {
|
||||||
|
if (test === true) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test === false) {
|
||||||
|
this.spec.healthcheck = { disable: true };
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.spec.healthcheck = { test };
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCommand(command: Command) {
|
||||||
|
this.spec.command = command;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addVolume(volume: string) {
|
||||||
|
if (!this.spec.volumes) {
|
||||||
|
this.spec.volumes = [];
|
||||||
|
}
|
||||||
|
this.spec.volumes.push(volume);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addVolumes(volumes: string[]) {
|
||||||
|
for (const volume of volumes) {
|
||||||
|
this.addVolume(volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
return this.spec;
|
||||||
|
}
|
||||||
|
}
|
937
docker/lib/docker-compose/types.ts
Normal file
937
docker/lib/docker-compose/types.ts
Normal file
|
@ -0,0 +1,937 @@
|
||||||
|
export type DefinitionsInclude =
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
path?: StringOrList;
|
||||||
|
env_file?: StringOrList;
|
||||||
|
project_directory?: string;
|
||||||
|
};
|
||||||
|
export type StringOrList = string | ListOfStrings;
|
||||||
|
export type ListOfStrings = string[];
|
||||||
|
export type DefinitionsDevelopment = {
|
||||||
|
watch?: {
|
||||||
|
ignore?: string[];
|
||||||
|
path: string;
|
||||||
|
action: 'rebuild' | 'sync' | 'sync+restart';
|
||||||
|
target?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
} & Development;
|
||||||
|
export type Development = {
|
||||||
|
watch?: {
|
||||||
|
ignore?: string[];
|
||||||
|
path: string;
|
||||||
|
action: 'rebuild' | 'sync' | 'sync+restart';
|
||||||
|
target?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
} | null;
|
||||||
|
export type DefinitionsDeployment = {
|
||||||
|
mode?: string;
|
||||||
|
endpoint_mode?: string;
|
||||||
|
replicas?: number | string;
|
||||||
|
labels?: ListOrDict;
|
||||||
|
rollback_config?: {
|
||||||
|
parallelism?: number | string;
|
||||||
|
delay?: string;
|
||||||
|
failure_action?: string;
|
||||||
|
monitor?: string;
|
||||||
|
max_failure_ratio?: number | string;
|
||||||
|
order?: 'start-first' | 'stop-first';
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
update_config?: {
|
||||||
|
parallelism?: number | string;
|
||||||
|
delay?: string;
|
||||||
|
failure_action?: string;
|
||||||
|
monitor?: string;
|
||||||
|
max_failure_ratio?: number | string;
|
||||||
|
order?: 'start-first' | 'stop-first';
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
resources?: {
|
||||||
|
limits?: {
|
||||||
|
cpus?: number | string;
|
||||||
|
memory?: string;
|
||||||
|
pids?: number | string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
reservations?: {
|
||||||
|
cpus?: number | string;
|
||||||
|
memory?: string;
|
||||||
|
generic_resources?: DefinitionsGenericResources;
|
||||||
|
devices?: DefinitionsDevices;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
restart_policy?: {
|
||||||
|
condition?: string;
|
||||||
|
delay?: string;
|
||||||
|
max_attempts?: number | string;
|
||||||
|
window?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
placement?: {
|
||||||
|
constraints?: string[];
|
||||||
|
preferences?: {
|
||||||
|
spread?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
max_replicas_per_node?: number | string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
} & Deployment;
|
||||||
|
export type ListOrDict =
|
||||||
|
| {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` ".+".
|
||||||
|
*/
|
||||||
|
[k: string]: undefined | string | number | boolean | null;
|
||||||
|
}
|
||||||
|
| string[];
|
||||||
|
export type DefinitionsGenericResources = {
|
||||||
|
discrete_resource_spec?: {
|
||||||
|
kind?: string;
|
||||||
|
value?: number | string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
export type DefinitionsDevices = {
|
||||||
|
capabilities: ListOfStrings;
|
||||||
|
count?: string | number;
|
||||||
|
device_ids?: ListOfStrings;
|
||||||
|
driver?: string;
|
||||||
|
options?: ListOrDict;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
export type Deployment = {
|
||||||
|
mode?: string;
|
||||||
|
endpoint_mode?: string;
|
||||||
|
replicas?: number | string;
|
||||||
|
labels?: ListOrDict;
|
||||||
|
rollback_config?: {
|
||||||
|
parallelism?: number | string;
|
||||||
|
delay?: string;
|
||||||
|
failure_action?: string;
|
||||||
|
monitor?: string;
|
||||||
|
max_failure_ratio?: number | string;
|
||||||
|
order?: 'start-first' | 'stop-first';
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
update_config?: {
|
||||||
|
parallelism?: number | string;
|
||||||
|
delay?: string;
|
||||||
|
failure_action?: string;
|
||||||
|
monitor?: string;
|
||||||
|
max_failure_ratio?: number | string;
|
||||||
|
order?: 'start-first' | 'stop-first';
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
resources?: {
|
||||||
|
limits?: {
|
||||||
|
cpus?: number | string;
|
||||||
|
memory?: string;
|
||||||
|
pids?: number | string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
reservations?: {
|
||||||
|
cpus?: number | string;
|
||||||
|
memory?: string;
|
||||||
|
generic_resources?: DefinitionsGenericResources;
|
||||||
|
devices?: DefinitionsDevices;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
restart_policy?: {
|
||||||
|
condition?: string;
|
||||||
|
delay?: string;
|
||||||
|
max_attempts?: number | string;
|
||||||
|
window?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
placement?: {
|
||||||
|
constraints?: string[];
|
||||||
|
preferences?: {
|
||||||
|
spread?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
max_replicas_per_node?: number | string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
} | null;
|
||||||
|
export type ExtraHosts = {} | string[];
|
||||||
|
export type ServiceConfigOrSecret = (
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
source?: string;
|
||||||
|
target?: string;
|
||||||
|
uid?: string;
|
||||||
|
gid?: string;
|
||||||
|
mode?: number | string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
)[];
|
||||||
|
export type Command = null | string | string[];
|
||||||
|
export type EnvFile =
|
||||||
|
| string
|
||||||
|
| (
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
path: string;
|
||||||
|
format?: string;
|
||||||
|
required?: boolean | string;
|
||||||
|
}
|
||||||
|
)[];
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `PropertiesNetworks`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^[a-zA-Z0-9._-]+$".
|
||||||
|
*/
|
||||||
|
export type DefinitionsNetwork = {
|
||||||
|
name?: string;
|
||||||
|
driver?: string;
|
||||||
|
driver_opts?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string | number;
|
||||||
|
};
|
||||||
|
ipam?: {
|
||||||
|
driver?: string;
|
||||||
|
config?: {
|
||||||
|
subnet?: string;
|
||||||
|
ip_range?: string;
|
||||||
|
gateway?: string;
|
||||||
|
aux_addresses?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
options?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
external?:
|
||||||
|
| boolean
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
name?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
internal?: boolean | string;
|
||||||
|
enable_ipv6?: boolean | string;
|
||||||
|
attachable?: boolean | string;
|
||||||
|
labels?: ListOrDict;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
} & Network;
|
||||||
|
export type Network = {
|
||||||
|
name?: string;
|
||||||
|
driver?: string;
|
||||||
|
driver_opts?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string | number;
|
||||||
|
};
|
||||||
|
ipam?: {
|
||||||
|
driver?: string;
|
||||||
|
config?: {
|
||||||
|
subnet?: string;
|
||||||
|
ip_range?: string;
|
||||||
|
gateway?: string;
|
||||||
|
aux_addresses?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
options?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
external?:
|
||||||
|
| boolean
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
name?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
internal?: boolean | string;
|
||||||
|
enable_ipv6?: boolean | string;
|
||||||
|
attachable?: boolean | string;
|
||||||
|
labels?: ListOrDict;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
} | null;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `PropertiesVolumes`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^[a-zA-Z0-9._-]+$".
|
||||||
|
*/
|
||||||
|
export type DefinitionsVolume = {
|
||||||
|
name?: string;
|
||||||
|
driver?: string;
|
||||||
|
driver_opts?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string | number;
|
||||||
|
};
|
||||||
|
external?:
|
||||||
|
| boolean
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
name?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
labels?: ListOrDict;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
} & Volume;
|
||||||
|
export type Volume = {
|
||||||
|
name?: string;
|
||||||
|
driver?: string;
|
||||||
|
driver_opts?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string | number;
|
||||||
|
};
|
||||||
|
external?:
|
||||||
|
| boolean
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
name?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
labels?: ListOrDict;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
} | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Compose file is a YAML file defining a multi-containers based application.
|
||||||
|
*/
|
||||||
|
export interface ComposeSpecification {
|
||||||
|
/**
|
||||||
|
* declared for backward compatibility, ignored.
|
||||||
|
*/
|
||||||
|
version?: string;
|
||||||
|
/**
|
||||||
|
* define the Compose project name, until user defines one explicitly.
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
/**
|
||||||
|
* compose sub-projects to be included.
|
||||||
|
*/
|
||||||
|
include?: DefinitionsInclude[];
|
||||||
|
services?: PropertiesServices;
|
||||||
|
networks?: PropertiesNetworks;
|
||||||
|
volumes?: PropertiesVolumes;
|
||||||
|
secrets?: PropertiesSecrets;
|
||||||
|
configs?: PropertiesConfigs;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `ComposeSpecification`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
export interface PropertiesServices {
|
||||||
|
[k: string]: DefinitionsService;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `PropertiesServices`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^[a-zA-Z0-9._-]+$".
|
||||||
|
*/
|
||||||
|
export interface DefinitionsService {
|
||||||
|
develop?: DefinitionsDevelopment;
|
||||||
|
deploy?: DefinitionsDeployment;
|
||||||
|
annotations?: ListOrDict;
|
||||||
|
attach?: boolean | string;
|
||||||
|
build?:
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
context?: string;
|
||||||
|
dockerfile?: string;
|
||||||
|
dockerfile_inline?: string;
|
||||||
|
entitlements?: string[];
|
||||||
|
args?: ListOrDict;
|
||||||
|
ssh?: ListOrDict;
|
||||||
|
labels?: ListOrDict;
|
||||||
|
cache_from?: string[];
|
||||||
|
cache_to?: string[];
|
||||||
|
no_cache?: boolean | string;
|
||||||
|
additional_contexts?: ListOrDict;
|
||||||
|
network?: string;
|
||||||
|
pull?: boolean | string;
|
||||||
|
target?: string;
|
||||||
|
shm_size?: number | string;
|
||||||
|
extra_hosts?: ExtraHosts;
|
||||||
|
isolation?: string;
|
||||||
|
privileged?: boolean | string;
|
||||||
|
secrets?: ServiceConfigOrSecret;
|
||||||
|
tags?: string[];
|
||||||
|
ulimits?: Ulimits;
|
||||||
|
platforms?: string[];
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
blkio_config?: {
|
||||||
|
device_read_bps?: BlkioLimit[];
|
||||||
|
device_read_iops?: BlkioLimit[];
|
||||||
|
device_write_bps?: BlkioLimit[];
|
||||||
|
device_write_iops?: BlkioLimit[];
|
||||||
|
weight?: number | string;
|
||||||
|
weight_device?: BlkioWeight[];
|
||||||
|
};
|
||||||
|
cap_add?: string[];
|
||||||
|
cap_drop?: string[];
|
||||||
|
cgroup?: 'host' | 'private';
|
||||||
|
cgroup_parent?: string;
|
||||||
|
command?: Command;
|
||||||
|
configs?: ServiceConfigOrSecret;
|
||||||
|
container_name?: string;
|
||||||
|
cpu_count?: string | number;
|
||||||
|
cpu_percent?: string | number;
|
||||||
|
cpu_shares?: number | string;
|
||||||
|
cpu_quota?: number | string;
|
||||||
|
cpu_period?: number | string;
|
||||||
|
cpu_rt_period?: number | string;
|
||||||
|
cpu_rt_runtime?: number | string;
|
||||||
|
cpus?: number | string;
|
||||||
|
cpuset?: string;
|
||||||
|
credential_spec?: {
|
||||||
|
config?: string;
|
||||||
|
file?: string;
|
||||||
|
registry?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
depends_on?:
|
||||||
|
| ListOfStrings
|
||||||
|
| {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^[a-zA-Z0-9._-]+$".
|
||||||
|
*/
|
||||||
|
[k: string]: {
|
||||||
|
restart?: boolean | string;
|
||||||
|
required?: boolean;
|
||||||
|
condition: 'service_started' | 'service_healthy' | 'service_completed_successfully';
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
device_cgroup_rules?: ListOfStrings;
|
||||||
|
devices?: (
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
source: string;
|
||||||
|
target?: string;
|
||||||
|
permissions?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
)[];
|
||||||
|
dns?: StringOrList;
|
||||||
|
dns_opt?: string[];
|
||||||
|
dns_search?: StringOrList;
|
||||||
|
domainname?: string;
|
||||||
|
entrypoint?: Command;
|
||||||
|
env_file?: EnvFile;
|
||||||
|
environment?: ListOrDict;
|
||||||
|
expose?: (string | number)[];
|
||||||
|
extends?:
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
service: string;
|
||||||
|
file?: string;
|
||||||
|
};
|
||||||
|
external_links?: string[];
|
||||||
|
extra_hosts?: ExtraHosts;
|
||||||
|
group_add?: (string | number)[];
|
||||||
|
healthcheck?: DefinitionsHealthcheck;
|
||||||
|
hostname?: string;
|
||||||
|
image?: string;
|
||||||
|
init?: boolean | string;
|
||||||
|
ipc?: string;
|
||||||
|
isolation?: string;
|
||||||
|
labels?: ListOrDict;
|
||||||
|
links?: string[];
|
||||||
|
logging?: {
|
||||||
|
driver?: string;
|
||||||
|
options?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string | number | null;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
mac_address?: string;
|
||||||
|
mem_limit?: number | string;
|
||||||
|
mem_reservation?: string | number;
|
||||||
|
mem_swappiness?: number | string;
|
||||||
|
memswap_limit?: number | string;
|
||||||
|
network_mode?: string;
|
||||||
|
networks?:
|
||||||
|
| ListOfStrings
|
||||||
|
| {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^[a-zA-Z0-9._-]+$".
|
||||||
|
*/
|
||||||
|
[k: string]: {
|
||||||
|
aliases?: ListOfStrings;
|
||||||
|
ipv4_address?: string;
|
||||||
|
ipv6_address?: string;
|
||||||
|
link_local_ips?: ListOfStrings;
|
||||||
|
mac_address?: string;
|
||||||
|
driver_opts?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string | number;
|
||||||
|
};
|
||||||
|
priority?: number;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
} | null;
|
||||||
|
};
|
||||||
|
oom_kill_disable?: boolean | string;
|
||||||
|
oom_score_adj?: string | number;
|
||||||
|
pid?: string | null;
|
||||||
|
pids_limit?: number | string;
|
||||||
|
platform?: string;
|
||||||
|
ports?: (
|
||||||
|
| number
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
name?: string;
|
||||||
|
mode?: string;
|
||||||
|
host_ip?: string;
|
||||||
|
target?: number | string;
|
||||||
|
published?: string | number;
|
||||||
|
protocol?: string;
|
||||||
|
app_protocol?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
)[];
|
||||||
|
post_start?: DefinitionsServiceHook[];
|
||||||
|
pre_stop?: DefinitionsServiceHook[];
|
||||||
|
privileged?: boolean | string;
|
||||||
|
profiles?: ListOfStrings;
|
||||||
|
pull_policy?: 'always' | 'never' | 'if_not_present' | 'build' | 'missing';
|
||||||
|
read_only?: boolean | string;
|
||||||
|
restart?: string;
|
||||||
|
runtime?: string;
|
||||||
|
scale?: number | string;
|
||||||
|
security_opt?: string[];
|
||||||
|
shm_size?: number | string;
|
||||||
|
secrets?: ServiceConfigOrSecret;
|
||||||
|
sysctls?: ListOrDict;
|
||||||
|
stdin_open?: boolean | string;
|
||||||
|
stop_grace_period?: string;
|
||||||
|
stop_signal?: string;
|
||||||
|
storage_opt?: {
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
tmpfs?: StringOrList;
|
||||||
|
tty?: boolean | string;
|
||||||
|
ulimits?: Ulimits;
|
||||||
|
user?: string;
|
||||||
|
uts?: string;
|
||||||
|
userns_mode?: string;
|
||||||
|
volumes?: (
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
type: string;
|
||||||
|
source?: string;
|
||||||
|
target?: string;
|
||||||
|
read_only?: boolean | string;
|
||||||
|
consistency?: string;
|
||||||
|
bind?: {
|
||||||
|
propagation?: string;
|
||||||
|
create_host_path?: boolean | string;
|
||||||
|
selinux?: 'z' | 'Z';
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
volume?: {
|
||||||
|
nocopy?: boolean | string;
|
||||||
|
subpath?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
tmpfs?: {
|
||||||
|
size?: number | string;
|
||||||
|
mode?: number | string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
)[];
|
||||||
|
volumes_from?: string[];
|
||||||
|
working_dir?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `DefinitionsService`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
export interface Ulimits {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Ulimits`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^[a-z]+$".
|
||||||
|
*/
|
||||||
|
[k: string]:
|
||||||
|
| (number | string)
|
||||||
|
| {
|
||||||
|
hard: number | string;
|
||||||
|
soft: number | string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export interface BlkioLimit {
|
||||||
|
path?: string;
|
||||||
|
rate?: number | string;
|
||||||
|
}
|
||||||
|
export interface BlkioWeight {
|
||||||
|
path?: string;
|
||||||
|
weight?: number | string;
|
||||||
|
}
|
||||||
|
export interface DefinitionsHealthcheck {
|
||||||
|
disable?: boolean | string;
|
||||||
|
interval?: string;
|
||||||
|
retries?: number | string;
|
||||||
|
test?: string | string[];
|
||||||
|
timeout?: string;
|
||||||
|
start_period?: string;
|
||||||
|
start_interval?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `DefinitionsHealthcheck`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
export interface DefinitionsServiceHook {
|
||||||
|
command?: Command;
|
||||||
|
user?: string;
|
||||||
|
privileged?: boolean | string;
|
||||||
|
working_dir?: string;
|
||||||
|
environment?: ListOrDict;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `DefinitionsServiceHook`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
export interface PropertiesNetworks {
|
||||||
|
[k: string]: DefinitionsNetwork;
|
||||||
|
}
|
||||||
|
export interface PropertiesVolumes {
|
||||||
|
[k: string]: DefinitionsVolume;
|
||||||
|
}
|
||||||
|
export interface PropertiesSecrets {
|
||||||
|
[k: string]: DefinitionsSecret;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `PropertiesSecrets`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^[a-zA-Z0-9._-]+$".
|
||||||
|
*/
|
||||||
|
export interface DefinitionsSecret {
|
||||||
|
name?: string;
|
||||||
|
environment?: string;
|
||||||
|
file?: string;
|
||||||
|
external?:
|
||||||
|
| boolean
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
name?: string;
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
labels?: ListOrDict;
|
||||||
|
driver?: string;
|
||||||
|
driver_opts?: {
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `undefined`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^.+$".
|
||||||
|
*/
|
||||||
|
[k: string]: string | number;
|
||||||
|
};
|
||||||
|
template_driver?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `DefinitionsSecret`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
export interface PropertiesConfigs {
|
||||||
|
[k: string]: DefinitionsConfig;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `PropertiesConfigs`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^[a-zA-Z0-9._-]+$".
|
||||||
|
*/
|
||||||
|
export interface DefinitionsConfig {
|
||||||
|
name?: string;
|
||||||
|
content?: string;
|
||||||
|
environment?: string;
|
||||||
|
file?: string;
|
||||||
|
external?:
|
||||||
|
| boolean
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
name?: string;
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
labels?: ListOrDict;
|
||||||
|
template_driver?: string;
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `DefinitionsConfig`'s JSON-Schema definition
|
||||||
|
* via the `patternProperty` "^x-".
|
||||||
|
*/
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
2
docker/lib/index.ts
Normal file
2
docker/lib/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from 'lib/build';
|
||||||
|
export * from 'lib/types';
|
41
docker/lib/types.ts
Normal file
41
docker/lib/types.ts
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
export type BaseOptions = {
|
||||||
|
releaseVersion: string;
|
||||||
|
healthchecks: boolean;
|
||||||
|
machineLearning: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GeneratorOptions = BaseOptions & FolderOptions & DatabaseOptions & RedisOptions;
|
||||||
|
|
||||||
|
export type FolderOptions = {
|
||||||
|
baseLocation: string;
|
||||||
|
encodedVideoLocation?: string;
|
||||||
|
libraryLocation?: string;
|
||||||
|
uploadLocation?: string;
|
||||||
|
profileLocation?: string;
|
||||||
|
thumbnailsLocation?: string;
|
||||||
|
backupsLocation?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DatabaseOptions = InternalDatabaseOptions | ExternalDatabaseOptions;
|
||||||
|
export type InternalDatabaseOptions = {
|
||||||
|
databaseUser: string;
|
||||||
|
databasePassword: string;
|
||||||
|
databaseName: string;
|
||||||
|
databaseLocation: string;
|
||||||
|
};
|
||||||
|
export type ExternalDatabaseOptions = { externalDatabaseUrl: string; databaseVectorExtension?: VectorExtension };
|
||||||
|
|
||||||
|
export type RedisOptions = InternalRedisOptions | ExternalRedisOptions;
|
||||||
|
export type InternalRedisOptions = {
|
||||||
|
redisHost?: string;
|
||||||
|
redisPort?: number;
|
||||||
|
redisDbIndex?: number;
|
||||||
|
redisUsername?: string;
|
||||||
|
redisPassword?: string;
|
||||||
|
redisSocket?: string;
|
||||||
|
};
|
||||||
|
export type ExternalRedisOptions = { externalRedisUrl: string };
|
||||||
|
|
||||||
|
export type VectorExtension = 'pgvector' | 'pgvecto.rs';
|
||||||
|
|
||||||
|
export type HardwareAccelerationPlatform = 'nvenc' | 'quicksync' | 'rkmpp' | 'vappi' | 'vaapi-wsl';
|
78
docker/lib/utils.ts
Normal file
78
docker/lib/utils.ts
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
import {
|
||||||
|
DatabaseOptions,
|
||||||
|
ExternalDatabaseOptions,
|
||||||
|
ExternalRedisOptions,
|
||||||
|
GeneratorOptions,
|
||||||
|
RedisOptions,
|
||||||
|
} from 'lib/types';
|
||||||
|
|
||||||
|
export const isExternalDatabase = (options: DatabaseOptions): options is ExternalDatabaseOptions =>
|
||||||
|
'externalDatabaseUrl' in options;
|
||||||
|
|
||||||
|
export const isExternalRedis = (options: RedisOptions): options is ExternalRedisOptions =>
|
||||||
|
'externalRedisUrl' in options;
|
||||||
|
|
||||||
|
export const asQueryParams = (values: Record<string, string | number | boolean | undefined>) => {
|
||||||
|
return new URLSearchParams(
|
||||||
|
Object.entries(values)
|
||||||
|
.filter(Boolean)
|
||||||
|
.map(([key, value]) => [key, String(value)]),
|
||||||
|
).toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getImmichVolumes = (options: GeneratorOptions) => {
|
||||||
|
const {
|
||||||
|
baseLocation,
|
||||||
|
encodedVideoLocation,
|
||||||
|
uploadLocation,
|
||||||
|
backupsLocation,
|
||||||
|
profileLocation,
|
||||||
|
libraryLocation,
|
||||||
|
thumbnailsLocation,
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
const internalBaseLocation = '/usr/src/app/upload';
|
||||||
|
|
||||||
|
const volumes = [`${baseLocation}:${internalBaseLocation}`];
|
||||||
|
|
||||||
|
for (const { override, folder } of [
|
||||||
|
{ override: encodedVideoLocation, folder: 'encoded-video' },
|
||||||
|
{ override: libraryLocation, folder: 'library' },
|
||||||
|
{ override: uploadLocation, folder: 'upload' },
|
||||||
|
{ override: profileLocation, folder: 'profile' },
|
||||||
|
{ override: thumbnailsLocation, folder: 'thumbs' },
|
||||||
|
{ override: backupsLocation, folder: 'backups' },
|
||||||
|
]) {
|
||||||
|
if (override) {
|
||||||
|
volumes.push(`${override}:${internalBaseLocation}/${folder}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
volumes.push(`/etc/localtime:/etc/localtime:ro`);
|
||||||
|
|
||||||
|
return volumes;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getImmichEnvironment = (options: GeneratorOptions) => {
|
||||||
|
const env: Record<string, string | number | undefined> = {};
|
||||||
|
if (isExternalDatabase(options)) {
|
||||||
|
env.DB_URL = options.externalDatabaseUrl;
|
||||||
|
env.DB_VECTOR_EXTENSION = options.databaseVectorExtension;
|
||||||
|
} else {
|
||||||
|
const { databaseUser, databasePassword, databaseName } = options;
|
||||||
|
env.DB_URL = `postgres://${databaseUser}:${databasePassword}@database:5432/${databaseName}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isExternalRedis(options)) {
|
||||||
|
env.REDIS_URL = options.externalRedisUrl;
|
||||||
|
} else {
|
||||||
|
env.REDIS_HOSTNAME = options.redisHost;
|
||||||
|
env.REDIS_PORT = options.redisPort;
|
||||||
|
env.REDIS_DBINDEX = options.redisDbIndex;
|
||||||
|
env.REDIS_USERNAME = options.redisUsername;
|
||||||
|
env.REDIS_PASSWORD = options.redisPassword;
|
||||||
|
env.REDIS_SOCKET = options.redisSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
return env;
|
||||||
|
};
|
4555
docker/package-lock.json
generated
Normal file
4555
docker/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
38
docker/package.json
Normal file
38
docker/package.json
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"name": "immich-docker",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"description": "A docker-compose generator for Immich",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"build": "vite build",
|
||||||
|
"generate": "npx tsx src/index.ts",
|
||||||
|
"lint": "eslint . --max-warnings 0",
|
||||||
|
"lint:fix": "npm run lint -- --fix",
|
||||||
|
"format": "prettier --check .",
|
||||||
|
"format:fix": "prettier --write ."
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"exports": "./dist/immich-docker.js",
|
||||||
|
"author": "team@immich.app",
|
||||||
|
"private": true,
|
||||||
|
"license": "GNU Affero General Public License version 3",
|
||||||
|
"dependencies": {
|
||||||
|
"js-yaml": "^4.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@eslint/eslintrc": "^3.2.0",
|
||||||
|
"@eslint/js": "^9.16.0",
|
||||||
|
"@types/js-yaml": "^4.0.9",
|
||||||
|
"@types/node": "^22.10.2",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^8.18.0",
|
||||||
|
"@typescript-eslint/parser": "^8.18.0",
|
||||||
|
"eslint-plugin-unicorn": "^56.0.1",
|
||||||
|
"globals": "^15.13.0",
|
||||||
|
"json-schema-to-ts": "^3.1.1",
|
||||||
|
"prettier-plugin-organize-imports": "^4.1.0",
|
||||||
|
"prettier-plugin-sort-json": "^4.0.0",
|
||||||
|
"vite": "^6.0.3",
|
||||||
|
"vitest": "^2.1.8"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
global:
|
global:
|
||||||
scrape_interval: 15s
|
scrape_interval: 15s
|
||||||
evaluation_interval: 15s
|
evaluation_interval: 15s
|
||||||
|
|
||||||
scrape_configs:
|
scrape_configs:
|
||||||
|
|
51
docker/src/index.ts
Normal file
51
docker/src/index.ts
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import { buildYaml, GeneratorOptions } from 'lib/index.ts';
|
||||||
|
|
||||||
|
console.log(process.env.PATH);
|
||||||
|
|
||||||
|
const main = () => {
|
||||||
|
const commonOptions = {
|
||||||
|
baseLocation: '/home/immich',
|
||||||
|
releaseVersion: 'v1.122.0',
|
||||||
|
healthchecks: true,
|
||||||
|
machineLearning: true,
|
||||||
|
// hardwareAcceleration: 'nvenc',
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultOptions: GeneratorOptions = {
|
||||||
|
...commonOptions,
|
||||||
|
databaseName: 'immich',
|
||||||
|
databaseUser: 'postgres',
|
||||||
|
databasePassword: 'postgres',
|
||||||
|
databaseLocation: '/home/immich/database',
|
||||||
|
};
|
||||||
|
|
||||||
|
const splitStorageOptions: GeneratorOptions = {
|
||||||
|
...defaultOptions,
|
||||||
|
thumbnailsLocation: '/home/fast/thumbs',
|
||||||
|
encodedVideoLocation: '/home/fast/encoded-videos',
|
||||||
|
};
|
||||||
|
|
||||||
|
const noHealthchecks: GeneratorOptions = {
|
||||||
|
...defaultOptions,
|
||||||
|
healthchecks: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const externalOptions: GeneratorOptions = {
|
||||||
|
...commonOptions,
|
||||||
|
externalDatabaseUrl: 'postgres://immich:immich@localhost:5432/immich',
|
||||||
|
databaseVectorExtension: 'pgvector',
|
||||||
|
externalRedisUrl: 'redis://database:6379/0',
|
||||||
|
};
|
||||||
|
|
||||||
|
const options = [defaultOptions, splitStorageOptions, noHealthchecks, externalOptions];
|
||||||
|
|
||||||
|
// TODO replace with vitest test files/scripts
|
||||||
|
for (const option of options) {
|
||||||
|
const spec = buildYaml(option);
|
||||||
|
console.log(spec);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
||||||
|
// get.immich.app/install?hardware-acceleration=nvenc&api-port=2283&vector-extension=pgvector&data=/data&thumbs=/thumbs&release-version=1.122.0&database-user=admin&database-password=admin&database-name=immich&no-healthchecks
|
19
docker/tsconfig.json
Normal file
19
docker/tsconfig.json
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowJs": true,
|
||||||
|
"baseUrl": "./",
|
||||||
|
"checkJs": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"module": "es2020",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"outDir": "./dist",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"strict": true,
|
||||||
|
"target": "es2022",
|
||||||
|
"types": []
|
||||||
|
},
|
||||||
|
"include": ["lib"]
|
||||||
|
}
|
25
docker/tsconfig.src.json
Normal file
25
docker/tsconfig.src.json
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"baseUrl": "./",
|
||||||
|
"declaration": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"incremental": true,
|
||||||
|
"jsx": "react",
|
||||||
|
"lib": ["dom", "es2023"],
|
||||||
|
"module": "node16",
|
||||||
|
"moduleResolution": "node16",
|
||||||
|
"outDir": "./dist",
|
||||||
|
"preserveWatchOutput": true,
|
||||||
|
"removeComments": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"strict": true,
|
||||||
|
"target": "es2022"
|
||||||
|
},
|
||||||
|
"include": ["src", "lib"]
|
||||||
|
}
|
20
docker/vite.config.js
Normal file
20
docker/vite.config.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import { resolve } from 'node:path';
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
lib: resolve('lib'),
|
||||||
|
src: resolve('src'),
|
||||||
|
test: resolve('test'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
lib: {
|
||||||
|
entry: resolve(__dirname, 'lib/index.ts'),
|
||||||
|
name: 'immich-docker',
|
||||||
|
// the proper extensions will be added
|
||||||
|
fileName: 'immich-docker',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
Loading…
Reference in a new issue