EasyDeploy
Wróć do bloga
hugo hugo-extended oracle-cloud docker saas static-site-generator

Budowa strony SaaS w Hugo: od konfiguracji do wdrożenia w Oracle Cloud

Łukasz Tomalczyk ·
Budowa strony SaaS w Hugo: od konfiguracji do wdrożenia w Oracle Cloud

Wprowadzenie

Budując aplikację SaaS, kluczowe jest stworzenie silnej obecności w sieci. Potrzebujemy miejsca, gdzie możemy publikować informacje o produkcie, udostępniać dokumentację i prezentować ofertę potencjalnym klientom.

Wybór właściwego narzędzia

Po analizie dostępnych rozwiązań zawęziłem wybór do dwóch ciekawych opcji. Pierwszą był Ghost — potężna platforma, ale wiąże się z kosztami subskrypcji. Na obecnym etapie projektu minimalizacja wydatków jest kluczowa, ponieważ mój SaaS nie generuje jeszcze przychodów. Drugą opcją było Hugo, które okazało się idealnym wyborem.

Dlaczego Hugo?

Hugo to niezwykle szybki generator statycznych stron, który pozwala tworzyć witryny, blogi i dokumentację w oparciu o proste pliki Markdown. Zamiast baz danych czy złożonych frameworków, Hugo konwertuje pliki .md do gotowego HTML, który można łatwo hostować na platformach takich jak GitHub Pages, Netlify, Vercel lub — w naszym przypadku — Oracle Cloud.

Najważniejsze zalety:

Nasza strategia wdrożenia

Naszym celem jest wdrożenie witryny w kontenerze Docker na Oracle Cloud (Always Free), zapewniając solidny hosting bez stałych kosztów.

Instrukcja instalacji krok po kroku

Wymagania wstępne

Pracuję na Windows z zainstalowanym Chocolatey — wykorzystamy go do szybkiej instalacji Hugo CLI.

Uwaga: Jeśli nie masz Chocolatey, odwiedź chocolatey.org, aby zainstalować narzędzie.

Instalacja Hugo Extended

Otwórz terminal jako administrator i uruchom:

choco install hugo-extended -y

Dlaczego Hugo Extended? Wersja rozszerzona jest kluczowa w naszym przypadku. Hugo Extended zawiera:

Te funkcje są wymagane przez większość współczesnych motywów Hugo, w tym przez motyw, którego użyjemy.

Tworzenie nowego projektu Hugo

Zainicjuj nową witrynę:

hugo new site EasyDeploySaaS
cd EasyDeploySaaS

Dodanie motywu

Użyjemy hugo-saasify-theme — nowoczesnego motywu stworzonego z myślą o stronach SaaS:

git init
git submodule add https://github.com/lukasztomalczyk/hugo-saasify-theme themes/hugo-saasify-theme

Konfiguracja początkowa

Utwórz podstawowy plik konfiguracyjny (hugo.toml):

baseURL = "https://your-domain.com"
title = "Your SaaS Name"
theme = "hugo-saasify-theme"

[module]
  [module.hugoVersion]
    extended = true
    min = "0.80.0"

Testowanie konfiguracji

Uruchom serwer deweloperski, aby sprawdzić, czy wszystko działa:

hugo server -D

Witryna będzie dostępna pod adresem http://localhost:1313.

Budowanie witryny

Gdy treść będzie gotowa, wygeneruj statyczne pliki:

hugo --minify

To polecenie tworzy zoptymalizowane pliki w katalogu public/, gotowe do wdrożenia.

Wdrożenie do Oracle Cloud

Teraz wdrożymy witrynę Hugo do Oracle Cloud, używając Dockera i Azure Pipelines.

Tworzenie Dockerfile

Utwórz Dockerfile w katalogu głównym projektu, korzystając z wieloetapowego builda:

# Etap 1: Budowa Hugo + TailwindCSS
FROM hugomods/hugo:debian-std-exts-0.152.2 AS builder

WORKDIR /src
COPY . .

# Instalacja zależności motywu (TailwindCSS / PostCSS)
RUN npm install

# Budowa CSS/JS i generowanie witryny Hugo
RUN npm run build

# Etap 2: Serwowanie przez Nginx
FROM nginx:alpine

