From bb58bd22558b005cc6981054a2ffb8877bb7e945 Mon Sep 17 00:00:00 2001 From: Aman7123 Date: Tue, 6 Jan 2026 21:18:32 -0500 Subject: [PATCH] Update docker, compose, db seeding, and docs --- Dockerfile | 41 +++++++++------- README.md | 35 ++++++++++++-- config/initializers/sidekiq.rb | 3 ++ db/seeds.rb | 8 +++- docker-compose.yml | 86 ++++++++++++++-------------------- 5 files changed, 98 insertions(+), 75 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8a7a0bdc..296cdf5c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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/* \ No newline at end of file +RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +ENTRYPOINT ["/bin/sh", "-c", "./docker-entrypoint.sh"] \ No newline at end of file diff --git a/README.md b/README.md index 87806c32..3f0c79ef 100644 --- a/README.md +++ b/README.md @@ -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) @@ -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 diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index 1ff24e4f..658a86c7 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -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 } } diff --git a/db/seeds.rb b/db/seeds.rb index 34f58497..99e8f5dd 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -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! \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index ac442381..89144a59 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -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 \ No newline at end of file + 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