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.