diff --git a/.docker/00-prepare-for-prod-dump.sql b/.docker/development/00-prepare-for-prod-dump.sql similarity index 100% rename from .docker/00-prepare-for-prod-dump.sql rename to .docker/development/00-prepare-for-prod-dump.sql diff --git a/.docker/Dockerfile b/.docker/development/Dockerfile similarity index 100% rename from .docker/Dockerfile rename to .docker/development/Dockerfile diff --git a/.docker/database-init.sql b/.docker/development/database-init.sql similarity index 100% rename from .docker/database-init.sql rename to .docker/development/database-init.sql diff --git a/.docker/entrypoint.sh b/.docker/development/entrypoint.sh similarity index 100% rename from .docker/entrypoint.sh rename to .docker/development/entrypoint.sh diff --git a/.docker/webpack-entrypoint.sh b/.docker/development/webpack-entrypoint.sh similarity index 100% rename from .docker/webpack-entrypoint.sh rename to .docker/development/webpack-entrypoint.sh diff --git a/.docker/production/Dockerfile b/.docker/production/Dockerfile new file mode 100644 index 00000000..7adc832a --- /dev/null +++ b/.docker/production/Dockerfile @@ -0,0 +1,193 @@ +################################# +# Variables # +################################# + +# Versioning +ARG RUBY_VERSION="3.0.6" +ARG BUNDLER_VERSION="2.3.20" +ARG NODEJS_VERSION="16" +ARG YARN_VERSION="1.22.22" + +# Packages +ARG BUILD_PACKAGES="git libicu-dev libpq-dev ca-certificates curl gnupg" +ARG RUN_PACKAGES="git graphicsmagick libicu-dev libpq5 poppler-utils libgeos-dev libpaper1" + +# Scripts +ARG PRE_INSTALL_SCRIPT="curl -sL https://deb.nodesource.com/setup_${NODEJS_VERSION}.x -o /tmp/nodesource_setup.sh && bash /tmp/nodesource_setup.sh" +ARG INSTALL_SCRIPT="node -v && npm -v && npm install -g yarn && yarn set version ${YARN_VERSION}" +ARG PRE_BUILD_SCRIPT +ARG BUILD_SCRIPT="yarn install && bundle exec rake assets:precompile" +ARG POST_BUILD_SCRIPT="echo \"(built at: $(date '+%Y-%m-%d %H:%M:%S'))\" > /app-src/BUILD_INFO" + +# Bundler specific +ARG BUNDLE_WITHOUT="development:metrics:test" + +# App specific +ARG RAILS_ENV="production" +ARG RACK_ENV="production" +ARG NODE_ENV="production" +ARG RAILS_HOST_NAME="needs-to-be-set.example.net" +ARG SECRET_KEY_BASE="needs-to-be-set" +ARG SKIP_MEMCACHE_CHECK="true" + +# Github specific +ARG GITHUB_SHA +ARG GITHUB_REPOSITORY +ARG GITHUB_REF_NAME +ARG BUILD_COMMIT="$GITHUB_SHA" +ARG BUILD_REPO="$GITHUB_REPOSITORY" +ARG BUILD_REF="$GITHUB_REF_NAME" + +# Runtime ENV vars +ARG SENTRY_CURRENT_ENV +ARG PS1="$SENTRY_CURRENT_ENV > " +ARG TZ="Europe/Zurich" + + +################################# +# Build Stage # +################################# + +FROM ruby:${RUBY_VERSION} AS build + +# arguments for steps +ARG PRE_INSTALL_SCRIPT +ARG BUILD_PACKAGES +ARG INSTALL_SCRIPT +ARG BUNDLER_VERSION +ARG PRE_BUILD_SCRIPT +ARG BUNDLE_WITHOUT +ARG BUILD_SCRIPT +ARG POST_BUILD_SCRIPT + +# arguments potentially used by steps +ARG NODE_ENV +ARG RACK_ENV +ARG RAILS_ENV +ARG RAILS_HOST_NAME +ARG SECRET_KEY_BASE +ARG TZ + +# Set build shell +SHELL ["/bin/bash", "-c"] + +# Use root user +USER root + +RUN bash -vxc "${PRE_INSTALL_SCRIPT:-"echo 'no PRE_INSTALL_SCRIPT provided'"}" + +# Install dependencies +RUN export DEBIAN_FRONTEND=noninteractive \ + && apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y --no-install-recommends ${BUILD_PACKAGES} \ + +RUN bash -vxc "${INSTALL_SCRIPT:-"echo 'no INSTALL_SCRIPT provided'"}" + +# Install specific versions of dependencies +RUN gem install bundler:${BUNDLER_VERSION} --no-document + +# TODO: Load artifacts + +# set up app-src directory +WORKDIR /app-src +COPY Gemfile Gemfile.lock ./ + +RUN bash -vxc "${PRE_BUILD_SCRIPT:-"echo 'no PRE_BUILD_SCRIPT provided'"}" + +# install gems and build the app +RUN bundle config set --local deployment 'true' \ + && bundle config set --local without ${BUNDLE_WITHOUT} \ + && bundle package \ + && bundle install \ + && bundle clean + +COPY . . + +RUN bash -vxc "${BUILD_SCRIPT:-"echo 'no BUILD_SCRIPT provided'"}" + +RUN bash -vxc "${POST_BUILD_SCRIPT:-"echo 'no POST_BUILD_SCRIPT provided'"}" + +# TODO: Save artifacts + +RUN rm -rf vendor/cache/ .git spec/ node_modules/ + + +################################# +# Run Stage # +################################# + +# This image will be replaced by Openshift +FROM ruby:${RUBY_VERSION}-slim AS app + +# Set runtime shell +SHELL ["/bin/bash", "-c"] + +# Add user +RUN adduser --disabled-password --uid 1001 --gid 0 --gecos "" app + +# arguments for steps +ARG RUN_PACKAGES +ARG BUNDLER_VERSION +ARG BUNDLE_WITHOUT + +# arguments potentially used by steps +ARG NODE_ENV +ARG RACK_ENV +ARG RAILS_ENV + +# data persisted in the image +ARG PS1 +ARG TZ +ARG BUILD_COMMIT +ARG BUILD_REPO +ARG BUILD_REF + +ENV PS1="${PS1}" \ + TZ="${TZ}" \ + BUILD_REPO="${BUILD_REPO}" \ + BUILD_REF="${BUILD_REF}" \ + BUILD_COMMIT="${BUILD_COMMIT}" \ + NODE_ENV="${NODE_ENV}" \ + RAILS_ENV="${RAILS_ENV}" \ + RACK_ENV="${RACK_ENV}" \ + # support bin-stubs \ + HOME="/app-src" \ + PATH="/app-src/bin:${PATH}" + +# Install dependencies, remove apt! +RUN export DEBIAN_FRONTEND=noninteractive \ + && apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y ${RUN_PACKAGES} vim curl less \ + && apt-get clean \ + && rm -rf /var/cache/apt/archives/* /var/lib/apt/lists/* /tmp/* /var/tmp/* \ + && truncate -s 0 /var/log/*log + +# Copy deployment ready source code from build +COPY --from=build /app-src /app-src +WORKDIR /app-src + +# Create pids folder for puma and +# set group permissions to folders that need write permissions +RUN mkdir -p tmp/pids \ + && chgrp 0 /app-src \ + && chgrp -R 0 /app-src/tmp \ + && chgrp -R 0 /app-src/log \ + && chmod u+w,g=u /app-src \ + && chmod -R u+w,g=u /app-src/tmp \ + && chmod -R u+w,g=u /app-src/log + +# Install specific versions of dependencies +RUN gem install bundler:${BUNDLER_VERSION} --no-document + +# Use cached gems +RUN bundle config set --local deployment 'true' \ + && bundle config set --local without ${BUNDLE_WITHOUT} \ + && bundle install + +USER 1001 + +ENTRYPOINT ["entrypoint.sh"] +CMD ["puma"] + diff --git a/.docker/production/entrypoint.sh b/.docker/production/entrypoint.sh new file mode 100755 index 00000000..ff5bb32d --- /dev/null +++ b/.docker/production/entrypoint.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -euo pipefail + +# Run deface compilation. +if [ "$RAILS_ENV" = "production" ] && [ ! -d "app/compiled_views" ]; then + SKIP_MEMCACHE_CHECK=1 DEFACE_ENABLED=1 bundle exec rails deface:precompile +else + echo "Skipping deface compilation because it is already done or not needed." +fi + +# Run deface compilation. +if [ "$RAILS_ENV" = "production" ] && [ ! -d "app/compiled_views" ]; then + SKIP_MEMCACHE_CHECK=1 DEFACE_ENABLED=1 bundle exec rails deface:precompile +else + echo "Skipping deface compilation because it is already done or not needed." +fi + +exec "$@" diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index b59c0812..00000000 --- a/Dockerfile +++ /dev/null @@ -1,155 +0,0 @@ -################################################################## -# Build Stage # -################################################################## - -FROM ruby:3.0.6 AS build - -ARG BUILD_PACKAGES="git libicu-dev libpq-dev ca-certificates curl gnupg" -ARG BUILD_SCRIPT="set -uex \ - && mkdir -p /etc/apt/keyrings \ - && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \ - && echo \"deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main\" > /etc/apt/sources.list.d/nodesource.list \ - && apt-get update \ - && apt-get install nodejs -y \ - && npm install -g yarn \ - && yarn set version 1.22.19" -ARG BUNDLE_WITHOUT="development:metrics:test" -ARG BUNDLER_VERSION="2.4.18" -ARG POST_BUILD_SCRIPT="bundle exec rails assets:precompile" -ARG SKIP_MEMCACHE_CHECK="true" -ARG RAILS_ENV="production" -ARG SECRET_KEY_BASE="thisneedstobeset" - -# Set build shell -SHELL ["/bin/bash", "-c"] - -# Use root user -USER root - -# Install packages needed at buildtime -RUN apt-get update \ - && apt-get upgrade -y \ - && apt-get install -y ${BUILD_PACKAGES} - -# Installs nodejs as a dependency -RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash - \ - && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg -o /root/yarn-pubkey.gpg && apt-key add /root/yarn-pubkey.gpg \ - && echo "deb https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list \ && apt-get update \ - && DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends \ - nodejs \ - && apt-get clean \ - && rm -rf /var/cache/apt/archives/* \ - && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \ - && truncate -s 0 /var/log/*log - -RUN [[ ${BUILD_SCRIPT} ]] && bash -c "${BUILD_SCRIPT}" - -# Install specific versions of dependencies -RUN gem install bundler:${BUNDLER_VERSION} --no-document - -# TODO: Load artifacts - -COPY ./Gemfile ./Gemfile.lock /app-src/ -WORKDIR /app-src - -# Run deployment -RUN bundle config set --local deployment 'true' \ - && bundle config set --local without ${BUNDLE_WITHOUT} \ - && bundle package \ - && bundle install \ - && bundle clean - -COPY ./package.json ./yarn.lock /app-src/ -RUN yarn - -# set up app-src directory -COPY . /app-src - -RUN [[ ${POST_BUILD_SCRIPT} ]] && bash -c "${POST_BUILD_SCRIPT}" - -# TODO: Save artifacts - -RUN rm -rf vendor/cache/ .git - -################################################################## -# Run Stage # -################################################################## - -# This image will be replaced by Openshift -FROM ruby:3.0.6-slim AS app - -# Set runtime shell -SHELL ["/bin/bash", "-c"] - -# Add user -RUN adduser --disabled-password --uid 1001 --gid 0 --gecos "" --shell /bin/bash app -# RUN adduser --disabled-password --uid 1002 --gid 0 --gecos "" clamav - -ARG BUNDLE_WITHOUT='development:metrics:test' -ARG BUNDLER_VERSION="2.3.22" -ARG RUN_PACKAGES="clamav clamav-daemon git graphicsmagick libicu-dev libpq5 nodejs poppler-utils libgeos-dev" -ARG PS1='$SENTRY_CURRENT_ENV:$PWD$ ' -ENV PS1=$PS1 -ARG TZ="Europe/Zurich" -ENV TZ=$TZ -ENV PATH=/app-src/bin:$PATH - - -# Prepare apt-get -RUN export DEBIAN_FRONTEND=noninteractive \ - && apt-get update \ - && apt-get upgrade -y \ - # Install libpaper1 seperately, because statx is broken on APPUiO build - && apt-get install -y ucf \ - && apt-get download libpaper1 \ - && dpkg --unpack libpaper1*.deb \ - && rm /var/lib/dpkg/info/libpaper1\:amd64.postinst \ - && dpkg --configure libpaper1 \ - && apt-get install -yf \ - && rm libpaper1*.deb \ - # Install the Packages we need at runtime - && apt-get -y install ${RUN_PACKAGES} \ - vim curl \ - # HACK: Maybe move to different image... gives clamav the right to execute - && usermod -a -G 0 clamav \ - # Clean up after ourselves - && unset DEBIAN_FRONTEND \ - # Install specific versions of dependencies - && gem install bundler:${BUNDLER_VERSION} --no-document - -# Copy deployment ready source code from build -COPY --from=build /app-src /app-src -COPY docker/ / -WORKDIR /app-src - -RUN chgrp -R 0 /app-src \ - && chmod -R u+w,g=u /app-src -# HACK: Maybe move to different image... Set group permissions to app folder and help clamav to start -RUN mkdir /var/run/clamav \ - && chown clamav /run/clamav \ - && sed -i 's/^chown/# chown/' /etc/init.d/clamav-daemon \ - && chgrp -R 0 \ - /app-src \ - /var/log/clamav \ - /var/lib/clamav \ - /var/run/clamav \ - /run/clamav \ - && chmod -R u+w,g=u \ - /app-src \ - /var/log/clamav \ - /var/lib/clamav \ - /var/run/clamav \ - /run/clamav \ - && freshclam - - -ENV HOME=/app-src - -USER 1000 - -# Use cached gems -RUN bundle config set --local deployment 'true' \ - && bundle config set --local without ${BUNDLE_WITHOUT} \ - && bundle - -CMD ["bundle", "exec", "puma", "-t", "8"] diff --git a/docker-compose.yml b/docker-compose.yml index 4963fb42..6e1ce47a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ services: app: &app build: context: . - dockerfile: ./.docker/Dockerfile + dockerfile: ./.docker/development/Dockerfile target: dev volumes: - .:/usr/src/app @@ -26,7 +26,7 @@ services: ports: - 3000:3000 command: bundle exec puma - entrypoint: ./.docker/entrypoint.sh + entrypoint: ./.docker/development/entrypoint.sh tty: true stdin_open: true pg: @@ -39,8 +39,8 @@ services: - 5432:5432 volumes: - pg-data:/var/lib/postgresql/data - #- ./.docker/00-prepare-for-prod-dump.sql:/docker-entrypoint-initdb.d/00-prepare-for-prod-dump.sql - #- ./.docker/database-init.sql:/docker-entrypoint-initdb.d/database-init.sql + #- ./.docker/development/00-prepare-for-prod-dump.sql:/docker-entrypoint-initdb.d/00-prepare-for-prod-dump.sql + #- ./.docker/development/database-init.sql:/docker-entrypoint-initdb.d/database-init.sql cache: image: memcached:1.5-alpine command: [ memcached, -l, '0.0.0.0', -p, '11211' ] @@ -49,7 +49,7 @@ services: depends_on: [] ports: - 3035:3035 - entrypoint: ./.docker/webpack-entrypoint.sh + entrypoint: ./.docker/development/webpack-entrypoint.sh command: [ 'bin/webpack-dev-server' ] mail: