diff --git a/.gitignore b/.gitignore index 0f7fe87..9fc184e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ tmp/* spec/output.log .byebug_history storage/ + +# Docker +docker/colore/variables.env diff --git a/README.md b/README.md index be1576a..eef080b 100644 --- a/README.md +++ b/README.md @@ -381,6 +381,33 @@ ARGS="$@" exec java -jar /usr/share/java/tika-app.jar $ARGS ``` +## Docker + +A multi-container Docker application defined in `docker-compose.yml` is +provided to speed up Colore installation on development machines. + +1. Copy `docker/colore/variables.env.example` to `docker/colore/variables.env` +2. Run `docker compose up` +3. Have fun with Colore up and running on `http://localhost:9240/` + +Note that some features of Colore, like synchronous HTML to PDF conversion, may +need to access stylesheets and JavaScripts on the host machine. In such cases, +please make sure that: + +1. The web application server allows for concurrent HTTP connections +2. The web application generates absolute urls to stylesheets and JavaScripts + (`config.asset_host` on a Rails application) +3. The container is capable of reaching assets on the host machine (it is + possible to use `host.docker.internal` on macOS) + +### Run tests in the container + +It is possible to run specs in the container by executing: + +``` +$ docker compose run colore bundle exec rspec +``` + ## Security notes Colore does not implement any authentication mechanism. It is up to you to diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..a033020 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,58 @@ +services: + colore: + platform: linux/amd64 + build: + context: . + dockerfile: ./docker/colore/Dockerfile + args: + RACK_ENV: development + container_name: colore + depends_on: + - redis + - sidekiq + env_file: + - ./docker/colore/variables.env + environment: + RACK_ENV: development + networks: + - colore + ports: + - 9240:9240 + restart: on-failure + volumes: + - storage:/colore/storage + redis: + container_name: redis + image: redis:5.0-alpine + networks: + - colore + restart: on-failure + volumes: + - redis:/data + sidekiq: + platform: linux/amd64 + build: + context: . + dockerfile: ./docker/colore/Dockerfile + args: + RACK_ENV: development + command: bundle exec sidekiq -C config/sidekiq.yml -r ./lib/sidekiq_app.rb + container_name: sidekiq + depends_on: + - redis + env_file: + - ./docker/colore/variables.env + environment: + RACK_ENV: development + networks: + - colore + restart: on-failure + volumes: + - storage:/colore/storage + +volumes: + storage: + redis: + +networks: + colore: diff --git a/docker/colore/Dockerfile b/docker/colore/Dockerfile new file mode 100644 index 0000000..5b0912f --- /dev/null +++ b/docker/colore/Dockerfile @@ -0,0 +1,91 @@ +FROM ruby:2.6.10 + +RUN apt update && apt install -y \ + build-essential \ + imagemagick \ + libmagic-dev \ + tesseract-ocr + +# Needed to get the latest libreoffice +# Ref: https://wiki.debian.org/LibreOffice#Using_Debian_backports +RUN echo 'deb http://deb.debian.org/debian bullseye-backports main contrib non-free' >> /etc/apt/sources.list +RUN apt update && apt install -y -t bullseye-backports libreoffice + +# Please keep using version 0.12.3 +# With newer versions of wkhtmltopdf, wkhtmltopdf/wkhtmltopdf#1524 and +# wkhtmltopdf/wkhtmltopdf#3241 will affect Colore's PDF output +# TODO: implement PDF comparison specs and update this library +ARG WKHTMLTOPDF_VERSION=0.12.3 +ARG WKHTMLTOPDF_MD5=6e991e1a1f3293ab673afa015703ef86 + +RUN wget --quiet https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/${WKHTMLTOPDF_VERSION}/wkhtmltox-${WKHTMLTOPDF_VERSION}_linux-generic-amd64.tar.xz -O wkhtmltox.tar.xz && \ + echo "${WKHTMLTOPDF_MD5} wkhtmltox.tar.xz" > MD5SUMS && \ + md5sum -c MD5SUMS && \ + tar -xf wkhtmltox.tar.xz && \ + mv wkhtmltox/bin/wkhtmltopdf /usr/local/bin && \ + rm -rf wkhtmltox wkhtmltox.tar.xz MD5SUMS + +ARG TIKA_VERSION=2.9.2 + +RUN wget --quiet https://archive.apache.org/dist/tika/KEYS -O tika-keys && \ + wget --quiet https://archive.apache.org/dist/tika/${TIKA_VERSION}/tika-app-${TIKA_VERSION}.jar.asc -O tika-app.jar.asc && \ + wget --quiet https://archive.apache.org/dist/tika/${TIKA_VERSION}/tika-app-${TIKA_VERSION}.jar -O tika-app.jar && \ + gpg --import tika-keys && \ + gpg --verify tika-app.jar.asc tika-app.jar && \ + rm -f tika-app.jar.asc tika-keys && \ + mv tika-app.jar /usr/share/java/tika-app.jar && \ + echo '#!/bin/sh\n\nARGS="$@"\n\n[ $# -eq 0 ] && ARGS="--help"\n\nexec java -jar /usr/share/java/tika-app.jar $ARGS\n' > /usr/local/bin/tika && \ + chmod +x /usr/local/bin/tika + +ENV APP_DIR /colore + +EXPOSE 9240 + +WORKDIR $APP_DIR + +# Create application user and add permissions +RUN groupadd --gid 1000 colore && \ + useradd --uid 1000 --gid colore --shell /bin/bash --create-home colore && \ + chown -R colore:colore $APP_DIR && \ + chmod -R 755 $APP_DIR + +# Switch to application user +USER colore + +RUN mkdir -p log +RUN mkdir -p tmp/pids + +ARG RACK_ENV +ENV RACK_ENV=${RACK_ENV:-production} + +RUN gem install bundler -v 2.4.22 + +# Copy command always runs as root +COPY --chown=colore:colore Gemfile . +COPY --chown=colore:colore Gemfile.lock . + +RUN echo $RACK_ENV +RUN \ + if [ "$RACK_ENV" = "development" ] || [ "$RACK_ENV" = "test" ]; then \ + bundle install --retry 10; \ + else \ + bundle config set deployment 'true' && bundle --retry 10; \ + fi + +COPY --chown=colore:colore bin ./bin +COPY --chown=colore:colore config ./config +COPY --chown=colore:colore lib ./lib +COPY --chown=colore:colore spec ./spec +COPY --chown=colore:colore config.ru . +COPY --chown=colore:colore Rakefile . +COPY --chown=colore:colore unicorn.rb . + +# Create the shared volume so it will be owned by the application user +RUN mkdir -p storage + +COPY --chown=colore:colore docker/colore/docker-entrypoint.sh ./bin +RUN chmod +x ./bin/docker-entrypoint.sh + +ENTRYPOINT ["/colore/bin/docker-entrypoint.sh"] + +CMD ["bundle", "exec", "unicorn"] diff --git a/docker/colore/docker-entrypoint.sh b/docker/colore/docker-entrypoint.sh new file mode 100755 index 0000000..721727a --- /dev/null +++ b/docker/colore/docker-entrypoint.sh @@ -0,0 +1,8 @@ +#!/bin/sh +set -e + +pwd + +rm -f tmp/pids/*.pid + +exec "$@" diff --git a/docker/colore/variables.env.example b/docker/colore/variables.env.example new file mode 100644 index 0000000..39689e1 --- /dev/null +++ b/docker/colore/variables.env.example @@ -0,0 +1,4 @@ +LANG=en_US.UTF-8 +LANGUAGE=en_US.UTF-8 +LC_ALL=C.UTF-8 +REDIS_URL=redis://redis:6379/4