Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a Docker compose file #215

Merged
merged 11 commits into from
May 28, 2024
8 changes: 6 additions & 2 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ MATERIAL_DIR=".material"
YAML_TEMPLATE="config/oxford.yaml"
NEXT_PUBLIC_MATERIAL_URL="https://github.com/UNIVERSE-HPC/course-material"
NEXT_PUBLIC_BASEPATH=""
NEXTAUTH_URL=http://localhost:3002/gutenberg/api/auth
NEXTAUTH_URL=http://localhost/gutenberg/api/auth
NEXTAUTH_SECRET="secret here"

GITHUB_SECRET="github_secret"
Expand All @@ -19,4 +19,8 @@ NEXT_PUBLIC_ENABLE_SEARCH=true
OPENAI_API_KEY="openai_api_key"
QDRANT_COLLECTION_NAME="gutenberg"
QDRANT_API_KEY=""
QDRANT_DB_URL=""
QDRANT_DB_URL=""

NGINX_HOST="localhost"
NGINX_PORT="80"
NGINX_IMAGE_TAG="latest"
15 changes: 14 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,19 @@ jobs:
- name: Run component tests
run: ${{ env.MANAGER }} component

docker-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: docker compose build
run: docker-compose -f docker-compose.yml build
- name: docker compose up
run: docker-compose -f docker-compose.yml up -d
- name: docker compose ps
run: docker-compose -f docker-compose.yml ps
- name: docker compose down
run: docker-compose -f docker-compose.yml down

deploy:
name: Deploy to staging
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
Expand All @@ -103,7 +116,7 @@ jobs:
run: corepack enable
- uses: actions/setup-python@v5
with:
python-version: '3.12'
python-version: "3.12"
- name: Checkout course material
shell: bash
run: |
Expand Down
77 changes: 74 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,76 @@
# Install dependencies only when needed
FROM node:20.9-alpine AS builder
# This dictates the branch of the Dockerfile to use, i.e. to pull, copy or use a
# placeholder for mounting the course material in. The appropriate values for
# $MATERIAL_METHOD are therefore ["pull", "copy", "placeholder"]
ARG MATERIAL_METHOD=copy

# Define the Python version to use
ARG PYTHON_VERSION=3.12.3-slim
ARG NODE_VERSION=20.9-alpine

####
# MATERIAL OPTION: PULL
# Pull course material into the app directory from a defined repo. Default is
# the Oxford course material repo defined in the config/oxford.yaml file.
FROM python:${PYTHON_VERSION} AS pull_material

# Variables for the material pull script
ARG YAML_TEMPLATE=config/oxford.yaml
ARG MATERIAL_DIR=.material
ARG CACHE_BUST=20240514

# Copy the scripts and config files into the container
ONBUILD WORKDIR /app
ONBUILD COPY ../scripts/ /app/scripts/
ONBUILD COPY ../config/ /app/config/

# Install dependencies and clean caches afterwards
ONBUILD RUN \
apt-get update && \
apt-get install -y git && \
apt-get clean && \
pip install --upgrade pip setuptools wheel && \
pip install -r scripts/python_requirements.txt && \
pip cache purge
# pull the material into the container with git
ONBUILD RUN \
echo ${CACHE_BUST} && \
python scripts/pull_material.py

####
# MATERIAL OPTION: COPY
# Copy existing course material into this container for the build
FROM node:${NODE_VERSION} AS copy_material

ARG MATERIAL_DIR=.material
# Material dir may not exist yet, so we pass COPY a file which we know will be
# in context (i.e. the entrypoint script) to ensure the COPY command doesn't
# fail
ONBUILD COPY ../entrypoint.sh ../${MATERIAL_DIR}* /app/${MATERIAL_DIR}/


####
# MATERIAL OPTION: PLACEHOLDER
# Make a placeholder directory for the material so we can mount over it later on
FROM node:${NODE_VERSION} AS placeholder_material

ARG MATERIAL_DIR=.material
ONBUILD RUN \
mkdir -p /app/${MATERIAL_DIR}/HPCu && \
touch /app/${MATERIAL_DIR}/HPCu/index.md


# Here we use the MATERIAL_METHOD arg to determine which method we use to get
# material into our container for build time.
FROM ${MATERIAL_METHOD}_material as material

####
# BUILDER
FROM node:${NODE_VERSION} AS builder
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
RUN echo node --version
# Install dependencies only when needed
COPY package.json .
COPY yarn.lock .
COPY .yarnrc.yml .
Expand All @@ -29,7 +96,10 @@ ARG DATABASE_URL
ENV DATABASE_URL ${DATABASE_URL}
ARG NEXT_PUBLIC_PLAUSIBLE_DOMAIN
ENV NEXT_PUBLIC_PLAUSIBLE_DOMAIN ${NEXT_PUBLIC_PLAUSIBLE_DOMAIN}
RUN npx prisma migrate deploy

# Copy the course material into this container for the build
ARG MATERIAL_DIR=.material
COPY --from=material /app/${MATERIAL_DIR} /app/${MATERIAL_DIR}

RUN yarn build

Expand All @@ -45,6 +115,7 @@ ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder --chown=nextjs:nextjs /app ./
COPY ./prisma /app/prisma

USER nextjs

Expand Down
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Gutenberg
# Gutenberg

