Skip to content

Deploy Nuxt 3 with Github Actions using Docker

Posted on:May 28, 2024 at 03:37 PM

Here I want to share with you how to deploy Nuxt 3 using github actions in vps using docker compose and use watchtower to trigger pulling newest images.

In your Nuxt root project directory, add Dockerfile with this value

FROM node:20 as builder

# Set working directory
WORKDIR /usr/src/app

COPY ./package*.json ./
# Install dependencies
RUN npm ci

# Copy all files
COPY . .

# Set env
ENV NODE_ENV production

ENV NITRO_PRESET node_cluster

# Build app
RUN npm run build

# final image use distroless for smaller build
FROM gcr.io/distroless/nodejs20-debian11:nonroot

# Set env
ENV NODE_ENV production

# Set working directory
WORKDIR /usr/src/app

# Copy .output from builder
COPY --from=builder /usr/src/app/.output/ /usr/src/app/.output/

# Expose the listening port
EXPOSE 3000

# Launch app
CMD [ ".output/server/index.mjs" ]

The Dockerfile is used to create docker image, and it will created by Github by Actions.

Then, create .github/workflows/docker-publish.yml from nuxt root project directory.

name: Deploy Docker on Github

on:
  push:
    branches:
      - main
run-name: ${{ github.actor }} is testing out GitHub Actions 🚀
jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      packages: write
      contents: read
    steps:
      - name: Git Checkout
        uses: actions/checkout@v4
      - name: Login to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ghcr.io/${{ github.repository }}:latest

After you push to your github repository, whenever you push to main branch, the github action job will running to build docker image. When it’s completed you can see your packages in https://github.com/{namespace}/{repository}/pkgs/container/{repository}

The process of creating docker images using github actions is done.

To build the Nuxt project, now login to your vps account. Make sure your docker has logged in to github container registy using personal access token (classic).

If not, generate your github personal-access-token in https://github.com/settings/tokens and check write:packages when selecting scope. Token only will be shown once, so you need to keep it until you have logged in to container registry.

To login to github container registry you can do this following steps

export GITHUB_CR_TOKEN=[your personal access token]

echo $GITHUB_CR_TOKEN | docker login ghcr.io -u [your github username] --password-stdin

After you successfully logged in, first create docker network to handle containers in the same network.

docker network create mengapa

That command will create mengapa docker network.

Here I use watchtower to handle pulling updated images when there’s changes in container registry (github).

This is the docker compose for watchtower


version: "3"

services:
    watchtower:
        image: containrrr/watchtower
        volumes:
            - /var/run/docker.sock:/var/run/docker.sock
            - /home/[your linux server username]/.docker/config.json:/config.json
        command: --interval 60 # it's by seconds, you can change it whatever you want 60 = 1 minutes
        networks:
            - mengapa
        environment:
            WATCHTOWER_LABEL_ENABLE: "true"
            WATCHTOWER_CLEANUP: "true"
            WATCHTOWER_ROLLING_RESTART: "true"

networks:
    mengapa:
        external: true

And this is docker compose file to create docker container for your Nuxt App.

# ~/docker-compose/nuxt/docker-compose.yml

version: "3.8"

services:
    nuxt:
        image: ghcr.io/[username]/[repository]:latest
        restart: on-failure
        ports:
            - 3000:3000
        networks:
            - mengapa
        labels:
            - "com.centurylinklabs.watchtower.enable=true"
networks:
    mengapa:
        external: true

After those container run successfully, everytime you push your code to main branch, the github action will create images and stores it as packages. Then watchtower will pull the newest images and restart the container and your app with newest feature will updated automatically.