When connecting to the webpage, your terminal running Docker might display the following error Error: ENOENT: no such file or directory, open '/usr/app/_posts/%5Bslug%5D.md'
. This will be fixed in further steps.
Deploy a Next.js application using Scaleway Serverless Containers and Serverless SQL Databases
- nextjs
- sql
This tutorial will guide you through deploying a fully serverless Next.js application using a Serverless Container and a Serverless SQL Database.
You can either deploy your application:
- step by step using Scaleway CLI to understand each detailed action performed, and the resources and subresources required
- using a Terraform template to deploy your application faster and have a ready-to-use Infrastructure as Code.
Before you start
To complete the actions presented below, you must have:
- A Scaleway account logged into the console
- Owner status or IAM permissions allowing you to perform actions in the intended Organization
- A valid API key
- Installed and initialized the Scaleway CLI
- Installed Docker Engine
- Installed Node 18 or newer
Deploy Next.js application frontend using Serverless Containers
Initializing the project
-
Run the command below in a terminal to export your API access and secret keys as environment variables:
export SCW_ACCESS_KEY=$(scw config get access-key)export SCW_SECRET_KEY=$(scw config get secret-key) -
Run the command below to make sure the environment variables are properly set:
scw infoThis command displays your access key and secret key in the last two lines of the output. The
ORIGIN
column should displayenv (SCW_ACCESS_KEY)
andenv (SCW_SECRET_KEY)
, and notdefault profile
.KEY VALUE ORIGIN(...)access_key SCWF9DETBF829TAFB1TB env (SCW_ACCESS_KEY)secret_key 9a1bcf92-xxxx-xxxx-xxxx-xxxxxxxxxxxx env (SCW_SECRET_KEY) -
Access the folder where you want to store your project repository and run the following command to initialize a blog template application:
npx create-next-app --example blog-starter my-nextjs-blog -
Type
y
when prompted to install the dependencies:Need to install the following packages:create-next-app@14.0.3Ok to proceed? (y) yThis will create a folder named
my-nextjs-blog
. -
Access the folder you just created:
cd my-nextjs-blog -
Make sure you can run the application locally:
npm run dev -
Access
http://localhost:3000
in a browser. The blog template displays.
Creating an image containing your Next.js app
-
Run the following command to create a
Dockerfile
:touch Dockerfile -
Add the following code to it:
# syntax=docker/dockerfile:1FROM node:20-alpine#Built time arguments used for pre-renderingARG PGHOSTARG PGPORTARG PGDATABASEARG PGUSERARG PGPASSWORDWORKDIR /usr/appCOPY ./ ./RUN npm installRUN npm run build#Web application configurationENV PORT=8080#Database configuration used for dynamically rendered data. These default values should be overwritten by container runtime environment variablesENV PGHOST=localhostENV PGPORT=5432ENV PGDATABASE=databaseENV PGUSER=userENV PGPASSWORD=passwordCMD npm run start -
Create a
.dockerignore
file by copying the.gitignore
file:cp .gitignore .dockerignoreDocker will now ignore node dependencies and build files generated during the container build.
-
Build your application container:
docker build -t my-nextjs-blog . -
Check that your container runs locally:
docker run -it -p 8080:8080 my-nextjs-blog -
Access
http://localhost:8080
in a browser. The blog template displays.Tip
Pushing the image to Scaleway Container Registry
-
Run the following command to create a Container Registry namespace and export its endpoint as a variable:
export REGISTRY_ENDPOINT=$(scw registry namespace create -o json | jq -r '.endpoint') -
Log in to your Container Registry from your local terminal:
docker login $REGISTRY_ENDPOINT -u nologin --password-stdin <<< "$SCW_SECRET_KEY"The following output displays:
Login Succeeded -
Tag and push your container image to your Container Registry namespace:
docker tag my-nextjs-blog:latest $REGISTRY_ENDPOINT/my-nextjs-blog:latestdocker push $REGISTRY_ENDPOINT/my-nextjs-blog:latest
Deploying the container with Scaleway Serverless Containers
-
Run the following command to create a Serverless Containers namespace and export its ID as a variable:
export CONTAINER_NAMESPACE_ID=$(scw container namespace create name="my-nextjs-blog-ns" -o json | jq -r '.id') -
Deploy a Serverless Container with your application image:
scw container container create name="my-nextjs-blog" namespace-id=$CONTAINER_NAMESPACE_ID registry-image=$REGISTRY_ENDPOINT/my-nextjs-blog:latestTipThe first deployment can take up to two minutes. You can check the deployment status with the following command:
scw container container list name=my-nextjs-blogWhen the status appears as
ready
, you can access the website via your browser. -
Copy the endpoint URL displayed next to the
DomainName
property, and paste it into your browser. The blog template displays.
Your Next.js application frontend is now online.
Your application cannot store any data persistently yet. We will now add a serverless storage in the next section.
Add serverless storage to your application using a Serverless SQL Database
Setting up the database
-
Run the following command to create a Serverless SQL Database and export its attributes as variables:
export PGHOST=$(scw sdb-sql database create name=tutorial-nextjs-blog-db cpu-min=0 cpu-max=4 -o json | jq -r '.endpoint' | cut -d "/" -f3 | cut -d ":" -f1 )export PGPORT='5432'export PGDATABASE='tutorial-nextjs-blog-db'export PGUSER=$(scw iam api-key get $SCW_ACCESS_KEY -o json | jq -r '.user_id')export PGPASSWORD=$SCW_SECRET_KEYThese environment variables are default PostgreSQL variables and are automatically recognized by most PostgreSQL-compatible tools.
-
Connect to your database using the
psql
tool:psqlNotepsql
automatically usesPGHOST
,PGPORT
,PGDATABASE
,PGUSER
,PGPASSWORD
environment variables as default arguments.An input field with the name of your database displays:
psql (15.3, server 16.1 (Debian 16.1-1.pgdg120+1))SSL connection (protocol: TLSv1.3, cipher: TLS_AES_128_GCM_SHA256, compression: off)Type "help" for help.tutorial-nextjs=> -
Create a table structure with the following query:
create table posts (title char(100), excerpt text, coverImage text, date date, author_name char(50), author_picture text, ogImage_url text, slug char(50), content text); -
Add data using the following command:
insert into posts values('Learn How to Pre-render Pages Using Static Generation with Next.js','Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus.','/assets/blog/hello-world/cover.jpg','2020-03-16T05:35:07.322Z','Tim Neutkens','/assets/blog/authors/tim.jpeg','/assets/blog/hello-world/cover.jpg','hello-world','Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus. Praesent elementum facilisis leo vel fringilla. Congue mauris rhoncus aenean vel. Egestas sed tempus urna et pharetra pharetra massa massa ultricies.'),('Dynamic Routing and Static Generation','Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus.','/assets/blog/dynamic-routing/cover.jpg','2020-03-16T05:35:07.322Z','JJ Kasper','/assets/blog/authors/jj.jpeg','/assets/blog/dynamic-routing/cover.jpg','dynamic-routing','Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus. Praesent elementum facilisis leo vel fringilla. Congue mauris rhoncus aenean vel. Egestas sed tempus urna et pharetra pharetra massa massa ultricies.'),('Preview Mode for Static Generation','Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus.','/assets/blog/preview/cover.jpg','2020-03-16T05:35:07.322Z','Joe Haddad','/assets/blog/authors/joe.jpeg','/assets/blog/preview/cover.jpg','preview','Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus. Praesent elementum facilisis leo vel fringilla. Congue mauris rhoncus aenean vel. Egestas sed tempus urna et pharetra pharetra massa massa ultricies.'); -
Exit the database query interface with the following command:
exit -
Run the command below to add the
node-postgres
dependency to your application:npm install pg && npm install --save-dev @types/pgThis library is required to connect from your front end to your database.
Your application folder should be called my-nextjs-blog
and structured as follows:
my-nextjs-blog/.next/app/node_modules/public/pages/src/package.jsontsconfig.json
Integrating the database into your application
You need to edit 3 files to have a proper integration with your database.
If you want to avoid doing these modifications manually, you can also retrieve the final code from this tutorial from our serverless-examples repository with the command below:
git clone git@github.com:scaleway/serverless-examples.git
Note that this repository differs slightly in configuration, as it will dynamically render pages and not pre-render them in the Nextjs app build phase.
-
Edit the file located at
src/lib/api.ts
by replacing its content with the following code. This will switch frontend content from local data to your Serverless SQL Database.import { Post } from "@/interfaces/post";import fs from "fs";import matter from "gray-matter";import { join } from "path";import { Client } from 'pg'export type Row = {slug: string;title: string;date: Date;coverimage: string;author_name: string;author_picture: string;excerpt: string;ogimage_url: string;content: string;preview?: boolean;};const client = new Client({ssl: {rejectUnauthorized: false,}})const connect = async () => {await client.connect()}connect()//This default function handles Nextjs pre-rendering with undefined valuesexport function getPostFromRow(row: Row){if (row === undefined){var postRow: Row = {slug: "Title",title: "Excerpt",date: new Date("2024-01-16"),coverimage: "",author_name: "",author_picture: "",excerpt: "",ogimage_url: "",content: "",preview: false}} else{var postRow = row}const post = {title: postRow.title,excerpt: postRow.excerpt,coverImage: postRow.coverimage,date: postRow.date.toISOString(),author: {name: postRow.author_name,picture: postRow.author_picture},ogImage: {url: postRow.ogimage_url},slug: postRow.slug,content: postRow.content,preview: false}return post;}export async function getPostBySlug(slug: string): Promise<Post> {const data = await client.query('SELECT * FROM posts WHERE slug=$1;',[slug])const post = getPostFromRow(data.rows[0])return post;}export async function getAllPosts(): Promise<Post[]> {const data = await client.query('SELECT * FROM posts;')const posts = data.rows.map((row) => (getPostFromRow(row)))return posts;} -
Edit the file located at
src/app/page.tsx
by replacing its content with the following code. This will update the main application home page which displays the posts list.import Container from "@/app/_components/container";import { HeroPost } from "@/app/_components/hero-post";import { Intro } from "@/app/_components/intro";import { MoreStories } from "@/app/_components/more-stories";import { getAllPosts } from "../lib/api";export default async function Index() {const allPosts = await getAllPosts();const heroPost = allPosts[0];const morePosts = allPosts.slice(1);return (<main><Container><Intro /><HeroPosttitle={heroPost.title}coverImage={heroPost.coverImage}date={heroPost.date}author={heroPost.author}slug={heroPost.slug}excerpt={heroPost.excerpt}/>{morePosts.length > 0 && <MoreStories posts={morePosts} />}</Container></main>);} -
Edit the file located at
src/app/posts/[slug]/page.tsx
by replacing its content with the following code. This will update pages that display a single post.import { Metadata } from "next";import { notFound } from "next/navigation";import { getAllPosts, getPostBySlug } from "../../../lib/api";import { CMS_NAME } from "../../../lib/constants";import markdownToHtml from "../../../lib/markdownToHtml";import Alert from "../../_components/alert";import Container from "../../_components/container";import Header from "../../_components/header";import { PostBody } from "../../_components/post-body";import { PostHeader } from "../../_components/post-header";export default async function Post({ params }: Params) {const post = await getPostBySlug(params.slug)if (!post) {return notFound();}return (<main><Alert preview={post.preview} /><Container><Header /><article className="mb-32"><PostHeadertitle={post.title}coverImage={post.coverImage}date={post.date}author={post.author}/><PostBody content={post.content} /></article></Container></main>);}type Params = {params: {slug: string;};};export async function generateMetadata({ params }: Params): Promise<Metadata> {const post = await getPostBySlug(params.slug);if (!post) {return notFound();}const title = `${post.title} | Next.js Blog Example with ${CMS_NAME}`;return {openGraph: {title,images: [post.ogImage.url],},};}export async function generateStaticParams() {const posts = await getAllPosts();return posts.map((post) => ({slug: post.slug,}));} -
Run the following command to ensure that you can run the application locally:
npm run dev -
Access
http://localhost:3000
in a browser. The images and titles of the first blog post have been updated with the content from your database.
Congratulations! You can already deploy your application by building a new container version, pushing it to the Container Registry, and deploying it to Serverless Containers.
However, your application would then connect with your user credentials, which is not a recommended security practice. To secure your deployment, we will now add a dedicated IAM application, give it the minimum required permissions, and provide its credentials to your application.
Secure and redeploy your application
-
Run the following command to create an IAM application and export it as a variable:
export SCW_APPLICATION_ID=$(scw iam application create name=tutorial-nextjs-app -o json | jq -r '.id')The
SCW_APPLICATION_ID
environment variable will store the IAM application ID so you can use it in later commands. -
Create an IAM policy giving your application rights to access the database:
scw iam policy create application-id=$SCW_APPLICATION_ID name=tutorial-nextjs-policy rules.0.organization-id=$(scw config get default-organization-id) rules.0.permission-set-names.0=ServerlessSQLDatabaseFullAccessThe permission
ServerlessSQLDatabaseFullAccess
lets your application read and write data or create new databases. You can restrict this later to fit your database use cases, usingServerlessSQLDatabaseRead
orServerlessSQLDatabaseReadWrite
permissions sets. -
Create an IAM API Key and export its secret key as an environment variable:
export SCW_APPLICATION_SECRET=$(scw iam api-key create application-id=$SCW_APPLICATION_ID -o json | jq -r '.secret_key') -
Build your application container with the updated code:
docker build -t my-nextjs-blog --build-arg PGHOST --build-arg PGDATABASE --build-arg PGPORT --build-arg PGUSER=$SCW_APPLICATION_ID --build-arg PGPASSWORD=$SCW_APPLICATION_SECRET .This time, the
build
command requires environment variables, because Next.js pre-rendering will access your database while building time to load page content.You can check that your container is running correctly locally with:
docker run -it -p 8080:8080 -e PGHOST -e PGDATABASE -e PGPORT -e PGUSER=$SCW_APPLICATION_ID -e PGPASSWORD=$SCW_APPLICATION_SECRET my-nextjs-blog -
Access http://localhost:8080 in a browser. The blog template displays.
-
Push your containerized application to the Container Registry:
docker tag my-nextjs-blog:latest $REGISTRY_ENDPOINT/my-nextjs-blog:latestdocker push $REGISTRY_ENDPOINT/my-nextjs-blog:latest -
Retrieve your container’s ID:
export CONTAINER_ID=$(scw container container list name="my-nextjs-blog" -o json | jq -r '.[0].id') -
Redeploy your Serverless Container:
scw container container deploy $CONTAINER_ID -
Refresh your browser page displaying the blog. An updated version displays.
Congratulations, you have deployed a full serverless Next.js application!
Going further with containers
-
Edit the source code locally, apply
scw container deploy
again, and see the new version go live in seconds. -
Inspect your newly created resources in the Scaleway console:
-
You can display your Registry namespace and container image in the Container Registry section.
-
You can display your Serverless Containers namespace and container deployment in the Serverless Containers section.
-
You can display your Serverless SQL Database in the Serverless SQL Databases section.
-
-
Fine-tune deployment options such as autoscaling, targeted regions, and more. You can find more information by typing
scw container deploy --help
in your terminal, or by referring to the dedicated documentation.
Deploy a Next.js application using Terraform templates
You must have Terraform installed and configured with Scaleway Terraform Provider for this part.
Initialize the project
-
Run the command below to export your access key and secret key as environment variables:
export SCW_ACCESS_KEY=$(scw config get access-key)export SCW_SECRET_KEY=$(scw config get secret-key) -
Run the command below to make sure the environment variables are properly set:
scw infoThis command displays your access_key and secret_key in the two last lines of the output. The
ORIGIN
column should displayenv (SCW_ACCESS_KEY)
andenv (SCW_SECRET_KEY)
, and notdefault profile
.KEY VALUE ORIGIN(...)access_key SCWF9DETBF829TAFB1TB env (SCW_ACCESS_KEY)secret_key 9a1bcf92-xxxx-xxxx-xxxx-xxxxxxxxxxxx env (SCW_SECRET_KEY) -
Run the following command to create a folder to store the template source code, and access it:
mkdir my-nextjs-blog&& cd my-nextjs-blog -
Copy the files from the serverless-examples repository to the folder.
NoteThese files extend the blog demo application from
npx create-next-app --example blog-starter my-nextjs-blog
, and add the required code to fetch data from a database instead of static markdown files. -
Install the required dependencies:
npm install -
Confirm you can run the application locally with the following commands:
npm run dev -
Access http://localhost:3000 in a browser. The blog template displays.
Building the image containing your Next.js app
-
Build your application container with:
docker build -t my-nextjs-blog .TipAn error message
Error: connect ECONNREFUSED
might display when building. This is linked to Next.js prerendering stage without any database to connect to yet but will raise any issue at runtime because all pages will be dynamically rendered. -
Run the following command to check that your container runs locally:
docker run -it -p 8080:8080 my-nextjs-blog -
Go to localhots:8080 in your browser. The message below displays because your application is not connected to the database yet.
Application error: a server-side exception has occurred (see the server logs for more information)
Pushing the image containing your Next.js app
-
Run the following command to create a Container Registry namespace and export its endpoint as a variable:
export REGISTRY_ENDPOINT=$(scw registry namespace create -o json | jq -r '.endpoint') -
Log in to your Container Registry from your local terminal:
docker login $REGISTRY_ENDPOINT -u nologin --password-stdin <<< "$SCW_SECRET_KEY"The following output displays:
Login Succeeded -
Tag and push your container image to your Container Registry namespace:
docker tag my-nextjs-blog:latest $REGISTRY_ENDPOINT/my-nextjs-blog:latestdocker push $REGISTRY_ENDPOINT/my-nextjs-blog:latest
Creating the Terraform configuration
-
Run the following command to create a new folder inside
my-nextjs-blog
to store your Terraform files, and access it:cd ..mkdir terraform-nextjs-blog&& cd terraform-nextjs-blog -
Create an empty
main.tf
Terraform file inside the folder.Your application folder should now be structured as follows:
my-nextjs-blog/terraform-nextjs-blog/main.tf -
Add the following code to your
main.tf
file:terraform {required_providers {scaleway = {source = "scaleway/scaleway"}}required_version = ">= 0.13"}variable "REGISTRY_ENDPOINT" {type = stringdescription = "Container Registry endpoint where your application container is stored"}variable "DEFAULT_PROJECT_ID" {type = stringdescription = "Project id where your resources will be created"}resource scaleway_container_namespace main {name = "tutorial-nextjs-blog-tf"description = "Namespace created for full serverless Nextjs app deployment"}resource scaleway_container main {name = "tutorial-nextjs-blog-tf"description = "Container for Nextjs blog"namespace_id = scaleway_container_namespace.main.idregistry_image = "${var.REGISTRY_ENDPOINT}/my-nextjs-blog:latest"port = 8080cpu_limit = 560memory_limit = 1024min_scale = 0max_scale = 5timeout = 600max_concurrency = 80privacy = "public"protocol = "http1"deploy = trueenvironment_variables = {"PGUSER" = scaleway_iam_application.app.id,"PGHOST" = trimsuffix(trimprefix(regex(":\\/\\/.*:",scaleway_sdb_sql_database.database.endpoint), "://"),":")"PGDATABASE" = scaleway_sdb_sql_database.database.name,"PGPORT" = trimprefix(regex(":[0-9]{1,5}",scaleway_sdb_sql_database.database.endpoint), ":")}secret_environment_variables = {"PGPASSWORD" = scaleway_iam_api_key.api_key.secret_key,}}resource scaleway_iam_application "app" {name = "tutorial-nextjs-app-tf"}resource scaleway_iam_policy "db_access" {name = "tutorial-nextjs-policy-tf"description = "Gives tutorial Nextjs app access to Serverless SQL Database"application_id = scaleway_iam_application.app.idrule {project_ids = ["${var.DEFAULT_PROJECT_ID}"]permission_set_names = ["ServerlessSQLDatabaseReadWrite"]}}resource scaleway_iam_api_key "api_key" {application_id = scaleway_iam_application.app.id}resource scaleway_sdb_sql_database "database" {name = "tutorial-nextjs-tf"min_cpu = 0max_cpu = 8}output "database_connection_string" {// Output as an example, you can give this string to your applicationvalue = format("postgres://%s:%s@%s",scaleway_iam_application.app.id,scaleway_iam_api_key.api_key.secret_key,trimprefix(scaleway_sdb_sql_database.database.endpoint, "postgres://"),)sensitive = true}output "container_url" {// Output as an example, you can give this string to your applicationvalue = scaleway_container.main.domain_namesensitive = true}
The Terraform file creates several resources:
-
A Serverless Containers namespace, that contains a Serverless Container, which hosts your Next.js application
-
A Serverless SQL Database which stores posts data
-
An IAM policy which grants your application the right permissions
-
An IAM application, used as a principal for your IAM policy
-
An IAM API key used as credentials to authenticate your application to the database
Deploying the app with Terraform
-
Run the following command to initialize the Terraform working directory:
terraform init -
Add the
REGISTRY_ENDPOINT
andDEFAULT_PROJECT_ID
environment variables to Terraform:export TF_VAR_REGISTRY_ENDPOINT=$REGISTRY_ENDPOINTexport TF_VAR_DEFAULT_PROJECT_ID=$(scw config get default-project-id) -
Create and review the Terraform execution plan of your infrastructure:
terraform plan -
Deploy your application by executing the actions listed in your Terraform plan:
terraform applyThe output will provide the URL with which you can access your application and the connection string for your database. Since they contain sensitive values, they are hidden by default.
-
Run the following command to display them:
terraform output -jsonA similar output displays:
{"container_url": {"sensitive": true,"type": "string","value": "tutorialnextjsblogtfaxtypxrf-tutorial-nextjs-blog-tf.functions.fnc.fr-par.scw.cloud"},"database_connection_string": {"sensitive": true,"type": "string","value": "postgres://example-f6b7-40cc-9ae8-7f24e64c6531:example-c770-46ea-b785-94bf39536e6a@650c9680-1100-48e4-b5a6-ff2ff5bcf142.pg.sdb.fr-par.scw.cloud:5432/tutorial-nextjs-tf?sslmode=require"}} -
Copy the container URL from the output and paste it into a browser to access your application. However, no post will be displayed because your database is still empty.
Adding content to the Serverless SQL Database
-
Run the following command to connect to your database using the link provided by Terraform’s output:
psql $(terraform output -json | jq -r '.database_connection_string.value')An input field with the name of your database displays:
psql (15.3, server 16.1 (Debian 16.1-1.pgdg120+1))SSL connection (protocol: TLSv1.3, cipher: TLS_AES_128_GCM_SHA256, compression: off)Type "help" for help.tutorial-nextjs=> -
Create a table structure with the following query:
create table posts (title char(100), excerpt text, coverImage text, date date, author_name char(50), author_picture text, ogImage_url text, slug char(50), content text); -
Add data using the following command:
insert into posts values('Learn How to Pre-render Pages Using Static Generation with Next.js','Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus.','/assets/blog/hello-world/cover.jpg','2020-03-16T05:35:07.322Z','Tim Neutkens','/assets/blog/authors/tim.jpeg','/assets/blog/hello-world/cover.jpg','hello-world','Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus. Praesent elementum facilisis leo vel fringilla. Congue mauris rhoncus aenean vel. Egestas sed tempus urna et pharetra pharetra massa massa ultricies.'),('Dynamic Routing and Static Generation','Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus.','/assets/blog/dynamic-routing/cover.jpg','2020-03-16T05:35:07.322Z','JJ Kasper','/assets/blog/authors/jj.jpeg','/assets/blog/dynamic-routing/cover.jpg','dynamic-routing','Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus. Praesent elementum facilisis leo vel fringilla. Congue mauris rhoncus aenean vel. Egestas sed tempus urna et pharetra pharetra massa massa ultricies.'),('Preview Mode for Static Generation','Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus.','/assets/blog/preview/cover.jpg','2020-03-16T05:35:07.322Z','Joe Haddad','/assets/blog/authors/joe.jpeg','/assets/blog/preview/cover.jpg','preview','Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus. Praesent elementum facilisis leo vel fringilla. Congue mauris rhoncus aenean vel. Egestas sed tempus urna et pharetra pharetra massa massa ultricies.'); -
Exit the database query interface with the following command:
exit -
Run the command below again, and open the container URL in a browser to access your application.
terraform output -jsonYour serverless application is now online.
-
Once you are done, run the following command to stop all your resources:
terraform destroy
Going further
-
Edit the source code locally, then:
-
Build a new container version with the following command:
docker build -t my-nextjs-blog . -
Push the new container to Container Registry:
docker tag my-nextjs-blog:latest $REGISTRY_ENDPOINT/my-nextjs-blog:latestdocker push $REGISTRY_ENDPOINT/my-nextjs-blog:latest` -
Update and apply a new container deployment:
export CONTAINER_ID=$(scw container container list name="my-nextjs-blog" -o json | jq -r '.[0].id')scw container container deploy $CONTAINER_ID -
The new version is live a few seconds later.
-
-
Inspect your newly created resources in the Scaleway console:
-
You can display your Registry namespace and container image in the Container Registry section
-
You can display your Serverless Containers namespace and container deployment in the Serverless Containers section
-
You can display your Serverless SQL Database in the Serverless SQL Databases section
-
-
Fine-tune deployment options such as autoscaling, targeted regions, and more. You can find more information by typing
scw container deploy --help
in your terminal, or by referring to the dedicated documentation. -
Change the security configuration for your container. It is currently public and anyone with the link can access it, but you can make it private to require authentication.
Troubleshooting
If you happen to encounter any issues, first check that you meet all the requirements.
- You have installed and configured the Scaleway CLI. Running the
scw account project get
command should return the following output:ID example-7afa-4a5d-9f6c-27db072f1527Name defaultOrganizationID example-7afa-4a5d-9f6c-27db072f1527CreatedAt 1 year agoUpdatedAt 1 year agoDescription -TipYou can also find and compare your Project and organization ID in the Scaleway console settings.
- You have Docker Engine installed. Running the
docker -v
command in a terminal should display your currently installed docker version:Docker version 24.0.6, build ed223bc820 - You have the right IAM permissions, specifically ContainersRegistryFullAccess, ContainersFullAccess and ServerlessSQLDatabaseFullAccess.