From 441d5a20c1e213b7ad56f2ae14e2fbb8e34ffd3a Mon Sep 17 00:00:00 2001 From: Webber Takken Date: Fri, 19 Apr 2024 01:08:45 +0200 Subject: [PATCH] feat: docker image (#6) * feat: docker image * chore: fix derp --- .cspell.json | 9 +++++ .dockerignore | 14 +++++++ .gitignore | 1 + bun.lockb | Bin 266596 -> 266604 bytes cspell.config.yaml | 8 ---- package.json | 9 +++-- tools/docker/Dockerfile | 80 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 109 insertions(+), 12 deletions(-) create mode 100644 .cspell.json create mode 100644 .dockerignore delete mode 100644 cspell.config.yaml create mode 100644 tools/docker/Dockerfile diff --git a/.cspell.json b/.cspell.json new file mode 100644 index 0000000..52b47a1 --- /dev/null +++ b/.cspell.json @@ -0,0 +1,9 @@ +{ + "version": "0.2", + "ignorePaths": [], + "dictionaryDefinitions": [], + "dictionaries": [], + "words": ["hass"], + "ignoreWords": [], + "import": [] +} diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..94549d0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,14 @@ +.dockerignore +.editorconfig +.env +.git +.github +.gitignore +.idea +.yarn +.vscode +coverage* +tools +LICENSE +README.md +node_modules diff --git a/.gitignore b/.gitignore index 7755077..54bbdec 100644 --- a/.gitignore +++ b/.gitignore @@ -6,5 +6,6 @@ /previous_deploy.tar.gz /.yarn /.idea +/.vscode /.env* !/.env*.dist diff --git a/bun.lockb b/bun.lockb index 3e01f018cb9371540ee13de7535b8d12d007dc16..7c6bc5abfb770f71155fee966691aef4158198a5 100644 GIT binary patch delta 24551 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 X*$QsF^~VZsY|l1J06SX2ZNdKlY#90- delta 24548 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 diff --git a/cspell.config.yaml b/cspell.config.yaml deleted file mode 100644 index a4896b0..0000000 --- a/cspell.config.yaml +++ /dev/null @@ -1,8 +0,0 @@ -version: '0.2' -ignorePaths: [] -dictionaryDefinitions: [] -dictionaries: [] -words: - - hass -ignoreWords: [] -import: [] diff --git a/package.json b/package.json index 32a4445..72a9394 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,9 @@ "type": "module", "scripts": { "dev": "bun --hot --watch src/main.ts", - "build": "bun build src/main.ts --target=bun --outfile=dist/server.js", - "start": "bun run dist/server.js", + "build": "docker build . -f tools/docker/Dockerfile -t automation-prod", + "build:dist": "bun build src/main.ts --target=bun --outfile=dist/server.js", + "start": "docker run --env-file .env automation-prod", "test": "vitest", "coverage": "vitest --coverage", "lint": "eslint src/ --ext .js,.ts,.tsx,.mts --max-warnings 0", @@ -16,7 +17,7 @@ "fix": "bun run format && bun run lint --fix", "typecheck": "tsc --noEmit", "types": "bun --env-file .env type-writer", - "prepare": "husky install" + "prepare": "husky install || true" }, "trustedDependencies": [ "husky" @@ -28,7 +29,7 @@ ], "*.@(ts|tsx|mts)": "bash -c 'bun tsc --skipLibCheck --noEmit'", "*.@(ts|tsx|mts|js|jsx|mjs|cjs)": [ - "bun eslint --max-warnings 0", + "eslint --max-warnings 0", "vitest related --run" ], "*.@(ts|tsx|mts|js|jsx|mjs|cjs|json|jsonc|json5|md|mdx|yaml|yml)": "prettier --write" diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile new file mode 100644 index 0000000..426ade7 --- /dev/null +++ b/tools/docker/Dockerfile @@ -0,0 +1,80 @@ +########################################################### +## ## +# # Base ## +## ## +########################################################### + +# see all versions at https://hub.docker.com/r/oven/bun/tags +ARG BUN_VERSION=1 + +# Official Bun image +FROM oven/bun:${BUN_VERSION} as base + +# Bun uses NODE_ENV for backward compatibility with Node +ENV NODE_ENV="production" + +# Simplicity first +WORKDIR /app + +########################################################### +## ## +## BUILDER ## +## ## +########################################################### + +FROM base as builder + +# Act as CI system: no interactive tty, no stdin/stdout, no watch processes +ENV CI="true" + +# Copy only relevant files for dev and prod +COPY package.json bun.lockb /app/prod/ +COPY package.json bun.lockb tsconfig.json vitest.config.ts .prettier* .eslint* .cspell.json /app/dev/ + +# Copy source code +COPY src/ /app/dev/src/ + +# Build and pre-flight checks +RUN cd /app/dev \ + && bun install --frozen-lockfile \ + # Note: `--watch false` is a workaround for https://github.com/vitest-dev/vitest/issues/1288 + && bun test --watch false \ + && bun run prettier --check . \ + && bun run lint \ + # Note: Can not do typecheck unless we pass in credentials during build time + # && bun run types \ + # && bun run typecheck \ + && bun run build:dist + +# Prod deps only +RUN cd /app/prod \ + && bun install --production --frozen-lockfile + +########################################################### +## ## +## PRODUCTION ## +## ## +########################################################### + +FROM base as prod + +# Open Container Initiative (OCI) labels +LABEL org.opencontainers.image.title="Automation Standalone" \ + org.opencontainers.image.description="This image contains an end-users automations application that communicates directly with a HomeAssistant instance" \ + org.opencontainers.image.version="1.0.0" \ + org.opencontainers.image.url="https://github.com/digital-alchemy/automation-standalone" \ + org.opencontainers.image.documentation="https://docs.digital-alchemy.app/" \ + org.opencontainers.image.source="https://github.com/digital-alchemy/automation-standalone" \ + org.opencontainers.image.vendor="Digital Alchemy" \ + org.opencontainers.image.authors="Webber Takken " \ + org.opencontainers.image.licenses="MIT" + +# Copy the distributable files and production specific dependencies +COPY --from=builder /app/dev/dist . +COPY --from=builder /app/prod/package.json . +COPY --from=builder /app/prod/node_modules node_modules + +# Run the app +USER bun +EXPOSE 3000 +ENTRYPOINT [ "bun", "run", "server.js" ]