From d450e734b2f8dd260f9ccbd3327631d2666d2931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ga=C5=82ka?= Date: Tue, 8 Oct 2024 19:36:35 +0200 Subject: [PATCH] feat(package): upgrade docker (#82) --- .dockerignore | 1 + .eslintrc.js => .eslintrc.cjs | 2 +- Dockerfile | 43 +++++++++++++ README.md | 50 +++++++++++++++ apps/api/Dockerfile | 38 ----------- apps/api/package.json | 2 + apps/api/tsconfig.json | 2 +- apps/web/Dockerfile | 39 ------------ apps/web/package.json | 2 + apps/web/vite.config.ts | 2 +- docker-compose.yml | 24 ++++--- package.json | 18 ++++-- pnpm-lock.yaml | 116 +++++++++++++++++++++++++++++++--- scripts/docker.js | 89 ++++++++++++++++++++++++++ 14 files changed, 324 insertions(+), 104 deletions(-) rename .eslintrc.js => .eslintrc.cjs (96%) create mode 100644 Dockerfile delete mode 100644 apps/api/Dockerfile delete mode 100644 apps/web/Dockerfile create mode 100644 scripts/docker.js diff --git a/.dockerignore b/.dockerignore index 05ad6f8..11203df 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,7 @@ .git node_modules dist +scripts **/Dockerfile docker-compose* .dockerignore diff --git a/.eslintrc.js b/.eslintrc.cjs similarity index 96% rename from .eslintrc.js rename to .eslintrc.cjs index 2fc37f4..be1e4e9 100644 --- a/.eslintrc.js +++ b/.eslintrc.cjs @@ -19,7 +19,7 @@ module.exports = { }, overrides: [ { - files: ['**/*.js'], + files: ['**/*.{js,cjs}'], env: { node: true, }, diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6718d56 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,43 @@ +FROM node:20-slim AS base + +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" + +RUN corepack enable + +FROM base AS build + +COPY . /usr/src/app +WORKDIR /usr/src/app +RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile +RUN pnpm build +RUN pnpm deploy --filter=api --prod /prod/api +RUN pnpm deploy --filter=web --prod /prod/web + +FROM base AS api + +WORKDIR /app +COPY --from=build /prod/api /app +EXPOSE 3000 +CMD ["node", "dist/main.js"] + +FROM nginx:stable AS web + +# This tool converts env vars into json to be injected into the config +ADD https://s3.amazonaws.com/se-com-docs/bins/json_env /usr/local/bin/ +RUN chmod +x /usr/local/bin/json_env + +COPY apps/web/docker/nginx.conf /etc/nginx/conf.d/default.conf +COPY apps/web/docker/expires.conf /etc/nginx/conf.d/expires.conf +COPY apps/web/docker/entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh + +ENV CONFIG_FILE_PATH=/app/config/app.json + +WORKDIR /app +COPY --from=build /prod/web/dist /app +RUN rm -rf /app/config/* + +ENTRYPOINT ["entrypoint.sh"] + +CMD ["nginx", "-g", "daemon off;"] diff --git a/README.md b/README.md index b748172..d16fc83 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,53 @@ # [Vue.js](https://vuejs.org/) + [NestJS](https://nestjs.com/) Monorepo [![CircleCI](https://circleci.com/gh/modernweb-pl/vue-nest-monorepo/tree/master.svg?style=svg)](https://circleci.com/gh/modernweb-pl/workflows/vue-nest-monorepo/tree/master) + + +## Docker support + +Repository includes Docker support for building and pushing images to GitHub Packages. Follow the steps below to build and push the Docker images. + +### Prerequisites + +Ensure you have Docker installed and running on your machine. You will also need to [authenticate to the GitHub Packages](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#authenticating-to-the-container-registry) to push the Docker images. + +```bash +echo $GITHUB_TOKEN | docker login ghcr.io -u --password-stdin +``` + +Adjust `docker.registry` and `homegae` fields in `package.json` which are used to properly name the images and link them to your GitHub repository in GitHub Packages: + +```json +{ + "homepage": "https://github.com//", + "docker": { + "registry": "ghcr.io//" + } +} +``` + +### Building the Docker Images + +To build the Docker images locally, you can use the following command: + +```bash +pnpm docker:build +``` + +### Pushing the Docker Images to GitHub Packages + +Once the images are built, push them to GitHub Packages using the following command: + +```bash +pnpm docker:push +``` + +### Docker Compose Setup + +Repository also includes a `docker-compose.yml` file for easier multi-container setup and orchestration. Use Docker Compose to start the services locally by running: + +```bash +docker-compose up +``` + +This will spin up all defined services and link containers as needed. diff --git a/apps/api/Dockerfile b/apps/api/Dockerfile deleted file mode 100644 index f6b8146..0000000 --- a/apps/api/Dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -FROM node:16 as builder - -RUN npm install -g pnpm - -WORKDIR /app - -COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ -COPY apps/api/package.json apps/api/ -COPY libs/dto/package.json libs/dto/ -RUN pnpm install --frozen-lockfile - -COPY tsconfig.json . -COPY apps/api apps/api -COPY libs libs - -RUN pnpm api build - -### Production image - -FROM node:16-slim as app - -RUN npm install -g pnpm - -WORKDIR /app -ENV NODE_ENV production -ENV PORT 3000 -EXPOSE 3000 - -COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ -COPY apps/api/package.json apps/api/ -COPY libs/dto/package.json libs/dto/ -RUN pnpm install --frozen-lockfile && rm -rf apps libs package.json pnpm-lock.yaml - -COPY --from=builder /app/dist/api . - -USER node - -CMD ["node", "main.js"] diff --git a/apps/api/package.json b/apps/api/package.json index 2ff08c8..ee6371f 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -11,6 +11,8 @@ "start": "nest start", "preview": "node ../../dist/api/main", "build": "nest build", + "docker:build": "node ../../scripts/docker build api", + "docker:push": "node ../../scripts/docker push api", "test": "jest", "test:watch": "jest --watch", "test:cov": "jest --coverage", diff --git a/apps/api/tsconfig.json b/apps/api/tsconfig.json index b1ca7be..89a8b29 100644 --- a/apps/api/tsconfig.json +++ b/apps/api/tsconfig.json @@ -7,7 +7,7 @@ "emitDecoratorMetadata": true, "experimentalDecorators": true, "target": "es2017", - "outDir": "../../dist/api", + "outDir": "./dist", "baseUrl": "./", "incremental": true } diff --git a/apps/web/Dockerfile b/apps/web/Dockerfile deleted file mode 100644 index 9a25e82..0000000 --- a/apps/web/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -FROM node:16 as builder - -RUN npm install -g pnpm - -WORKDIR /app - -COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ -COPY apps/web/package.json apps/web/ -COPY libs/dto/package.json libs/dto/ -RUN pnpm install --frozen-lockfile - -COPY tsconfig.json . -COPY apps/web apps/web -COPY libs libs - -RUN pnpm web build - -### Production image - -FROM nginx:stable as app - -# This tool converts env vars into json to be injected into the config -ADD https://s3.amazonaws.com/se-com-docs/bins/json_env /usr/local/bin/ -RUN chmod +x /usr/local/bin/json_env - -COPY apps/web/docker/nginx.conf /etc/nginx/conf.d/default.conf -COPY apps/web/docker/expires.conf /etc/nginx/conf.d/expires.conf -COPY apps/web/docker/entrypoint.sh /usr/local/bin/entrypoint.sh -RUN chmod +x /usr/local/bin/entrypoint.sh - -ENV CONFIG_FILE_PATH /app/config/app.json - -RUN mkdir /app -COPY --from=builder /app/dist/web /app -RUN rm -rf /app/config/* - -ENTRYPOINT ["entrypoint.sh"] - -CMD ["nginx", "-g", "daemon off;"] diff --git a/apps/web/package.json b/apps/web/package.json index 574953d..089be90 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -10,6 +10,8 @@ "preview": "vite build && vite preview --port 4173", "build": "concurrently 'pnpm type-check' 'pnpm build-only'", "build-only": "vite build", + "docker:build": "node ../../scripts/docker build web", + "docker:push": "node ../../scripts/docker push web", "test": "vitest run --environment jsdom", "test:watch": "vitest --environment jsdom", "test:e2e": "start-server-and-test 'pnpm preview' http://localhost:4173/ 'cypress run --e2e'", diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts index 9aed89f..7686a94 100644 --- a/apps/web/vite.config.ts +++ b/apps/web/vite.config.ts @@ -8,7 +8,7 @@ import { VitePWA } from 'vite-plugin-pwa'; // https://vitejs.dev/config/ export default defineConfig({ build: { - outDir: '../../dist/web', + outDir: './dist', emptyOutDir: true, }, server: { diff --git a/docker-compose.yml b/docker-compose.yml index 36fec7d..a654856 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,23 +1,31 @@ -version: '3.7' - services: web: build: context: . - dockerfile: apps/web/Dockerfile + target: web environment: - - API_URL=http://localhost:3000/api - - CONFIG_VARS=API_URL + - CONFIG_VARS=API_URL,DEMO_MODE + - API_URL=http://localhost:3000 + - DEMO_MODE=true ports: - - 8080:80 + - "8080:80" tty: true api: build: context: . - dockerfile: apps/api/Dockerfile + target: api environment: - AUTH_SECRET=ThisIsNotASecretKeyJustForTesting + - MONGO_URL=mongodb://mongo/vue-nest-monorepo + - NODE_ENV=demo ports: - - 3000:3000 + - "3000:3000" tty: true + + mongo: + image: mongo:8 + ports: + - "27017:27017" + volumes: + - .data/mongo:/var/lib/mysql diff --git a/package.json b/package.json index a842899..653af53 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,13 @@ { "name": "vue-nest-monorepo", "private": true, - "repository": "git@github.com:modernweb-pl/vue-nest-monorepo.git", "author": "ModernWeb ", + "repository": "git@github.com:modernweb-pl/vue-nest-monorepo.git", + "homepage": "https://github.com/modernweb-pl/vue-nest-monorepo", + "docker": { + "registry": "ghcr.io/modernweb-pl/vue-nest-monorepo" + }, + "type": "module", "packageManager": "pnpm@9.10.0", "engineStrict": true, "engines": { @@ -12,13 +17,12 @@ "scripts": { "dev": "pnpm -r --parallel dev", "api": "pnpm -F @app/api", - "api:docker": "docker build . -t docker.pkg.github.com/modernweb-pl/vue-nest-monorepo/api -f apps/api/Dockerfile", - "api:docker:push": "docker push docker.pkg.github.com/modernweb-pl/vue-nest-monorepo/api", "web": "pnpm -F @app/web", - "web:docker": "docker build . -t docker.pkg.github.com/modernweb-pl/vue-nest-monorepo/web -f apps/web/Dockerfile", - "web:docker:push": "docker push docker.pkg.github.com/modernweb-pl/vue-nest-monorepo/web", "build": "pnpm -r --parallel build", - "clean": "rimraf --glob dist node_modules apps/*/node_modules", + "docker:build": "pnpm -r --stream docker:build", + "docker:push": "pnpm -r --stream docker:push", + "clean": "rimraf --glob apps/*/dist node_modules apps/*/node_modules", + "clean:build": "rimraf --glob apps/*/dist", "format": "pnpm lint --fix && prettier --write **/*.{html,scss,json}", "lint": "eslint . --ext .js,.jsx,.ts,.tsx,.vue,.cjs,.mjs", "test": "pnpm -r --parallel test", @@ -34,10 +38,12 @@ "eslint": "^8.41.0", "eslint-config-prettier": "^7.2.0", "eslint-plugin-prettier": "^3.4.1", + "execa": "^9.4.0", "lint-staged": "~10.0.10", "prettier": "~2.0.5", "rimraf": "^6.0.1", "typescript": "^4.9.5", + "yargs": "^17.7.2", "yorkie": "~2.0.0" }, "gitHooks": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8859e6b..cd7de7b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,9 @@ importers: eslint-plugin-prettier: specifier: ^3.4.1 version: 3.4.1(eslint-config-prettier@7.2.0(eslint@8.57.1))(eslint@8.57.1)(prettier@2.0.5) + execa: + specifier: ^9.4.0 + version: 9.4.0 lint-staged: specifier: ~10.0.10 version: 10.0.10 @@ -47,6 +50,9 @@ importers: typescript: specifier: ^4.9.5 version: 4.9.5 + yargs: + specifier: ^17.7.2 + version: 17.7.2 yorkie: specifier: ~2.0.0 version: 2.0.0 @@ -1394,6 +1400,10 @@ packages: resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} engines: {node: '>=18'} + '@sindresorhus/merge-streams@4.0.0': + resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} + engines: {node: '>=18'} + '@sinonjs/commons@3.0.1': resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} @@ -3124,6 +3134,10 @@ packages: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} + execa@9.4.0: + resolution: {integrity: sha512-yKHlle2YGxZE842MERVIplWwNH5VYmqqcPFgtnlU//K8gxuFFXu0pwd/CrfXTumFpeEiufsP7+opT/bPJa1yVw==} + engines: {node: ^18.19.0 || >=20.5.0} + executable@4.1.1: resolution: {integrity: sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==} engines: {node: '>=4'} @@ -3213,6 +3227,10 @@ packages: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} engines: {node: '>=8'} + figures@6.1.0: + resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} + engines: {node: '>=18'} + file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -3588,6 +3606,10 @@ packages: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} + human-signals@8.0.0: + resolution: {integrity: sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==} + engines: {node: '>=18.18.0'} + iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -3859,6 +3881,10 @@ packages: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + is-weakref@1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} @@ -4710,6 +4736,10 @@ packages: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + npm-run-path@6.0.0: + resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==} + engines: {node: '>=18'} + nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} @@ -4869,6 +4899,10 @@ packages: resolution: {integrity: sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA==} engines: {node: '>=18'} + parse-ms@4.0.0: + resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} + engines: {node: '>=18'} + parse-path@7.0.0: resolution: {integrity: sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==} @@ -5055,6 +5089,10 @@ packages: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + pretty-ms@9.1.0: + resolution: {integrity: sha512-o1piW0n3tgKIKCwk2vpM/vOV13zjJzvP37Ioze54YlTHE06m4tjEbzg9WsKkvTuyYln2DHjo5pY4qrZGI0otpw==} + engines: {node: '>=18'} + pretty@2.0.0: resolution: {integrity: sha512-G9xUchgTEiNpormdYBl+Pha50gOUovT18IvAe7EYMZ1/f9W/WWMPRn+xI68yXNMUk3QXHDwo/1wV/4NejVNe1w==} engines: {node: '>=0.10.0'} @@ -5707,6 +5745,10 @@ packages: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} + strip-final-newline@4.0.0: + resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} + engines: {node: '>=18'} + strip-indent@2.0.0: resolution: {integrity: sha512-RsSNPLpq6YUL7QYy44RnPVTn/lcVZtb48Uof3X5JLbF4zD/Gs7ZFDv2HWol+leoQN2mT86LAzSshGfkTlSOpsA==} engines: {node: '>=4'} @@ -6073,6 +6115,10 @@ packages: resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} engines: {node: '>=18'} + unicorn-magic@0.3.0: + resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} + engines: {node: '>=18'} + unique-filename@3.0.0: resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -6551,6 +6597,10 @@ packages: resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} engines: {node: '>=18'} + yoctocolors@2.1.1: + resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} + engines: {node: '>=18'} + yorkie@2.0.0: resolution: {integrity: sha512-jcKpkthap6x63MB4TxwCyuIGkV0oYP/YRyuQU5UO0Yz/E/ZAu+653/uov+phdmO54n6BcvFRyyt0RRrWdN2mpw==} engines: {node: '>=4'} @@ -7440,7 +7490,7 @@ snapshots: '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7 espree: 9.6.1 globals: 13.24.0 ignore: 5.3.2 @@ -7462,7 +7512,7 @@ snapshots: '@humanwhocodes/config-array@0.13.0': dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -8204,6 +8254,8 @@ snapshots: '@sindresorhus/merge-streams@2.3.0': {} + '@sindresorhus/merge-streams@4.0.0': {} + '@sinonjs/commons@3.0.1': dependencies: type-detect: 4.0.8 @@ -8444,7 +8496,7 @@ snapshots: '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/type-utils': 5.62.0(eslint@8.57.1)(typescript@4.9.5) '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@4.9.5) - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7 eslint: 8.57.1 graphemer: 1.4.0 ignore: 5.3.2 @@ -8461,7 +8513,7 @@ snapshots: '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/types': 5.62.0 '@typescript-eslint/typescript-estree': 5.62.0(typescript@4.9.5) - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7 eslint: 8.57.1 optionalDependencies: typescript: 4.9.5 @@ -8477,7 +8529,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 5.62.0(typescript@4.9.5) '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@4.9.5) - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7 eslint: 8.57.1 tsutils: 3.21.0(typescript@4.9.5) optionalDependencies: @@ -8491,7 +8543,7 @@ snapshots: dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7 globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.3 @@ -9724,6 +9776,10 @@ snapshots: dependencies: ms: 2.1.2 + debug@4.3.7: + dependencies: + ms: 2.1.3 + debug@4.3.7(supports-color@8.1.1): dependencies: ms: 2.1.3 @@ -10102,7 +10158,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7 doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -10235,6 +10291,21 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 + execa@9.4.0: + dependencies: + '@sindresorhus/merge-streams': 4.0.0 + cross-spawn: 7.0.3 + figures: 6.1.0 + get-stream: 9.0.1 + human-signals: 8.0.0 + is-plain-obj: 4.1.0 + is-stream: 4.0.1 + npm-run-path: 6.0.0 + pretty-ms: 9.1.0 + signal-exit: 4.1.0 + strip-final-newline: 4.0.0 + yoctocolors: 2.1.1 + executable@4.1.1: dependencies: pify: 2.3.0 @@ -10363,6 +10434,10 @@ snapshots: dependencies: escape-string-regexp: 1.0.5 + figures@6.1.0: + dependencies: + is-unicode-supported: 2.1.0 + file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 @@ -10760,7 +10835,7 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.1 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7 transitivePeerDependencies: - supports-color @@ -10790,6 +10865,8 @@ snapshots: human-signals@5.0.0: {} + human-signals@8.0.0: {} + iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 @@ -11032,6 +11109,8 @@ snapshots: is-unicode-supported@0.1.0: {} + is-unicode-supported@2.1.0: {} + is-weakref@1.0.2: dependencies: call-bind: 1.0.7 @@ -11608,7 +11687,7 @@ snapshots: chalk: 3.0.0 commander: 4.1.1 cosmiconfig: 6.0.0 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7 dedent: 0.7.0 execa: 3.4.0 listr: 0.14.3 @@ -12143,6 +12222,11 @@ snapshots: dependencies: path-key: 4.0.0 + npm-run-path@6.0.0: + dependencies: + path-key: 4.0.0 + unicorn-magic: 0.3.0 + nth-check@2.1.1: dependencies: boolbase: 1.0.0 @@ -12303,6 +12387,8 @@ snapshots: index-to-position: 0.1.2 type-fest: 4.26.1 + parse-ms@4.0.0: {} + parse-path@7.0.0: dependencies: protocols: 2.0.1 @@ -12453,6 +12539,10 @@ snapshots: ansi-styles: 5.2.0 react-is: 18.3.1 + pretty-ms@9.1.0: + dependencies: + parse-ms: 4.0.0 + pretty@2.0.0: dependencies: condense-newlines: 0.2.1 @@ -12896,7 +12986,7 @@ snapshots: socks-proxy-agent@8.0.4: dependencies: agent-base: 7.1.1 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7 socks: 2.8.3 transitivePeerDependencies: - supports-color @@ -13138,6 +13228,8 @@ snapshots: strip-final-newline@3.0.0: {} + strip-final-newline@4.0.0: {} + strip-indent@2.0.0: {} strip-json-comments@3.1.1: {} @@ -13481,6 +13573,8 @@ snapshots: unicorn-magic@0.1.0: {} + unicorn-magic@0.3.0: {} + unique-filename@3.0.0: dependencies: unique-slug: 4.0.0 @@ -14053,6 +14147,8 @@ snapshots: yoctocolors-cjs@2.1.2: {} + yoctocolors@2.1.1: {} + yorkie@2.0.0: dependencies: execa: 0.8.0 diff --git a/scripts/docker.js b/scripts/docker.js new file mode 100644 index 0000000..f852274 --- /dev/null +++ b/scripts/docker.js @@ -0,0 +1,89 @@ +/* eslint-disable no-console */ + +import { execa } from 'execa'; +import fs from 'node:fs'; +import { createRequire } from 'node:module'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import yargs from 'yargs'; +import { hideBin } from 'yargs/helpers'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const rootPath = path.resolve(__dirname, '../'); +const packagesDir = 'apps'; +const packagesPath = path.join(rootPath, packagesDir); +const packages = fs.readdirSync(packagesPath); + +const { + docker: { registry }, + homepage, +} = createRequire(`${rootPath}/`)('./package.json'); +const { version } = createRequire(`${rootPath}/`)('./lerna.json'); + +const exec = (bin, args, opts = {}) => + execa(bin, args, { stdio: 'inherit', cwd: rootPath, ...opts }); + +const imageInfo = (target, tag) => { + if (!packages.includes(target)) { + throw new Error(`Invalid target: '${target}'`); + } + const targetPath = `${packagesPath}/${target}`; + const targetPackage = createRequire(import.meta.url)(`${targetPath}/package.json`); + const name = targetPackage.name.replace('@', ''); + const packageName = `${registry}/${name}`; + const currentImage = `${packageName}:v${version}`; + const tagImage = `${packageName}:${tag}`; + + return { packageName, currentImage, tagImage }; +}; + +yargs(hideBin(process.argv)) + .command( + 'build ', + 'build docker image', + { + tag: { alias: 't', default: 'latest' }, + verbose: { alias: 'v', type: 'boolean' }, + }, + async (args) => { + const { target, tag, verbose } = args; + const { currentImage, tagImage } = imageInfo(target, tag); + const dockerArgs = [ + 'build', + '.', + '--target', + target, + '--label', + `org.opencontainers.image.source=${homepage}`, + '-t', + currentImage, + '-t', + tagImage, + ]; + if (verbose) { + dockerArgs.push('--progress', 'plain'); + } + console.log('Running docker:', dockerArgs.join(' ')); + await exec('docker', dockerArgs); + }, + ) + .command( + 'push ', + 'push docker image', + { + tag: { alias: 't', default: 'latest' }, + verbose: { alias: 'v', type: 'boolean' }, + }, + async (args) => { + const { target, tag, verbose } = args; + const { packageName } = imageInfo(target, tag); + const dockerArgs = ['push', packageName, '-a']; + if (verbose) { + dockerArgs.push('--progress', 'plain'); + } + console.log('Running docker:', dockerArgs.join(' ')); + await exec('docker', dockerArgs); + }, + ) + .help() + .parse();