Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 24 additions & 17 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
# Use the Ruby 3.2.2 image from Docker Hub as the base image (https://hub.docker.com/_/ruby)
FROM ruby:3.2.2
FROM node:20.19-alpine AS builder

RUN apt-get update -qq && apt-get install -y postgresql-client git libvips npm
RUN npm install --global yarn

WORKDIR /app
WORKDIR /code

ARG RAILS_ENV
ARG VITE_HOSTNAME
ARG VITE_IIIF_MANIFEST_ITEM_LIMIT
ARG VITE_MAP_TILER_KEY
ARG VITE_POSTMARK_INTERVAL

# Add Rails gems
COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock
COPY client/ .

RUN bundle install
ARG GENERATE_SOURCEMAP=false
ARG DISABLE_ESLINT_PLUGIN=true

RUN yarn install && yarn build

FROM ruby:3.4.4

RUN apt-get update -qq && apt-get install -y postgresql-client git libvips npm

WORKDIR /app

COPY . .
COPY --from=builder /code/build /app/public

ENV DISABLE_ESLINT_PLUGIN=true
ENV GENERATE_SOURCEMAP=false
ENV NODE_OPTIONS="--max-old-space-size=16384"
RUN bundle install

# Build and deploy React front-end
RUN yarn build && yarn deploy
# COnfigure some runtime defaults for rails and node
ENV RAILS_ENV=docker
ENV RAILS_LOG_TO_STDOUT=true
ENV RAILS_SERVE_STATIC_FILES=true
ENV NODE_OPTIONS="--max-old-space-size=16384"

# Clean up APT when done.
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

ENTRYPOINT ["/bin/sh", "-c", "./docker-entrypoint.sh"]
35 changes: 30 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

