Supercharge Your Fullstack Apps: Integrating Next.js, Prisma and Docker for Seamless Development

Fullstack web development has never been easier thanks to the power of modern tools and technologies. However, with so many options available, it can be overwhelming to decide which tools to use and how to integrate them effectively. In this tutorial, we'll guide you through integrating Next.js, Prisma, and Docker to simplify the development and deployment process of fullstack applications.

What is Next.js?

Next.js is a popular open-source React framework for building server-rendered applications. It combines the ease of development of React with the benefits of server-side rendering, static site generation, and automatic code splitting. With Next.js, you can build high-performance and SEO-friendly applications using the latest web standards.

What is Prisma?

Prisma is an open-source ORM (Object-Relational Mapper) for Node.js and TypeScript that simplifies database management. It lets you model your data in a typesafe and intuitive way, and generates a type-safe client that can be used to interact with the database. With Prisma, you can focus on your domain logic and let it handle the database access layer.

What is Docker?

Docker is a popular open-source platform for building, shipping, and running containerized applications. It provides a way to package an application and its dependencies into a container that can run on any system that has Docker installed, regardless of the underlying hardware or software. With Docker, you can ensure that your application runs the same way everywhere, and easily deploy it to multiple environments.

Getting Started

Let's start by creating a new Next.js application using the official create-next-app command:


    npx create-next-app my-app
    cd my-app
    

Next, let's add Prisma to our project by installing the required dependencies:


    npm install prisma @prisma/client
    

Now, let's start by defining our data model in a new file named schema.prisma:


    datasource db {
      provider = "postgresql"
      url = env("DATABASE_URL")
    }

    model User {
      id Int @id @default(autoincrement())
      name String
      email String @unique
      password String
    }
    

This schema defines a single data model named User with four fields: id, name, email, and password. Each field has its own type, and some fields have additional attributes like @id which marks the field as the primary key and @unique which enforces uniqueness.

Next, we can use Prisma Migrate to create the database schema based on our data model. To do this, run the following commands:


    npx prisma migrate save --name init --experimental
    npx prisma migrate up --experimental
    

These commands will create the necessary tables and fields in the database based on our data model. We can now interact with the database using the Prisma Client, which we'll generate in a later step.

Integrating Prisma with Next.js

Now that we've set up our data model and database, let's integrate Prisma with our Next.js application. To do this, we'll generate a Prisma Client by running the following command:


    npx prisma generate
    

This command will generate a TypeScript client that we can use to interact with our database. The client will be placed in the node_modules/.prisma/client directory.

Next, let's create a simple API endpoint that retrieves a list of users from the database and returns them as JSON. Create a new file named api/users.ts with the following code:


    import { PrismaClient } from '@prisma/client'
    import type { NextApiRequest, NextApiResponse } from 'next'

    const prisma = new PrismaClient()

    export default async function handle(req: NextApiRequest, res: NextApiResponse) {
      const users = await prisma.user.findMany()
      res.json(users)
    }
    

This file imports the Prisma Client and defines an API endpoint that retrieves a list of all users from the database using the findMany method. The results are returned as JSON using the res.json method.

Finally, let's add a new page that displays the list of users using server-side rendering. Create a new file named pages/users.tsx with the following code:


    import { GetServerSideProps } from 'next'
    import { PrismaClient } from '@prisma/client'

    const prisma = new PrismaClient()

    export default function Users({ users }) {
      return (
        <div>
          <h1>Users</h1>
          <ul>
            {users.map((user) => (
              <li key={user.id}>
                <strong>{user.name}</strong> ({user.email})
              </li>
            ))}
          </ul>
        </div>
      )
    }

    export const getServerSideProps: GetServerSideProps = async () => {
      const users = await prisma.user.findMany()
      return {
        props: { users },
      }
    }
    

This file defines a new Next.js page component that retrieves a list of all users from the database using the Prisma Client and renders it as an unordered list. The data is fetched using the getServerSideProps function, which runs on the server and returns the fetched data as props to the component.

With this implementation, the list of users will be fetched from the server on each page load. However, if you want to pre-render the page at build time, you can use the getStaticProps function instead.

Using Docker for Deployment

Finally, let's look at how we can use Docker to package our application and deploy it to multiple environments. To do this, we'll create a new Dockerfile in the root of our project with the following content:


    # Use an official Node.js runtime as a parent image
    FROM node:14

    # Set the working directory to /app
    WORKDIR /app

    # Copy package.json and package-lock.json to /app
    COPY package*.json ./

    # Install dependencies
    RUN npm install

    # Copy the rest of the application to /app
    COPY . .

    # Build the application
    RUN npm run build

    # Expose port 3000
    EXPOSE 3000

    # Run the application
    CMD ["npm", "start"]
    

This Dockerfile creates a new Docker image based on the official Node.js 14 image, sets the working directory to /app, and copies the package.json and package-lock.json files to it. It then installs the dependencies using npm install, copies the rest of the application to the image, builds the application using npm run build, and exposes port 3000. Finally, it sets the command to run the application using npm start.

To build the Docker image, run the following command:


    docker build -t my-app .
    

This command will build the Docker image with the tag my-app.

To run the Docker container, use the following command:


    docker run -p 3000:3000 my-app
    

This command will run the Docker container and map port 3000 on the host machine to port 3000 in the container. You can now access your application by visiting http://localhost:3000 in your browser.

Conclusion

By integrating Next.js, Prisma, and Docker, we've simplified the development and deployment process of fullstack applications. We can now leverage the power of Next.js for frontend development while deploying Docker containers and using Prisma for seamless database management. We hope this guide was helpful, and happy coding!