How to Build and Run Next.js Applications with Docker, Compose, & NGINX

At DockerCon 2022, Kathleen Juell, a Full Stack Engineer at Sourcegraph, shared some tips for combining Next.js, Docker, and NGINX to serve static content. With nearly 400 million active websites today, efficient content delivery is key to attracting new web application users.

In some cases, using Next.js can boost deployment efficiency, accelerate time to market, and help attract web users. Follow along as we tackle building and running Next.js applications with Docker. We’ll also cover key processes and helpful practices for serving that static content. 

Why serve static content with a web application?

According to Kathleen, the following are the benefits of serving static content: 

Fewer moving parts, like databases or other microservices, directly impact page rendering. This backend simplicity minimizes attack surfaces. Static content stands up better (with fewer uncertainties) to higher traffic loads.Static websites are fast since they don’t require repeated rendering.Static website code is stable and relatively unchanging, improving scalability.Simpler content means more deployment options.

Since we know why building a static web app is beneficial, let’s explore how.

Building our services stack

To serve static content efficiently, a three-pronged services approach composed of Next.js, NGINX, and Docker is useful. While it’s possible to run a Next.js server, offloading those tasks to an NGINX server is preferable. NGINX is event-driven and excels at rapidly serving content thanks to its single-threaded architecture. This enables performance optimization even during periods of higher traffic.  

Luckily, containerizing a cross-platform NGINX server instance is pretty straightforward. This setup is also resource friendly. Below are some of the reasons why Kathleen — explicitly or perhaps implicitly — leveraged three technologies. 

Docker Desktop also gives us the tools needed to build and deploy our application. It’s important to install Docker Desktop before recreating Kathleen’s development process. 

The following trio of services will serve our static content:

First, our auth-backend has a build context rooted in a directory and a port mapping. It’s based on a slimmer alpine flavor of the Node.js Docker Official Image and uses named Dockerfile build stages to prevent reordered COPY instructions from breaking. 

Second, our client service has its own build context and a named volume mapped to the staticbuild:/app/out directory. This lets us mount our volume within our NGINX container. We’re not mapping any ports since NGINX will serve our content.

Third, we’ll containerize an NGINX server that’s based on the NGINX Docker Official Image.

As Kathleen mentions, ending this client service’s Dockerfile with a RUN command is key. We want the container to exit after completing the yarn build process. This process generates our static content and should only happen once for a static web application.

Each component is accounted for within its own container. Now, how do we seamlessly spin up this multi-container deployment and start serving content? Let’s dive in!

Using Docker Compose and Docker volumes

The simplest way to orchestrate multi-container deployments is with Docker Compose. This lets us define multiple services within a unified configuration, without having to juggle multiple files or write complex code. 

We use a compose.yml file to describe our services, their contexts, networks, ports, volumes, and more. These configurations influence app behavior. 

Here’s what our complete Docker Compose file looks like: 

services:
auth-backend:
build:
context: ./auth-backend
ports:
– "3001:3001"
networks:
– dev

client:
build:
context: ./client
volumes:
– staticbuild:/app/out
networks:
– dev

nginx:
build:
context: ./nginx
volumes:
– staticbuild:/app/public
ports:
– “8080:80”
networks:
– dev

networks:
dev:
driver: bridge

volumes:
staticbuild:

You’ll also see that we’ve defined our networks and volumes in this file. These services all share the dev network, which lets them communicate with each other while remaining discoverable. You’ll also see a common volume between these services. We’ll now explain why that’s significant.

Using mounted volumes to share files

Specifically, this example leverages named volumes to share files between containers. By mapping the staticbuild volume to Next.js’ default out directory location, you can export your build and serve content with your NGINX server. This typically exists as one or more HTML files. Note that NGINX uses the app/public directory by comparison. 

While Next.js helps present your content on the frontend, NGINX delivers those important resources from the backend. 

Leveraging A/B testing to create tailored user experiences

You can customize your client-side code to change your app’s appearance, and ultimately the end-user experience. This code impacts how page content is displayed while something like an NGINX server is running. It may also determine which users see which content — something that’s common based on sign-in status, for example. 

Testing helps us understand how application changes can impact these user experiences, both positively and negatively. A/B testing helps us uncover the “best” version of our application by comparing features and page designs. How does this look in practice? 

Specifically, you can use cookies and hooks to track user login activity. When a user logs in, they’ll see something like user stories (from Kathleen’s example). Logged-out users won’t see this content. Alternatively, a web user might only have access to certain pages once they’re authenticated. It’s your job to monitor user activity, review any feedback, and determine if those changes bring clear value. 

These are just two use cases for A/B testing, and the possibilities are nearly endless when it comes to conditionally rendering static content with Next.js. 

Containerize your Next.js static web app

There are many different ways to serve static content. However, Kathleen’s three-service method remains an excellent example. It’s useful both during exploratory testing and in production. To learn more, check out Kathleen’s complete talk. 

By containerizing each service, your application remains flexible and deployable across any platform. Docker can help developers craft accessible, customizable user experiences within their web applications. Get started with Next.js and Docker today to begin serving your static web content! 

Additional Resources

Check out the NGINX Docker Official ImageRead about the Node Docker Official ImageLearn about getting started with Docker ComposeView our awesome-compose sample GitHub projects
Quelle: https://blog.docker.com/feed/

August 2022 Newsletter

Community All-Hands: September 1st
Join us tomorrow at our Community All-Hands on September 1st! This virtual event is an opportunity for the community to come together with Docker staff to learn, share, and collaborate. Don’t miss your opportunity to win Docker swag!

Register Now

