From 419277e9a87fbb2ac23c43c76e997f7151e13ee6 Mon Sep 17 00:00:00 2001 From: Vygandas Pliasas Date: Sat, 23 Dec 2023 14:38:51 +0200 Subject: [PATCH] #68 production dockerfiles builds pushing in ci (#157) * build and push docker image * few tweaks and api dockerfile * add github ci to build and publish docker image for api * new build for docker * new build for docker * small fix * small fix * small fix * small fix * small fix * small fix * added more details to .env.example --- .dockerignore | 3 +- .env.example | 2 + .github/workflows/docker_build_push.yml | 57 +++++++++++++++++++++++++ .prettierignore | 1 + apps/api/project.json | 3 +- apps/api/src/config/typeorm.config.ts | 8 +++- docker/deployments/api.dockerfile | 46 ++++++++++++++++++++ docker/deployments/start-container | 3 ++ docker/deployments/supervisord.conf | 18 ++++++++ nx.json | 5 ++- package.json | 18 ++++---- 11 files changed, 150 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/docker_build_push.yml create mode 100644 docker/deployments/api.dockerfile create mode 100644 docker/deployments/start-container create mode 100644 docker/deployments/supervisord.conf diff --git a/.dockerignore b/.dockerignore index b3b02ae..c6f5da7 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,4 @@ Makefile -docker README.md docs .env @@ -8,4 +7,4 @@ docs .idea node_modules nx -.vscode \ No newline at end of file +.vscode diff --git a/.env.example b/.env.example index bb2dc72..419d3bd 100644 --- a/.env.example +++ b/.env.example @@ -3,6 +3,8 @@ DATABASE_PORT=5432 DATABASE_USERNAME=postgres DATABASE_PASSWORD=secret DATABASE_NAME=postgres +# If certificate is set, it will use ssl for connection. If it's not set, it will set ssl: false. +#DATABASE_CERT="-----BEGIN CERTIFICATE----- ...MAg==-----END CERTIFICATE-----" REDIS_PASSWORD=redis diff --git a/.github/workflows/docker_build_push.yml b/.github/workflows/docker_build_push.yml new file mode 100644 index 0000000..81e68cd --- /dev/null +++ b/.github/workflows/docker_build_push.yml @@ -0,0 +1,57 @@ +name: Create and publish a Docker image + +# Configures this workflow to run every time a change is pushed to the branch called `release`. +on: + workflow_dispatch: + push: + branches: + - 'main' + tags: + - 'v*' + pull_request: + branches: + - 'main' + +# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu. +jobs: + build-and-push-image: + runs-on: ubuntu-latest + # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job. + permissions: + contents: read + packages: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Uses the `docker/login-action` action to log in to the Container registry using the account and + # password that will publish the packages. Once published, the packages are scoped to the account defined here. + - name: Log in to the Container registry + uses: docker/login-action@v3 + if: github.event_name != 'pull_request' + with: + username: ${{ secrets.DOCKER_HUB_USER }} + password: ${{ secrets.DOCKER_HUB_TOKEN }} + + # This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and + # labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be + # referenced in a subsequent step. The `images` value provides the base name for the tags and labels. + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: + ${{ env.REGISTRY || 'docker.io' }}/${{ env.IMAGE_NAME || github.repository }} + + # This step uses the `docker/build-push-action` action to build the image, based on your + # repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages. + # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository. + # It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step. + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + push: ${{ github.event_name != 'pull_request' }} + file: docker/deployments/api.dockerfile + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.prettierignore b/.prettierignore index a7aa16e..611d948 100644 --- a/.prettierignore +++ b/.prettierignore @@ -13,3 +13,4 @@ /.vscode pnpm-lock.yaml package.json +.github diff --git a/apps/api/project.json b/apps/api/project.json index ac493ed..e48093b 100644 --- a/apps/api/project.json +++ b/apps/api/project.json @@ -7,7 +7,8 @@ "build": { "executor": "nx:run-commands", "options": { - "commands": ["nest build -c apps/api/nest-cli.json"] + "commands": ["nest build -c apps/api/nest-cli.json"], + "generatePackageJson": true }, "outputs": ["{options.outputPath}"] }, diff --git a/apps/api/src/config/typeorm.config.ts b/apps/api/src/config/typeorm.config.ts index 5986f79..fb2cb6a 100644 --- a/apps/api/src/config/typeorm.config.ts +++ b/apps/api/src/config/typeorm.config.ts @@ -17,7 +17,13 @@ export const config = { entities: [__dirname + '/../**/*.entity.{js,ts}'], migrations: [join(__dirname, '..', 'migrations', '*.{ts,js}')], autoLoadEntities: true, - synchronize: false + synchronize: false, + ssl: process.env.DATABASE_CERT + ? { + rejectUnauthorized: false, + ca: String(process.env.DATABASE_CERT) + } + : false } export const typeOrmConfig = registerAs('typeorm', () => config) diff --git a/docker/deployments/api.dockerfile b/docker/deployments/api.dockerfile new file mode 100644 index 0000000..1dd6a49 --- /dev/null +++ b/docker/deployments/api.dockerfile @@ -0,0 +1,46 @@ +FROM ubuntu:22.04 + +ARG NODE_MAJOR=18 +ARG NODE_ENV=production +ENV NODE_ENV=${NODE_ENV} +ENV TZ=UTC + +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN apt-get update +RUN apt-get install -y ca-certificates curl gnupg supervisor +RUN mkdir -p /etc/apt/keyrings +RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg +RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list +RUN apt-get update +RUN apt-get install nodejs -y +RUN npm install -g npm +RUN npm install -g yarn + +RUN apt-get install -y zip unzip supervisor libcap2-bin libpng-dev +RUN apt-get -y autoremove +RUN apt-get clean +RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +WORKDIR /app + +COPY ./package.json ./ + +RUN yarn install --production=false +RUN yarn global add nx + +COPY . . + +RUN nx repair + +RUN nx run api:build:production + +COPY ./docker/deployments/start-container /usr/local/bin/start-container +COPY ./docker/deployments/supervisord.conf /etc/supervisor/conf.d/supervisord.conf +RUN chmod +x /usr/local/bin/start-container + +EXPOSE 3000 + +#ENTRYPOINT ["start-container"] +ENTRYPOINT ["nx", "run", "api:serve"] +#ENTRYPOINT ["bash"] diff --git a/docker/deployments/start-container b/docker/deployments/start-container new file mode 100644 index 0000000..68e595b --- /dev/null +++ b/docker/deployments/start-container @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf diff --git a/docker/deployments/supervisord.conf b/docker/deployments/supervisord.conf new file mode 100644 index 0000000..0a1d869 --- /dev/null +++ b/docker/deployments/supervisord.conf @@ -0,0 +1,18 @@ +[supervisord] +nodaemon=true +user=root +logfile=/var/log/supervisor/supervisord.log +pidfile=/var/run/supervisord.pid + +[program:api] +command=node /app/dist/apps/api/src/main.js +autostart=true +autorestart=true +startretries=5 +numprocs=1 +startsecs=0 +process_name=%(program_name)s_%(process_num)02d +stderr_logfile=/var/log/supervisor/%(program_name)s_stderr.log +stderr_logfile_maxbytes=10MB +stdout_logfile=/var/log/supervisor/%(program_name)s_stdout.log +stdout_logfile_maxbytes=10MB diff --git a/nx.json b/nx.json index d032763..32a9542 100644 --- a/nx.json +++ b/nx.json @@ -4,7 +4,10 @@ "build": { "cache": true, "dependsOn": ["^build"], - "inputs": ["production", "^production"] + "inputs": ["production", "^production"], + "options": { + "generatePackageJson": true + } }, "lint": { "cache": true, diff --git a/package.json b/package.json index ed39a65..b08799a 100644 --- a/package.json +++ b/package.json @@ -77,19 +77,19 @@ "@nestjs/cli": "^10.2.1", "@nestjs/schematics": "^10.0.1", "@nestjs/testing": "^10.0.2", - "@nx/cypress": "17.1.1", - "@nx/detox": "17.2.3", - "@nx/eslint": "17.0.3", + "@nx/cypress": "17.0.1", + "@nx/detox": "17.0.1", + "@nx/eslint": "17.0.1", "@nx/eslint-plugin": "17.0.1", - "@nx/expo": "^17.2.3", - "@nx/jest": "17.2.3", - "@nx/js": "17.2.3", - "@nx/nest": "17.1.2", + "@nx/expo": "^17.0.1", + "@nx/jest": "17.0.1", + "@nx/js": "17.0.1", + "@nx/nest": "17.0.1", "@nx/next": "^17.0.1", "@nx/node": "17.0.1", "@nx/react": "^17.0.1", - "@nx/webpack": "17.1.1", - "@nx/workspace": "17.1.1", + "@nx/webpack": "17.0.1", + "@nx/workspace": "17.0.1", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7", "@svgr/webpack": "^8.0.1", "@swc-node/register": "~1.6.7",