Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upload API Prep Part 1: Add db-migrate, extract config.ts, change tsoa entrypoint and use tsx in prod #33

Merged
merged 11 commits into from
Dec 6, 2024
3 changes: 2 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
# Useless and heavy folders
**/build
**/dist
data
[...]
**/.next
**/.vercel
Expand All @@ -16,4 +17,4 @@
# Other useless files in the image
.git/
.github/
[...]
[...]
4 changes: 3 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ POSTGRES_PASSWORD=badgehub
PGADMIN_DEFAULT_PASSWORD=badgehub
[email protected]

JWT_SIGNING_KEY="!!HackThePlanet!!"
NODE_ENV=development

JWT_SIGNING_KEY="!!HackThePlanet!!"
24 changes: 9 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,29 +1,23 @@
# Build Stage
FROM node:22-bookworm-slim AS build

WORKDIR /home/node/app

COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait why are we removing this?

Copy link
Collaborator Author

@francisduvivier francisduvivier Dec 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no build anymore, we just run straight with tsx.
Here the commit and a bit about the rationale:

Fix production setup
The path aliases and imports without extensions were giving issues after typescript compilation, leading to a situation where devleopment works fine but production crashes.
So I chose here to just run the same way in prod as in development, namely using tsx. The alternative was doing bundling with esbuild for prod.
But I don't see an issue or big disadvantage for us with using tsx in prod and the advantage is simplicity and debuggability and least chance of discrepancies between development and prod.

# Prod stage
FROM node:22-bookworm-slim

WORKDIR /home/node/app
ENV NODE_ENV=production

# Copy only needed files
COPY --chown=node:node --from=build /home/node/app/dist ./dist
COPY --chown=node:node --from=build /home/node/app/public ./public
COPY --chown=node:node --from=build /home/node/app/package*.json ./
COPY --chown=node:node ./package*.json .

RUN npm ci --only=production --ignore-scripts

COPY process.json .
COPY --chown=node:node process.json .
RUN mkdir -p /home/node/.pm2 /home/node/app/logs /home/node/app/pids && chown -R node:node /home/node/.pm2 /home/node/app/logs

# db-migrate stuff
COPY --chown=node:node migrations ./migrations
COPY --chown=node:node database.json .

COPY --chown=node:node ./public ./public
COPY --chown=node:node ./src ./src

USER node
EXPOSE 8081
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, but if you put USER node at the top of the file, you might get rid of all the --chown=node:node?

Copy link
Collaborator Author

@francisduvivier francisduvivier Dec 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I copied this over from the original dockedfile here, but would indeed be interesting to check if this is actually needed.

CMD ["./node_modules/pm2/bin/pm2-runtime", "process.json"]
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,50 @@

## - Development -

### Database Migrations

In order to make sure that we can keep track of the database schema, we use [db-migrate](https://db-migrate.readthedocs.io/en/latest/).
This allows us to track the database changes along with git and provide a framework for migrating data and rolling back changes.
So when a change to the database schema is needed, a new migration should be created instead of manually changing the database.
To create a new migration, follow the steps below.

#### Create a new migration

```bash
npm run db-migrate:create -- <migration-name>
```

This will create a new migration file in the `migrations` directory with the name `<timestamp>-<migration-name>.js` as well as 2 sql files, one for the up migration and one for the down migration.

#### Fill in the down and up migration sql files with the necessary changes to the database schema.

These sql commands should take care of changing the database schema as well as migrating the data if necessary.

#### Run the migration to test it.

```bash
npm run db-migrate:up
```

#### Create updated mock.sql

For the mock data, we always want up to date tables, so after you have done the migration on the mock data, you should re-export the database.
You can do this with the pg_dump command in the postgres container:

```bash
npm run backup
```

#### Run the down migration to test it.

```bash
npm run db-migrate:down
```

#### Commit the migration files to git.

When the code is deployed, the up migrations will be run automatically before starting the server.

## Install

Make sure [Docker](https://www.docker.com/get-started/) is installed and running.
Expand Down Expand Up @@ -99,5 +143,7 @@ docker compose --file docker-compose-production.yml down

- [Express](https://expressjs.com/), a framework for Node.js
- [tsoa](https://tsoa-community.github.io/docs/) for generating a swagger file from code
- [sql-template-tag](https://github.com/blakeembrey/sql-template-tag) for more easily writing SQL queries
- [db-migrate](https://db-migrate.readthedocs.io/en/latest/) for database migrations
- [tsx](https://tsx.is/) for watching TypeScript files in Node.js
- [PM2](https://pm2.keymetrics.io/) for managing Node.js processes
12 changes: 12 additions & 0 deletions database.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"defaultEnv": "pg-from-env",
"pg-from-env": {
"driver": "pg",
"host": { "ENV": "POSTGRES_HOST" },
"database": { "ENV": "POSTGRES_DB" },
"user": { "ENV": "POSTGRES_USER" },
"password": { "ENV": "POSTGRES_PASSWORD" },
"port": "5432",
"schema": "badgehub"
}
}
2 changes: 1 addition & 1 deletion docker-compose-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ volumes:
networks:
badgehub_network:
name: badgehub_network
external: true
external: true
4 changes: 4 additions & 0 deletions migrations/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"description": "This package.json file is picked up by db-migrate and that is needed because the js files generated by db-migrate are commonjs",
"type": "commonjs"
}
Loading
Loading