Containerizing a Static Site - DigitalOcean Kubernetes - Part 3

In my previous article, I configured the Kubernetes cluster with a private Docker registry. In this one, I aim to convert this site to a Docker container and deploy it to the cluster. This time there isn't a nice DigitalOcean tutorial, but Docker is already nice to work in.

Setting up Docker

This site generates using Hugo. Building it is as simple as running the Hugo command.

hugo

To build the image, it's important to know how the site's built. Hugo builds the output into the public/ folder. The Dockerfile can use an nginx-alpine image for hosting. That leaves Docker to run the Hugo command. Luckily, there's a Hugo image created by the community to build the site.

Dockerfile

FROM klakegg/hugo:alpine-onbuild AS hugo

FROM nginx:alpine
COPY --from=hugo /onbuild /usr/share/nginx/html

Then the image can be built and tested.

docker build -t <registry.yoursite.com>/<name>:latest .
docker run -it -p 8085:80 <registry.yoursite.com>/<name>:latest .

Preview the site by visiting http://localhost:8085.

Deploying the site

Once I verified the site works, I pushed it to the private registry. Then it's as simple as setting up a deployment (or adding to an existing one), and updating the configuration.

docker push <registry.yoursite.com>/<name>:latest

hello-world.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: <yoursite>-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  tls:
    - hosts:
        - <yoursite.com>
      secretName: hello-kubernetes-tls
  rules:
    - host: <yoursite.com>
      http:
        paths:
          - path: /
            backend:
              serviceName: <yoursite>
              servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: <yoursite>
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
  selector:
    app: <yoursite>
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: <yoursite>
spec:
  replicas: 2
  selector:
    matchLabels:
      app: <yoursite>
  template:
    metadata:
      labels:
        app: <yoursite>
    spec:
      containers:
        - name: <yoursite>
          image: <registry.yoursite.com>/<name>:latest
          ports:
            - containerPort: 80
      imagePullSecrets:
        - name: regcred

Now update the configuration.

kubectl apply -f hello-world.yaml

Finally, I went and looked at the new site.

Impressions

The hardest part about this was finding the right Docker image with Hugo in it. The cluster updated fine, remained stable, and performed blue green updating successfully with zero downtime. I must say I'm quite impressed so far. I'll update the article if I run into any issues.