Skip to main content

Set up your Static Site Generator (SSG)

In this docs you will learn the basics to get your existing static site generator site building on disco and being served by disco. If you have a static site or running apps, refer to these sections instead.

Overview

At this point, you already have installed the CLI on your computer, installed disco on your server, and you have added your disco Github app with the permissions to your repository on Github.

In this guide, you will have a Dockerfile to build your site, and you'll have a disco.json file telling disco where to find the files to be served within your image.

The site before disco

Let's use a very barebone home made site generator as an example.

The repository contains two files:

generate.py
requirements.txt

The file requirements.txt contains our dependencies:

markdown2==2.4.13

You would install those dependencies locally with:

pip install -r requirements.txt

The file generate.py contains the code to generate our site:

import os
import markdown2

DIST_DIR = "dist"
INDEX_MARKDOWN = """
# Home

Hello World

"""

html = f"""<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
{markdown2.markdown(md)}
</body>
</html>
"""

if not os.path.isdir(DIST_DIR):
os.makedirs(DIST_DIR)

with open(f"{DIST_DIR}/index.html", "w", encoding="utf-8") as f:
f.write(html)

You could run it locally with:

python generate.py

Create your Dockerfile

Static sites generator on disco are built using a Dockerfile.

For this example, in Python, we'll use the official Python image from Docker Hub. Just create a file named Dockerfile at the root of your repository.

FROM python:3.12.3
WORKDIR /site
COPY . /site
RUN pip install -r requirements.txt
RUN python generate.py

See notes below for some optimizations we can make to speed up builds.

Create your disco.json

Create a file named disco.json at the root of your repository. The disco.json file tells disco where to find the files to serve inside the Docker image we just built with the Dockerfile above.

{
"version": "1.0",
"services": {
"web": {
"type": "generator",
"publicPath": "dist"
}
}
}```

The name `web` is a magic name. When disco sees it, it knows that it's the one to use to expose to the internet, create a TLS certificate for HTTPS, etc.

`publicPath` is relative to the `WOKRDIR` in your `Dockerfile`. In our example, the directory `dist` actually means `/app/dist` in our Docker image.


### That's it!

Your site is now ready to be deployed on disco. You can use the CLI to add the project.

```bash
disco projects:add \
--name first-site \
--github yourname/reponame \
--domain first-site.example.com

And now, every time you git push new commits, disco will deploy the site automatically.

You can see the deployment output with:

disco deploy:output --project first-site

Optimizing the Dockerfile

In the section Create your Dockerfile, to keep it simpler, we just copied the whole app to the image and then installed the dependencies.

While it works, we're not using Docker's build cache to its full extend. When we're copying files to a Docker image, Docker will use the fact that files changed or not to decide if it needs to execute that part of the Dockerfile. In other words, if we copy the whole app to the image, chances are that every time we deploy, something changed and we'll go through the whole build.

If we start by copying files that are less likely to change and have a big impact on build time, we can speed up builds quite a bit. In our case, if we copy the requirements.txt file first, and install the dependencies, it means that each time we deploy, if nothing changed in requirements.txt, Docker will just use the dependencies from the cache and not try to download them again.

FROM python:3.12.3
WORKDIR /site
# copy the files describing our dependencies first
COPY ./requirements.txt /site/requirements.txt
# install the dependencies
RUN pip install -r requirements.txt
# then copy the rest of the site
COPY . /site
# then build your site
RUN python generate.py