Vue Academy · Lesson

Deploying Full-Stack Vue to Production

Docker Compose for Vue + Fastify, nginx reverse proxy, SSL with Let's Encrypt, CI/CD.

Lesson 4 of 413 steps

Deploying Full-Stack Vue to Production is a free Vue Academy lesson on CoddyKit. This is lesson 4 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Vue Academy learning path, and your progress syncs across the web and the CoddyKit app. The Vue Academy course includes 4 lessons in total.

The Production Topology

A full-stack Vue + Fastify app in production typically runs as two containers: an nginx container serving the built Vue static files, and a Fastify API container. nginx also reverse-proxies /api to the API.

Building the Vue App

Build the SPA with Vite to produce optimized static assets in dist. This is what nginx will serve.

# package.json script
npm run build
# produces dist/ with hashed JS/CSS and index.html

Vue Dockerfile (multi-stage)

Use a multi-stage Docker build: build with Node, then copy the static output into a small nginx image. The final image contains only static files and nginx.

FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf

nginx.conf: SPA + API Proxy

The nginx config serves the SPA (with a try_files fallback to index.html for client routing) and proxies /api to the Fastify container by its service name.

server {
  listen 80;
  root /usr/share/nginx/html;

  location / {
    try_files $uri $uri/ /index.html;
  }

  location /api/ {
    proxy_pass http://fastify-api:3000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
}

Fastify Dockerfile

The API image installs production dependencies and runs the server. Bind to 0.0.0.0 so it is reachable from other containers.

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

docker-compose.yml

docker-compose wires the two services on a shared network. The proxy target fastify-api in nginx.conf matches the service name here.

services:
  vue-nginx:
    build: ./frontend
    ports:
      - '80:80'
      - '443:443'
    depends_on:
      - fastify-api
  fastify-api:
    build: ./backend
    environment:
      - JWT_SECRET=${JWT_SECRET}
    expose:
      - '3000'

Service Discovery by Name

Inside the compose network, containers reach each other by service name. nginx proxies to http://fastify-api:3000 — no IPs, no public exposure of the API port.

# only nginx is published to the host (80/443)
# fastify-api uses 'expose', reachable only internally

SSL with Certbot

Add HTTPS using Let's Encrypt via Certbot. Mount the certificates into nginx and configure a 443 server block, redirecting HTTP to HTTPS.

server {
  listen 443 ssl;
  ssl_certificate /etc/letsencrypt/live/app.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/app.com/privkey.pem;
  # ... same location blocks as before
}
server {
  listen 80;
  return 301 https://$host$request_uri;
}

Certbot Renewal

Certbot certificates last 90 days. Run a renewal command on a schedule (cron or a sidecar container) and reload nginx so renewed certs take effect.

# cron entry, twice daily
certbot renew --quiet && nginx -s reload

GitHub Actions CI/CD

Automate build and deploy with GitHub Actions: on push to main, build and test, then build/push images or SSH to the server to pull and restart with compose.

name: deploy
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm test
      - name: Deploy over SSH
        run: ssh $HOST 'cd /app && git pull && docker compose up -d --build'

Secrets and Environment

Never bake secrets into images. Pass them via environment variables (compose environment / env_file) sourced from GitHub Actions secrets. Keep JWT_SECRET, DB URLs, etc. out of the repo.

Quick Check

Test your understanding of full-stack deployment.

Recap

You learned production deployment:

  • Two services: vue-nginx (static) and fastify-api
  • nginx.conf serves the SPA and proxies /api to the API service name
  • docker-compose wires them; only nginx is published to the host
  • HTTPS via Certbot with scheduled renewal
  • GitHub Actions builds, tests, and deploys; secrets stay in env vars
Free to start

Learn HTML with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
42
Lessons
156

Frequently Asked Questions

Is the “Deploying Full-Stack Vue to Production” lesson free?

Yes — any 3 lessons of the Vue Academy learning path, including “Deploying Full-Stack Vue to Production”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Vue Academy course includes 4 lessons in total.

What will I learn in “Deploying Full-Stack Vue to Production”?

Docker Compose for Vue + Fastify, nginx reverse proxy, SSL with Let's Encrypt, CI/CD. You practise Vue Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Vue Academy?

No prior experience is required. Vue Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.

How long does the “Deploying Full-Stack Vue to Production” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Vue Academy lesson?

Yes. Every Vue Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Fastify Backend for Vue SPAs
  2. JWT Authentication: Login and Refresh
  3. Authenticated API Calls with Axios Interceptors
  4. Deploying Full-Stack Vue to Production
← Back to Vue Academy