# Usunięcie domyślnej zawartości
RUN rm -rf /usr/share/nginx/html/*

# Kopiowanie zbudowanych plików Hugo
COPY --from=builder /src/public /usr/share/nginx/html

# Kopiowanie niestandardowej konfiguracji Nginx
COPY nginx.conf /etc/nginx/nginx.conf

# Wystawienie niestandardowego portu
EXPOSE 8091

# Start Nginx
CMD ["nginx", "-g", "daemon off;"]

Konfiguracja Azure Pipeline

Użyjemy Azure Pipelines do automatycznego wdrożenia. Należy:

  1. Skonfigurować połączenie SSH w Azure DevOps
  2. Ustawić dane połączeniowe serwera

Potok 1: Budowa i wysyłka obrazu Docker

Create website-azure-pipeline-compile.yml:

trigger: none

parameters:
  - name: repository
    displayName: Repository
    type: string
    default: 'Production'
    values:
      - Production
      - Test

variables:
  docker_tag: '${{ parameters.repository }}'
  app_name: 'EasyDeployWebsite'
  app_name_lower: 'easy-deploy-website'

resources:
- repo: self

stages:
- stage: Build
  displayName: Build Multiarch Docker Image
  jobs:
  - job: Build
    displayName: Build and Push Multiarch Image
    pool:
      vmImage: ubuntu-latest
    steps:
    - checkout: self
      submodules: true

    # Docker Hub login
    - task: Docker@2
      displayName: Docker Login
      inputs:
        command: login
        containerRegistry: 'hub.docker.com'

    # Setup QEMU for ARM emulation
    - script: |
        docker run --rm --privileged tonistiigi/binfmt --install all
      displayName: Setup QEMU for multiarch

    # Create buildx builder
    - script: |
        docker buildx create --use --name mybuilder
        docker buildx inspect --bootstrap
      displayName: Setup Docker Buildx

    # Build and push multiarch image
    - script: |
        docker buildx build \
          --platform linux/arm64 \
          -f $(Build.SourcesDirectory)/src/Dockerfile \
          -t lukasztomalczyk/sp-craft.$(app_name_lower)-arm64:$(Build.BuildId) \
          -t lukasztomalczyk/sp-craft.$(app_name_lower)-arm64:$(docker_tag) \
          $(Build.SourcesDirectory)/src \
          --push
      displayName: Build and Push Multiarch Docker Image

Potok 2: Wdrożenie na serwer

Create website-azure-pipeline-install.yml:

trigger: none

parameters:
  - name: server
    displayName: Environment
    type: string
    default: 'Production'
    values:
      - Production
      - Test

variables:
- name: environment
  value: '${{ parameters.server }}'
- name: app_name
  value: 'EasyDeployWebsite'
- name: server_username
  value: 'opc'

resources:
- repo: self

stages:
- stage: Deploy
  displayName: Deploy to Server
  jobs:
  - job: Deploy
    displayName: Deploy and Run
    pool:
      vmImage: ubuntu-latest
    steps:
    - task: SSH@0
      displayName: Create required folders
      inputs:
        sshEndpoint: 'SSH-$(environment)'
        runOptions: 'commands'
        commands: >
          mkdir -p /home/$(server_username)/$(environment)/SpCraft.$(app_name)
        readyTimeout: '20000'

    - task: replacetokens@6
      displayName: Replace tokens in docker-compose
      inputs:
        root: '$(Build.SourcesDirectory)/src'
        sources: 'docker-compose.yml'
        tokenPattern: 'doublebraces'
        missingVarAction: 'keep'

    - task: CopyFilesOverSSH@0
      displayName: Copy docker-compose.yml
      inputs:
        sshEndpoint: 'SSH-$(environment)'
        sourceFolder: '$(Build.SourcesDirectory)/src'
        contents: |
          docker-compose.yml
        targetFolder: >
          /home/$(server_username)/$(environment)/SpCraft.$(app_name)
        readyTimeout: '20000'

    - task: SSH@0
      displayName: Stop existing container
      continueOnError: true
      inputs:
        sshEndpoint: 'SSH-$(environment)'
        runOptions: 'commands'
        commands: >
          docker-compose
          -f /home/$(server_username)/$(environment)/SpCraft.$(app_name)/docker-compose.yml
          down >/dev/null 2>&1
        readyTimeout: '20000'

    - task: SSH@0
      displayName: Pull latest images
      continueOnError: true
      inputs:
        sshEndpoint: 'SSH-$(environment)'
        runOptions: 'commands'
        commands: >
          docker-compose
          -f /home/$(server_username)/$(environment)/SpCraft.$(app_name)/docker-compose.yml
          pull >/dev/null 2>&1
        readyTimeout: '20000'

    - task: SSH@0
      displayName: Start container
      inputs:
        sshEndpoint: 'SSH-$(environment)'
        runOptions: 'commands'
        commands: >
          docker-compose
          -f /home/$(server_username)/$(environment)/SpCraft.$(app_name)/docker-compose.yml
          up -d >/dev/null 2>&1
        readyTimeout: '20000'

Zarządzanie środowiskami

Uwaga: Ten układ obejmuje separację środowisk (Production/Test). W prostszych wdrożeniach możesz:

Kluczowe korzyści

Podsumowanie

Hugo Extended to doskonała podstawa do budowy szybkich, skalowalnych witryn SaaS. Statyczny charakter stron Hugo zapewnia błyskawiczne działanie i minimalne zużycie zasobów serwera, co świetnie sprawdza się w nowoczesnych aplikacjach webowych.

Kolejne kroki

  1. Dopasuj motyw do swojej marki
  2. Przygotuj atrakcyjne treści dla grupy docelowej
  3. Skonfiguruj proces wdrożenia na wybranej platformie
  4. Dodaj analitykę i optymalizację SEO

Zasoby