Skip to main content
In this guide, we deploy a Next.js application.

Create Next.js application

Create an application from the template or use an existing one:
npx create-next-app@latest nextjs-demo --yes
cd nextjs-demo/
Make sure it works locally:
npm run dev

Get access to infra

You should have an instance before you start. If you don’t - follow Get Started. Check that you have access:
neterial kube get clusters
NAME      STATUS   PROVIDER        LOCATION   AGE         VERSION
default   Ready    Hetzner Cloud   hel1       17 hours    1.32
neterial kube get kubeconfig
kubectl config use-context default-neterial-admin@default-neterial
kubectl get nodes
NAME                       STATUS   ROLES                  AGE   VERSION
nks-default-ctl-53b7716f   Ready    control-plane,master   20h   v1.33.5+k3s1
The infrastructure is created. Now we’re ready to build a container image.

Build a container image

Requirement: Docker. If you don’t have it - install it. Install Railpack:
curl -sSL https://railpack.com/install.sh | sh
Prepare builder:
docker run --rm --privileged -d --name buildkit moby/buildkit
export BUILDKIT_HOST='docker-container://buildkit'
Build the container image:
railpack build --name $(neterial kube get registry --hostname)/nextjs-demo .

Deploy

Requirement: kubectl utility. Install how-to Push the image to the registry:
docker push $(neterial kube get registry --hostname)/nextjs-demo
Create deployment YAML:
export REGISTRY=$(neterial kube get registry --hostname)/nextjs-demo
export WORKLOAD_HOSTNAME=$(neterial kube get workload-hostname)

cat <<EOF > app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nextjs-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nextjs-demo
  template:
    metadata:
      labels:
        app: nextjs-demo
    spec:
      imagePullSecrets:
        - name: registry-cred
      containers:
        - name: nextjs-demo
          image: "${REGISTRY}:latest"
          imagePullPolicy: Always
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nextjs-demo
spec:
  selector:
    app: nextjs-demo
  ports:
    - port: 80
      targetPort: 3000
      protocol: TCP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nextjs-demo
  annotations:
    kubernetes.io/ingressClassName: "traefik"
    traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
    traefik.ingress.kubernetes.io/router.tls.certresolver: default
    traefik.ingress.kubernetes.io/router.tls: "true"
spec:
  rules:
    - host: "nextjs-demo.${WORKLOAD_HOSTNAME}"
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nextjs-demo
                port:
                  number: 80
EOF
And finally, deploy:
kubectl apply -f app.yaml

Check if the app is available from the Internet

To get the URL for your application, run:
kubectl get ingress nextjs-demo -o go-template --template=\
'{{range .spec.rules}}https://{{.host}}{{"\n"}}{{end}}'

Re-deploy after code update

Build, push, and apply again to update the version:
railpack build --name $(neterial kube get registry --hostname)/nextjs-demo .
docker push $(neterial kube get registry --hostname)/nextjs-demo
kubectl rollout restart deployment nextjs-demo