News you can use and monthly highlights:
6 Docker Compose Best Practices for Dev and Prod – Give your development team a quick knowledge boost with these tips and best practices for using Docker Compose in development and production environments.
Docker Multistage Builds for Hugo – Learn how to keep your Docker container images nice and slim with the use of multistage builds for a hugo documentation project.
How to create a dockerized Nuxt 3 development environment – Learn how Docker simplifies and accelerates the Nuxt.js development workflow. It can also help you build a bleeding-edge, local web app while ensuring consistency between development and production.
Optimize Dockerfile images for NextJS – Is the size of your Next.js Docker image impacting your overall CI/CD pipeline? Here’s an article that’ll help you to improve the development and production lifecycle by optimizing your Docker images efficiently.
Building and Testing Multi-Arch Images with Docker Buildx and QEMU – Building Docker images for multiple architectures has become increasingly popular. This guide walks you through how to build a Docker image for linux/amd64 and linux/arm64 using Docker Buildx. It’ll also walk you through using QEMU to emulate an ARM environment for multiple platform builds.
Implementation And Containerization Of Microservices Using .NET Core 6 And Docker – This article helps you create microservices using the .NET Core 6 Web API and Docker. It’ll also walk you through how to connect them using Ocelot API Gateway.​

Testing with Telepresence
Wishing for a way to synchronize local changes with a remote Kubernetes environment? There is a Docker Extension for that! Learn how Telepresence partners with Docker Desktop to help you run integration tests quickly and where to get started.

Learn More

The latest tips and tricks from the community:

How to Build and Deploy a Task Management Application Using Go
Containerizing a Legendary PetClinic App Built with Spring Boot
Build and Deploy a Retail Store Items Detection System Using No-Code AI Vision at the Edge
Slim.AI Docker Extension for Docker Desktop

Dear Moby: Advice for developers
Looking for developer-specific advice and insights? Introducing our Dear Moby collection — a web series and advice column inspired by and made for YOU, our Docker community. Check out the show, read the column, and submit your app dev questions here.

Watch Dear Moby

Educational content created by the experts at Docker:

How I Built My First Containerized Java Web Application
How to Use the Apache httpd Docker Official Image
How to Use the Redis Docker Official Image
How to Develop and Deploy a Customer Churn Prediction Model Using Python, Streamlit, and Docker

Docker Captain: Julien Maitrehenry
Julien has been working with Docker since 2014 and is now joining as a Docker Captain! His friends call him “Mister Docker” because he’s always sharing his knowledge with others. Julien’s top tip for working with Docker is to build cross-platform images.

Meet the Captain

See what the Docker team has been up to:

Bulk User Add for Docker Business and Teams
Virtual Desktop Support, Mac Permission Changes, & New Extensions in Docker Desktop 4.11
Demo: Managing and Securing Your Docker Workflows
Conversation with RedMonk: Developer Engagement in the Remote Work Era

Docker Hub v1 API deprecation
On September 5th, 2022, Docker plans to deprecate the Docker Hub v1 API endpoints that access information related to Docker Hub repositories. Please update to the v2 endpoints to continue using the Docker Hub API.

Learn More

Subscribe to our newsletter to get the latest news, blogs, tips, how-to guides, best practices, and more from Docker experts sent directly to your inbox once a month.

Quelle: https://blog.docker.com/feed/

Amazon SageMaker ist jetzt in der AWS-Region Asien-Pazifik (Jakarta) verfügbar

Amazon SageMaker ist jetzt in der AWS-Region Asien-Pazifik (Jakarta) verfügbar. Amazon SageMaker ist ein vollständig verwalteter Service, der jedem Entwickler und Daten-Wissenschaftler die Möglichkeit bietet, schnell Modelle für Machine Learning (ML) zu erstellen, zu schulen und bereitzustellen. SageMaker beseitigt die Schwierigkeiten und den Aufwand bei jedem Schritt des Machine-Learning-Prozesses, um die Entwicklung hochwertiger Modelle zu vereinfachen.
Quelle: aws.amazon.com

Amazon-RDS unterstützt jetzt die Einrichtung einer Verbindung zwischen deiner RDS-Datenbank und deiner EC2-Compute-Instance mit nur einem Klick

Ab heute hast du die Möglichkeit, während der Datenbankerstellung die Verbindung automatisch von den Amazon-RDS (Amazon-Relational-Database-Service) und Amazon-Aurora-Datenbanken zu einer Amazon-EC2 (Amazon-Elastic-Compute-Cloud) Compute-Instance zu ändern. Wenn du eine Datenbank mit der Amazon-RDS-Konsole bereitstellst, ist es jetzt möglich eine EC2-Instance auszuwählen, und mit nur einem Klick die Verbindung zwischen der Datenbank und der EC2-Instance herzustellen, den von AWS empfohlenen bewährten Methoden folgend. Amazon-RDS richtet während der Datenbankerstellung deine VPC- und ähnliche Netzwerkeinstellungen automatisch ein, um eine sichere Verbindung zwischen der EC2-Instance und der RDS-Datenbank herzustellen.
Quelle: aws.amazon.com

Einführung einer API von Amazon-Connect, um per Berechtigung, Beschreibung und Tags nach Sicherheitsprofilen zu suchen

Amazon-Connect bietet nun eine neue API zur Suche nach Sicherheitsprofilen in deiner Amazon-Connect-Instance an. Diese neue API stellt eine programmgesteuerte und flexible Möglichkeit für die Suche nach Sicherheitsprofilen mit Name, Beschreibung, Berechtigungen oder Tags, bereit. Du kannst diese API jetzt benutzen, um z. B. nach allen Sicherheitsprofilen zu suchen, welche über die Berechtigung verfügen, Kontaktabläufe zu bearbeiten. Weitere Informationen zu dieser neuen API findest du in der API-Dokumentation.
Quelle: aws.amazon.com