Deploy Astro on VPS with Nginx: Complete Guide Using Docker and Docker Compose

3 min read

TL;DR Deploying an Astro website on your VPS using Docker, Docker Compose, and Nginx provides full control, security, and scalability. Organize the project with a modular directory structure, configure Docker Compose to orchestrate services, and use Nginx as a reverse proxy. Build and start the services with docker-compose up --build -d, then access your website via your VPS IP. Enhance security with SSL and DNS proxying.

Deploying Astro to Your VPS with Nginx

Deploying Astro to Your VPS with Nginx
Deploying Astro to Your VPS with Nginx

Deploying an Astro website on your own Virtual Private Server (VPS) gives you full control over your web project while enhancing security and performance. This guide shows you how to deploy an Astro website using Docker, Docker Compose, and Nginx.

By the end of this article, you will:

  • Deploy Astro on a VPS using Docker and Docker Compose.
  • Configure Nginx as a reverse proxy for secure and efficient traffic management.
  • Manage containerized services for scalability and maintainability.

Prerequisites

Before you begin, make sure you have the following:

  • A VPS with root access.
  • Docker and Docker Compose installed.
  • Basic knowledge of Docker and Nginx.

Directory Structure

Organize your project directory as follows:

project-directory/
|-- docker-compose.yml
|-- astro/
|   |-- Dockerfile
|   |-- (Astro project files)
|-- nginx/
    |-- Dockerfile
    |-- nginx.conf

This structure keeps configurations modular and maintainable.

Step 1: Docker Compose Configuration

The docker-compose.yml file orchestrates your deployment, defining two services:

  • astro: Hosts the Astro website.
  • nginx: Acts as a reverse proxy for incoming traffic.

Create the docker-compose.yml file:

version: '1'

services:
  astro:
    container_name: astro
    restart: unless-stopped
    build:
      context: ./astro
      dockerfile: Dockerfile
    volumes:
      - shared-data:/usr/src/astro/shared-data
    ports:
      - "4321:4321"
    networks:
      - network1

  nginx:
    container_name: nginx
    restart: unless-stopped
    build:
      context: ./nginx
      dockerfile: Dockerfile
    volumes:
      - shared-data:/usr/src/nginx/shared-data
    ports:
      - "80:80"
    depends_on:
      - astro
    networks:
      - network1

volumes:
  shared-data:

networks:
  network1:
    driver: bridge

This configuration ensures:

  • Volumes: Shared data between containers.
  • Networks: Secure communication between services.
  • Depends_on: Nginx starts after Astro is ready.

Step 2: Astro Dockerfile

Inside the astro/ directory, create a Dockerfile:

FROM node:lts AS base
WORKDIR /app

COPY package.json package-lock.json ./
ENV ASTRO_DB_REMOTE_URL=libsql://example.com
ENV ASTRO_DB_APP_TOKEN=123456789

FROM base AS prod-deps
RUN npm install --omit=dev

FROM base AS build-deps
RUN npm install

FROM build-deps AS build
COPY . .
RUN npm run build --remote

FROM base AS runtime
COPY --from=prod-deps /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist

ENV HOST=0.0.0.0
ENV PORT=4321
EXPOSE 4321
CMD node ./dist/server/entry.mjs

This Dockerfile uses a multi-stage build to optimize image size and maintain security.

Step 3: Nginx Configuration

Inside the nginx/ directory, create a Dockerfile and nginx.conf.

Nginx Dockerfile:

FROM nginx:1.23.1
WORKDIR usr/src/nginx
RUN rm /etc/nginx/nginx.conf
COPY nginx.conf /etc/nginx/
RUN rm /etc/nginx/conf.d/default.conf
COPY project.conf /etc/nginx/conf.d/
RUN mkdir /usr/src/nginx/shared-data

nginx.conf:

user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

http {
    include       /etc/nginx/mime.types;
    default_type  text/html;
    access_log  /var/log/nginx/access.log  main;
    sendfile        on;
    keepalive_timeout  65;
    gzip  on;
    include /etc/nginx/conf.d/*.conf;
}

project.conf:

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://astro:4321;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_buffering off;
    }
}

This setup ensures Nginx proxies traffic efficiently to the Astro service.

Step 4: Deploy the Setup

  1. Place all files in the appropriate directories.
  2. Build and start the services:
    docker-compose up --build -d
    
  3. Access your VPS IP in a browser to view the deployed Astro website.

Next Steps and References

To secure your deployment, consider:

  • Configuring SSL with Let’s Encrypt.
  • Using a DNS proxy like Cloudflare.

Feb 22, 2025


If you have any questions or other feedback, feel free to reach out to me on the social media platforms listed below.