From 685d336de797b582d20e3a4b9c473dbeec7a033a Mon Sep 17 00:00:00 2001 From: janik6n <janikarh@gmail.com> Date: Mon, 23 Dec 2024 20:36:20 +0200 Subject: [PATCH] Added container build + run --- .dockerignore | 19 +++++++++++++++++++ CHANGELOG.md | 18 ++++++++++++++++++ Dockerfile | 32 ++++++++++++++++++++++++++++++++ README.md | 25 +++++++++++++++++++------ package-lock.json | 4 ++-- package.json | 10 ++++++---- 6 files changed, 96 insertions(+), 12 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..4f8a436 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,19 @@ +.DS_Store +*.log +**/.env +.git +.gitignore +*.log +**/node_modules +**/npm-debug.log +Dockerfile +.dockerignore +**/dist +**/eslint.config.mjs +**/.prettierrc.json +**/vitest.config.js +**/vitest.workspace.js +**/*.md +.github +**/docs +.vscode diff --git a/CHANGELOG.md b/CHANGELOG.md index 6547aeb..3b7d094 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,24 @@ All notable changes to this template will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.1.0] - 2024-12-23 + +### Added + +- Build and run the app as Docker container. + +### Changed + +### Deprecated + +### Fixed + +### Removed + +### Security + +### Internal + ## [1.0.0] - 2024-12-22 This is a major rewrite of this template. Many tools have been changed. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8227d30 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +# Node build image +FROM node:22.12.0-bookworm AS builder +# Install Ubuntu packages + dumb-init +RUN apt-get update && apt-get install -y --no-install-recommends dumb-init +# Set working directory +WORKDIR /app +# Copy package.json and package-lock.json +COPY ./package*.json . +# Install NPM dependencies +RUN npm install +# Copy source files +COPY . . +# Build the app (TS > JS + treeshake + bundle + minify with Esbuild) +RUN npm run build + +# Production image +FROM node:22.12.0-bookworm-slim AS production +# Install ca-certificates +RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates && rm -rf /var/lib/apt/lists/* +# Set Node.js environment to production +ENV NODE_ENV=production +# Copy dumb-init from builder +COPY --from=builder /usr/bin/dumb-init /usr/bin/dumb-init +# Do not run as root, create a new user +USER node +WORKDIR /app +# Copy bundled app with source map from builder container +COPY --chown=node:node --from=builder /app/dist . +# Set environment variable as an example +ENV CONTAINERIZED=true +# Run the app +CMD ["sh", "-c", "dumb-init node index.mjs"] diff --git a/README.md b/README.md index 7ac3322..06b04eb 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@    +   [](https://github.com/janik6n/typescript-starter/actions) @@ -17,7 +18,8 @@ This is my batteries included TypeScript starter updated for 2025, with: - ⚙️ NPM package manager - 🚥 testing with [Vitest](https://vitest.dev/) - 📦 production bundling with [esbuild](https://esbuild.github.io/) -- ⚗️ Code linting & formatting with [ESLint](https://eslint.org/) + [Prettier](https://prettier.io/) +- 🐳 optional building of production ready [Docker](https://www.docker.com/) image +- ⚗️ Code linting & formatting with [ESLint](https://eslint.org/) & [Prettier](https://prettier.io/) - 🔬 [VS Code](https://code.visualstudio.com/) configuration for debugging - 🔥 hot reloading - 🔁 GitHub Actions workflow to run code quality checks and tests @@ -25,7 +27,7 @@ This is my batteries included TypeScript starter updated for 2025, with: ## ✅ Prerequisites - Make sure you have Node.js 22 installed. This is built, configured and tested with `Node.js 22`. -- Install VS Code, and the following extensions: +- If you want to use VS Code, make sure the following extensions are installed: - [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) - [Vitest](https://marketplace.visualstudio.com/items?itemName=vitest.explorer) @@ -34,7 +36,7 @@ This is my batteries included TypeScript starter updated for 2025, with: How to use this template? 1. Make sure prerequisites are met. -2. Copy the repository as zip so you don't have to deal with git history. +2. Download the repository as zip so you don't have to deal with git history of this repository. 3. Delete `package-lock.json`. 3. Replace `janik6n` in `package.json` with your own username, along with other info. 3. Install dependencies by running `npm install` on the project root directory. @@ -78,11 +80,17 @@ Build command explained: `"build": "rimraf ./dist && npx tsc --noEmit && node bu Sometimes it is necessary to see the built app with just transpiling without bundling. This can be accomplished with `npm run build:tsc`. -*Future plans: build as Docker 🐳 container with `npm run build:container`.* +### ⚙️ Run production bundle -### ⚙️ Serve production bundle +Run the built app with `npm run start`. -Serve the built app with `npm run start`. +### 🐳 Build as container + +Run `npm run build:container` to build the app as Docker container. Multi-stage build is used to minimize the production image size. Debian-based image is used to minimize the risk of compatibility issues. + +### 🐳 Run as container + +Run the containerized app with `npm run start:container`. ## 🐛 Known issues @@ -123,6 +131,11 @@ None as of now. 🦗 - https://esbuild.github.io/ +### Docker & Node.js + +- https://hub.docker.com/_/node +- https://snyk.io/blog/choosing-the-best-node-js-docker-image/ + ### GitHub - https://github.com/features/actions diff --git a/package-lock.json b/package-lock.json index 5ec1b8e..1690310 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "typescript-starter", - "version": "1.0.0", + "version": "1.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "typescript-starter", - "version": "1.0.0", + "version": "1.1.0", "license": "MIT", "devDependencies": { "@eslint/js": "^9.17.0", diff --git a/package.json b/package.json index 96fd31b..d59c704 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "typescript-starter", "description": "TypeScript Starter", - "version": "1.0.0", + "version": "1.1.0", "homepage": "https://github.com/janik6n/typescript-starter#readme", "repository": { "type": "git", @@ -22,7 +22,7 @@ "scripts": { "build": "rimraf ./dist && npx tsc --noEmit && node build.js", "build:tsc": "rimraf ./dist && tsc", - "build:container": "echo \"TODO: Not implemented yet\" && exit 1", + "build:container": "docker build -t typescript-starter:1.1.0 .", "dev": "tsx src/index.ts", "dev:watch": "tsx watch src/index.ts", "format": "prettier . --write", @@ -34,7 +34,8 @@ "test:cov": "vitest run --coverage.enabled=true", "test:watch": "vitest --coverage.enabled=false --project='unit-integration'", "test:ci": "vitest run --coverage.enabled=true --project='unit-integration'", - "start": "node ./dist/index.mjs" + "start": "node ./dist/index.mjs", + "start:container": "docker run -it --rm typescript-starter:1.1.0" }, "engines": { "node": ">=22.0.0" @@ -53,5 +54,6 @@ "typescript": "^5.7.2", "typescript-eslint": "^8.18.1", "vitest": "^2.1.8" - } + }, + "dependencies": {} } \ No newline at end of file