Skip to content

Commit

Permalink
First shot at a Dockerfile for Pulfalight.
Browse files Browse the repository at this point in the history
  • Loading branch information
tpendragon committed Jan 9, 2024
1 parent 3eaee9a commit 0e22c7c
Show file tree
Hide file tree
Showing 4 changed files with 284 additions and 0 deletions.
30 changes: 30 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.git/
log/*
!log/.keep
app/assets/builds/*
!app/assets/builds/.keep
node_modules/
public/assets/
public/packs/
public/packs-test/
public/packs-dev/
public/vite-dev/
public/vite-test/
public/vite/
storage/*
!storage/.keep
tmp/*
!tmp/.keep

.bundle
.byebug_history
.dockerignore
.env*
!.env.example
config/master.key
docker-compose.override.yml
yarn-error.log
yarn-debug.log*
.yarn-integrity
docker
spec
24 changes: 24 additions & 0 deletions bin/docker-entrypoint-web
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bash

set -e

# Always keep this here as it ensures your latest built assets make their way
# into your volume persisted public directory.
cp -r /public /app

# Sprockets will use the first sprockets file it finds not the latest one. We
# need to delete all of the old sprockets files except for the one that was
# last built into the image. That's what the code below does.

# shellcheck disable=SC2125
manifest_files=/app/public/assets/.sprockets-manifest-*.json

if compgen -G "${manifest_files}" > /dev/null 2>&1; then
# shellcheck disable=SC2086,SC2061
find \
${manifest_files} \
-type f ! -name "$(basename /public/assets/.sprockets-manifest-*.json)" \
-delete
fi

exec "$@"
127 changes: 127 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
x-app: &default-app
build:
context: "."
dockerfile: "./docker/Dockerfile"
target: "app"
args:
- "UID=${UID:-1000}"
- "GID=${GID:-1000}"
- "RAILS_ENV=${RAILS_ENV:-production}"
- "NODE_ENV=${NODE_ENV:-production}"
depends_on:
postgres:
condition: "service_started"
required: false
redis:
condition: "service_started"
required: false
env_file:
- "./docker/.env"
restart: "${DOCKER_RESTART_POLICY:-unless-stopped}"
stop_grace_period: "3s"
tty: true
volumes:
- "${DOCKER_WEB_VOLUME:-./public:/app/public}"

x-assets: &default-assets
build:
context: "."
dockerfile: "./docker/Dockerfile"
target: "assets"
args:
- "UID=${UID:-1000}"
- "GID=${GID:-1000}"
- "RAILS_ENV=${RAILS_ENV:-production}"
- "NODE_ENV=${NODE_ENV:-production}"
env_file:
- "./docker/.env"
profiles: ["assets"]
restart: "${DOCKER_RESTART_POLICY:-unless-stopped}"
stop_grace_period: "3s"
tty: true
volumes:
- ".:/app"

services:
postgres:
deploy:
resources:
limits:
cpus: "${DOCKER_POSTGRES_CPUS:-0}"
memory: "${DOCKER_POSTGRES_MEMORY:-0}"
environment:
POSTGRES_USER: "${POSTGRES_USER}"
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
# POSTGRES_DB: "${POSTGRES_DB}"
image: "postgres:16.1-bookworm"
profiles: ["dev"]
restart: "${DOCKER_RESTART_POLICY:-unless-stopped}"
stop_grace_period: "3s"
volumes:
- "postgres:/var/lib/postgresql/data"

redis:
deploy:
resources:
limits:
cpus: "${DOCKER_REDIS_CPUS:-0}"
memory: "${DOCKER_REDIS_MEMORY:-0}"
image: "redis:7.2.3-bookworm"
profiles: ["dev"]
restart: "${DOCKER_RESTART_POLICY:-unless-stopped}"
stop_grace_period: "3s"
volumes:
- "redis:/data"
solr:
image: "solr:8.4"
profiles: ["dev"]
volumes:
- "./solr/conf:/core/conf"
command: "solr-precreate core /core"

web:
<<: *default-app
deploy:
resources:
limits:
cpus: "${DOCKER_WEB_CPUS:-0}"
memory: "${DOCKER_WEB_MEMORY:-0}"
depends_on:
postgres:
condition: "service_started"
required: false
redis:
condition: "service_started"
required: false
migration:
condition: "service_started"
required: false
healthcheck:
test: "${DOCKER_WEB_HEALTHCHECK_TEST:-curl localhost:8000/up}"
interval: "60s"
timeout: "3s"
start_period: "5s"
retries: 3
ports:
- "${DOCKER_WEB_PORT_FORWARD:-127.0.0.1:8000}:${PORT:-8000}"
profiles: ["web"]

worker:
<<: *default-app
command: "bundle exec sidekiq -C config/sidekiq.yml"
entrypoint: []
deploy:
resources:
limits:
cpus: "${DOCKER_WORKER_CPUS:-0}"
memory: "${DOCKER_WORKER_MEMORY:-0}"
profiles: ["worker"]
migration:
<<: *default-app
entrypoint: []
command: "bash -c \"bundle exec rake db:create && bundle exec rake db:migrate\""
restart: no

volumes:
postgres: {}
redis: {}
103 changes: 103 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
FROM ruby:3.1.0-slim-bullseye AS assets

WORKDIR /app

ARG UID=1000
ARG GID=1000
ENV NVM_DIR /usr/local/nvm
ARG NODE_VERSION=18.18.0
ENV NODE_VERSION="${NODE_VERSION}"

RUN bash -c "set -o pipefail && apt-get update \
&& apt-get install -y --no-install-recommends build-essential curl git libpq-dev python3-pip \
&& mkdir -p /usr/local/nvm \
&& curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash \
&& source $NVM_DIR/nvm.sh \
&& nvm install $NODE_VERSION \
&& nvm alias default $NODE_VERSION \
&& nvm use default \
&& npm install --global yarn \
&& yarn global add node-gyp \
&& rm -rf /var/lib/apt/lists/* /usr/share/doc /usr/share/man \
&& apt-get clean \
&& groupadd -g \"${GID}\" ruby \
&& useradd --create-home --no-log-init -u \"${UID}\" -g \"${GID}\" ruby \
&& mkdir /node_modules && chown ruby:ruby -R /node_modules /app"
ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH

USER ruby

COPY --chown=ruby:ruby Gemfile* ./
RUN bundle config --global frozen 1 && bundle config set --local without 'development test' && bundle install

COPY --chown=ruby:ruby package.json *yarn* ./
RUN yarn install

ARG RAILS_ENV="production"
ARG NODE_ENV="production"
ENV RAILS_ENV="${RAILS_ENV}" \
NODE_ENV="${NODE_ENV}" \
PATH="${PATH}:/home/ruby/.local/bin:/node_modules/.bin" \
USER="ruby"

COPY --chown=ruby:ruby . .

RUN if [ "${RAILS_ENV}" != "development" ]; then \
SECRET_KEY_BASE=1 rails assets:precompile; fi

CMD ["bash"]

###############################################################################

FROM ruby:3.1.0-slim-bullseye AS app

WORKDIR /app

ARG UID=1000
ARG GID=1000
ENV NVM_DIR /usr/local/nvm
ARG NODE_VERSION=18.18.0
ENV NODE_VERSION="${NODE_VERSION}"

RUN apt-get update \
&& apt-get install -y --no-install-recommends build-essential python3-pip curl libpq-dev \
&& rm -rf /var/lib/apt/lists/* /usr/share/doc /usr/share/man \
&& apt-get clean \
&& groupadd -g "${GID}" ruby \
&& useradd --create-home --no-log-init -u "${UID}" -g "${GID}" ruby \
&& chown ruby:ruby -R /app
ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH
# We have to install NodeJS in the app until we don't have execjs for the
# bootstrap gem.
RUN bash -c "set -o pipefail && \
mkdir -p /usr/local/nvm \
&& curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash \
&& source $NVM_DIR/nvm.sh \
&& nvm install $NODE_VERSION \
&& nvm alias default $NODE_VERSION \
&& nvm use default"

USER ruby

COPY --chown=ruby:ruby bin/ ./bin
RUN chmod 0755 bin/*

ARG RAILS_ENV="production"
ENV RAILS_ENV="${RAILS_ENV}" \
PATH="${PATH}:/home/ruby/.local/bin" \
USER="ruby"

COPY --chown=ruby:ruby --from=assets /usr/local/bundle /usr/local/bundle
COPY --chown=ruby:ruby --from=assets /app/public /public
COPY --chown=ruby:ruby . .
RUN bundle config --global frozen 1
RUN bundle config set --local without 'development test'
RUN bundle install

ENTRYPOINT ["/app/bin/docker-entrypoint-web"]

EXPOSE 8000

CMD ["rails", "s", "-p", "8000"]

0 comments on commit 0e22c7c

Please sign in to comment.