- macOS or Linux
- Ruby version that matches the `.ruby-version` file. ([rbenv](https://github.com/rbenv/rbenv) is recommended for managing Ruby versions)
- Node 18 ([nvm](https://github.com/nvm-sh/nvm) is likewise recommended)
- Node 20.19 ([nvm](https://github.com/nvm-sh/nvm) is likewise recommended)
- Postgres (this template is confirmed to work with Postgres 18, but any reasonably recent version should work)
- Heroku CLI (optional, if you want to deploy on Heroku)

Expand All @@ -30,11 +30,36 @@ To install Flow types run `yarn flow-typed install`. To run Flow server run `yar

## Docker

#### Prerequsites
To run via Docker requires a IIIF Cloud instance as well. This can be run as a separate Docker application, or pointed to a IIIF Cloud application hosted somewhere else. All that's required is the `IIIF_CLOUD_*` environment variables are set properly and a MapTiler account/API key.
### Prerequisites

#### Running
To run via a Docker container (for development or production) set your environment variables in `.env`, you can use `.env.example` as a template. If an image has not yet been built, run `docker compose up --build` to build the image and start the container. Subsequent starts of the container can be done with `docker compose up` if no code changes have been made.
#### Required: S3 (AWS)
The default Docker setup requires an S3 bucket for storage.
Make sure the bucket already exists and the credentials have permission to read/write to it.

#### Required: MapTiler API Key
Map rendering requires a MapTiler Cloud API key. You can obtain a testing key by following the MapTiler docs:
https://docs.maptiler.com/cloud/api/authentication-key/#get-a-testing-key

#### Optional: IIIF Cloud
IIIF Cloud is only required for IIIF-related functionality. The app can start without IIIF configured, but certain features will not work.

### Running

#### First-time run (recommended)
This starts the database in the background, waits for it to initialize, then starts the app with the required environment variables.

```bash
dc up db -d && \
sleep 35 && \
AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \
AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
AWS_REGION=${AWS_REGION} \
AWS_BUCKET_NAME=${AWS_BUCKET_NAME} \
VITE_MAP_TILER_KEY=${VITE_MAP_TILER_KEY} \
dc up app
```

**Note:** For a long term solution rename `.env.example` to `.env` to use with the Compose [env_file](https://docs.docker.com/compose/how-tos/environment-variables/set-environment-variables/#use-the-env_file-attribute) attribute

## Production

Expand Down
3 changes: 3 additions & 0 deletions config/initializers/sidekiq.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
require 'sidekiq'
require 'sidekiq/job'

if Rails.env.production? || Rails.env.staging?
Sidekiq.configure_server do |config|
config.redis = { ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE } }
Expand Down
8 changes: 7 additions & 1 deletion db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,10 @@
#
# movies = Movie.create([{ name: "Star Wars" }, { name: "Lord of the Rings" }])
# Character.create(name: "Luke", movie: movies.first)
CoreDataConnector::User.create!(name: 'Administrator', email: 'admin@example.com', password: 'password', password_confirmation: 'password', admin: true)
admin = CoreDataConnector::User.find_or_initialize_by(email: "admin@example.com")
admin.assign_attributes(
name: "Administrator",
password: "P@ssw0rd",
role: "admin"
)
admin.save!
86 changes: 34 additions & 52 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,66 +1,48 @@
version: "3.5"
services:
app:
build:
args:
- RAILS_ENV=docker
- VITE_HOSTNAME=$VITE_HOSTNAME
- VITE_IIIF_MANIFEST_ITEM_LIMIT=$VITE_IIIF_MANIFEST_ITEM_LIMIT
- VITE_MAP_TILER_KEY=$VITE_MAP_TILER_KEY
- VITE_HOSTNAME=${VITE_HOSTNAME:-http://localhost:3000}
- VITE_MAP_TILER_KEY=${VITE_MAP_TILER_KEY}
- VITE_IIIF_MANIFEST_ITEM_LIMIT=${VITE_IIIF_MANIFEST_ITEM_LIMIT:-1000}
- VITE_POSTMARK_INTERVAL=${VITE_POSTMARK_INTERVAL:-24}
context: .
container_name: core-data-cloud-app
depends_on:
- db
entrypoint: /app/docker-entrypoint.sh
environment:
- AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
- AWS_REGION=$AWS_REGION
- AWS_BUCKET_NAME=$AWS_BUCKET_NAME
- DATABASE_HOST=db
- DATABASE_USERNAME=$DATABASE_USERNAME
- DATABASE_PASSWORD=$DATABASE_PASSWORD
- DATABASE_NAME=$DATABASE_NAME
- DATABASE_POOL=$DATABASE_POOL
- DATABASE_PORT=5432
- IIIF_CLOUD_API_KEY=$IIIF_CLOUD_API_KEY
- IIIF_CLOUD_URL=$IIIF_CLOUD_URL
- IIIF_CLOUD_PROJECT_ID=$IIIF_CLOUD_PROJECT_ID
- IIIF_MANIFEST_ITEM_LIMIT=$IIIF_MANIFEST_ITEM_LIMIT
- PORT=3000
- RAILS_ENV=docker
- RAILS_LOG_TO_STDOUT=true
- RAILS_SERVE_STATIC_FILES=true
- SECRET_KEY_BASE=$SECRET_KEY_BASE
networks:
- default
- shared
AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
AWS_REGION: $AWS_REGION
AWS_BUCKET_NAME: $AWS_BUCKET_NAME
DATABASE_HOST: ${DATABASE_HOST:-db}
DATABASE_USERNAME: ${DATABASE_USERNAME:-core_data}
DATABASE_PASSWORD: ${DATABASE_PASSWORD:-change-me}
DATABASE_NAME: ${DATABASE_NAME:-core_data}
IIIF_CLOUD_API_KEY: $IIIF_CLOUD_API_KEY
IIIF_CLOUD_URL: $IIIF_CLOUD_URL
IIIF_CLOUD_PROJECT_ID: ${IIIF_CLOUD_PROJECT_ID:-1}
IIIF_MANIFEST_ITEM_LIMIT: ${IIIF_MANIFEST_ITEM_LIMIT:-1000}
SECRET_KEY_BASE: ${SECRET_KEY_BASE:-339485u34895u4398u58394u543u59834u958u347y62347632t47235467235674}
# TYPESENSE_API_KEY: ${TYPESENSE_API_KEY:-75bcbf52-c291-4121-acf2-288c8c762b3e}
ports:
- "3000:3000"
working_dir: /app
- 3000:3000
db:
container_name: core-data-cloud-db
environment:
- POSTGRES_PASSWORD=$DATABASE_PASSWORD
- POSTGRES_USER=$DATABASE_USERNAME
- PGDATA=$DATABASE_VOLUME:/var/lib/postgresql/data/pgdata
image: postgis/postgis:16-3.4-alpine
ports:
- "54334:5432"
volumes:
- $DATABASE_VOLUME:/var/lib/postgresql/data
working_dir: /app
typesense:
container_name: core-data-cloud-typesense
environment:
TYPESENSE_API_KEY: $TYPESENSE_API_KEY
TYPESENSE_DATA_DIR: /data
image: typesense/typesense:0.25.1
ports:
- "8108:8108"
volumes:
- $TYPESENSE_VOLUME:/data
networks:
shared:
name: pssexternal
external: true
POSTGRES_PASSWORD: ${DATABASE_PASSWORD:-change-me}
POSTGRES_USER: ${DATABASE_USERNAME:-core_data}
expose:
- 5432
# If you need to reconcile, enable this section and include corresponding API key in app service
# typesense:
# image: typesense/typesense:0.25.1
# container_name: core-data-cloud-typesense
# environment:
# TYPESENSE_API_KEY: ${TYPESENSE_API_KEY:-75bcbf52-c291-4121-acf2-288c8c762b3e}
# TYPESENSE_DATA_DIR: /data
# expose:
# - 8108
# volumes:
# - ${TYPESENSE_VOLUME:-./_data/ts_vol}:/data