[![Build and Test](https://github.com/OxfordRSE/gutenberg/actions/workflows/test.yml/badge.svg)](https://github.com/OxfordRSE/gutenberg/actions/workflows/test.yml)

Expand All @@ -20,7 +20,7 @@ To see our full documentation, please visit [our documentation site](https://blo

To get a development environment running, follow the instructions below:

## Getting started
## Getting started (installing locally)

Setting up a local development requires the following software:

Expand All @@ -29,7 +29,7 @@ Setting up a local development requires the following software:
- `node` version v18.19.1 or later - packaged with `npm`
- `corepack` version `0.28.0` or later - install with `npm install -g corepack`
- `yarn` version `3.3.0` or later - installed via `corepack` with `yarn --version`
- For developing the renderer rather than just materials, you'll also need a `postgres` instance
- For developing the full web application functionality rather than just previewing materials, you'll also need a `postgres` instance

### 1. Clone repository

Expand Down Expand Up @@ -104,6 +104,10 @@ This means that your edits will be reflected instantly.

Now everything should be set up for local development of the core systems.

## Getting started (using Docker-compose)

Gutenberg also has a deployable dev environment using docker-compose. If you wish to use this alternative then see [getting started using docker compose](blog.oxrse.uk/gutenberg/getting-started-docker-compose).

## Developing material

You can develop material by editing the `.material` folder.
Expand Down
37 changes: 37 additions & 0 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
version: '3.9'

x-vol-args: &args
volumes:
- ./.material:/app/.material

services:
db:
image: postgres
restart: always
shm_size: 128mb
environment:
POSTGRES_PASSWORD: super-secret-password
POSTGRES_USER: postgres
ports:
- "5432:5432"

gutenberg:
image: gutenberg
build:
context: .
dockerfile: Dockerfile
args:
CACHE_BUST: ${CACHE_BUST}
MATERIAL_METHOD: "pull"
MATERIAL_DIR: ".material"
YAML_TEMPLATE: "config/oxford.yaml"
ports:
- "3000:3000"
links:
- db
<<: *args
depends_on:
db:
condition: service_started
environment:
DATABASE_URL: postgresql://postgres:super-secret-password@db:5432
61 changes: 61 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Use postgres/example user/password credentials
version: "3.9"

services:
nginx:
image: nginx:${NGINX_IMAGE_TAG} # stable-alpine3.19
volumes:
- ./nginx:/etc/nginx/templates
ports:
- "80:8080"
environment:
- NGINX_HOST=localhost
- NGINX_PORT=8080
- NGINX_PROXY_PASS=http://gutenberg:3000
depends_on:
gutenberg:
condition: service_started

db:
image: postgres
restart: always
shm_size: 128mb
environment:
POSTGRES_PASSWORD: super-secret-password
POSTGRES_USER: postgres
ports:
- "5432:5432"
volumes:
- db-data:/var/lib/postgresql/data

gutenberg:
image: gutenberg
build:
context: .
dockerfile: Dockerfile
args:
CACHE_BUST: ${CACHE_BUST}
MATERIAL_METHOD: "pull"
MATERIAL_DIR: ".material"
YAML_TEMPLATE: "config/oxford.yaml"
links:
- db
depends_on:
db:
condition: service_started
environment:
DATABASE_URL: postgresql://postgres:super-secret-password@db:5432

qdrant:
image: qdrant
build:
context: qdrant/.
dockerfile: Dockerfile
ports:
- "6333:6333"
volumes:
- qdrant_data:/qdrant/storage

volumes:
db-data:
qdrant_data:
42 changes: 42 additions & 0 deletions docs/development/docker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
Title: Deploying with Docker-compose
permalink: /gutenberg/docker
---

Gutenberg can be deployed both locally and to production using docker-compose.

- `git` version 2.43.0 or later
- `docker` version 18.03 or later

Both of which will need to be installed following instructions for your system.

Then we can get started by cloning the repository with git and entering into it with `cd`:

```bash
git clone https://github.com/OxfordRSE/gutenberg.git`
cd gutenberg
```

From here we can simply run:

```
docker-compose up
```

which should make gutenberg available to you at http://localhost:3000. This will
build a Docker image the first time you run it (assuming you don't already have
an image called `gutenburg` in your local registry) from the local source code -
this might take a few minutes. If you want to force a rebuild after you've made
some changes you can append the `--build` flag after `up`, i.e.

```
docker-compose up --build
```

Although this isn't particularly quick. By default the compose setup will pull
the repo from the source defined in `config/oxford.yaml`, though you can change
this from inside the `dev-compose.yml`, either by changing the `YAML_TEMPLATE`
value (under `services.gutenberg.build.args`) to a different config yaml file or
changing `MATERIAL_METHOD` to `"copy"` to copy a locally checked out folder into
the container at build-time instead of pulling fresh - for more details on how
to pull material to edit locally follow the below section.
2 changes: 2 additions & 0 deletions docs/development/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ permalink: /development/

This will guide you through the process of setting up a development environment.

If you instead wish to build the application via docker then please refer to the [docker guide]({{"/development/docker" | relative_url }})

To see how to to build the docs, please see the [documentation guide]({{"/development/docs" | relative_url }}).

<!-- prettier-ignore -->
Expand Down
4 changes: 4 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#!/bin/bash

# Run migrations on the database
npx prisma migrate deploy

yarn cron &
yarn start
14 changes: 14 additions & 0 deletions nginx/default.conf.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
server {
listen ${NGINX_PORT};
server_name ${NGINX_HOST};

#access_log /var/log/nginx/host.access.log main;

location / {
proxy_pass ${NGINX_PROXY_PASS};
}

#error_page 404 /404.html;
}


3 changes: 3 additions & 0 deletions run-compose.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash
export CACHE_BUST=$(date +%s)
docker-compose build --build-arg CACHE_BUST=$CACHE_BUST