NextJS with Prisma on Kubernetes
source link: https://willschenk.com/articles/2021/next_js_with_prisma/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Published December 8, 2021 #nextjs, #javascript, #prisma, #knative, #kubernetes
Now that we have our cluster up and running, lets look at how to build and deploy a NextJS app on it, including the database.
Create a NextJS app
We'll scaffold out a TypeScript app.
npx create-next-app@latest --typescript myapp
cd myapp
npm run dev
Fireup a local data
docker run -e POSTGRES_PASSWORD=awesome_password -p 5432:5432 postgres
Install prisma
We'll add the npm packages to our project.
npm install prisma
npx prisma init
Edit .env
and change the url to be
DATABASE_URL="postgresql://postgres:awesome_password@localhost:5432/mydb?schema=public"
Data Models
In primsa/schema.prisma
add a model:
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
title String @db.VarChar(255)
content String?
}
Run the migration
npx prisma migrate dev --name init
Run prisma studio
to check it out
npx prisma studio
Write the post page and api
This is a basic demostration, so nothing fancy.
tsconfig.json
"baseUrl" : "."
and "strict":"false"
to compilerOptions
.
lib/prisma.ts
import { PrismaClient } from '@prisma/client';
declare global {
var prisma: PrismaClient | undefined;
}
export const prisma = global.prisma || new PrismaClient();
if (process.env.NODE_ENV !== 'production') global.prisma = prisma;
pages/posts.ts
We'll use react-hook-form
to make things simplier.
npm install react-hook-form
A couple points.
We query the database in
getServiceSideProps
We are fetching our API from
window.location.origin
We are totally hacking the window reload, I'm just lazy
import Head from 'next/head';
import { prisma } from 'lib/prisma';
import { Post } from '.prisma/client';
import Link from 'next/link';
import { useForm } from 'react-hook-form';
export default function PostsPage({ posts }) {
const {
register,
handleSubmit,
formState: { errors, isSubmitted },
} = useForm();
const onSubmit = (data) => {
try {
fetch(`${window.location.origin}/api/create`, {
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json',
},
method: 'POST',
}).then( () => {
window.location.href = window.location.href
} )
} catch (error) {
throw new Error(error);
}
};
return (
<>
<ul>
{posts.map((item: Post) => (
<li key={item.id}>{item.title} - {item.content}</li>
))}
</ul>
<form onSubmit={handleSubmit(onSubmit)}>
<label>Title</label>
<input
id="title"
type="text"
{...register('title', {required: true})}/>
<br/>
<label>Content</label>
<input
type="text"
id="content"
{...register('content', {required: true})}/>
<input type="submit"/>
</form>
</>
);
}
export const getServerSideProps = async () => {
const posts = await prisma.post.findMany({
select: {
id: true,
title: true,
content: true
},
});
console.log(posts);
return {
props: {
posts,
},
};
};
api/create.ts
This is the api request to handle the post. It runs on the server.
import { prisma } from 'lib/prisma';
export default async function handler(req, res) {
const { content, title } = req.body;
try {
const feedback = await prisma.post.create({
data: {
content,
title,
},
});
res.status(200).json(feedback);
} catch (error) {
res.status(400).json({
message: `Something went wrong :/ ${error}`,
});
}
}
Setup postgres
on your cluster
helm repo add bitnami https://charts.bitnami.com/bitnami
helm upgrade --install postgres bitnami/postgresql
Eventually the database will be available on postgres-postgresql.default.svc.cluster.local
We can get the password using
kubectl get secret --namespace default postgres-postgresql -o jsonpath="{.data.postgresql-password}" | base64 --decode
1oOFIcOvB1
When we deploy the function we'll set the DATABASE_URL
to look something like:
DATABASE_URL="postgresql://postgres:[email protected]:5432/database?schema=public"
You'll need to update that with your actual password of course.
Migrate the database
We are going to setup the database from our local enviornment. We'll
use kubectl
to forward the local postgres port to the remote install.
Remember to stop your local postgres container
kubectl port-forward svc/postgres-postgresql 5432:5432
Then, using the password that we found above, deploy the current migrations to the postgres that's being forwared on localhost. This is a different url then the previous one shown!:
DATABASE_URL="postgresql://postgres:1oOFIcOvB1@localhost:5432/database?schema=public" \
npx prisma migrate deploy
You can also run prisma studio
that way, by the way.
Deploy the service
Build image
We need to tweaks the dockerfile from the official docs to add prisma
generate
to get the client code. So, copy over that Dockerfile
and
then, right after it copies the node_modules
over added
RUN npx prisma generate
For me it's on like 14, right before yarn build
.
Since I'm working off an M1 mac, I need to set the --platform
to make
sure that the image is built using the correct binaries. An example
of this is:
docker build . --platform linux/amd64 -t wschenk/prismatest && docker push wschenk/prismatest
Create the service
kn service create prisma \
--image wschenk/prismatest \
--env DATABASE_URL="postgresql://postgres:[email protected]:5432/database?schema=public"
Once this is up and running, you should be able to interact with your service and add messages.
References
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK