Solidus on Rails 7 and Docker

Solidus on Rails 7 and Docker

I've decided to jump into the world of e-commerce engines built on Ruby on Rails. I'm gonna start by tinkering around with Solidus. Nothing too fancy, just some notes for my future self in case I need it for a client's project.

I wonder if it's possible to run Solidus on the latest Ruby on Rails version with all its features, like Hotwire, TurboStream, TurboFrame, and Stimulus. Perhaps it could lead me to a series of articles. Also, I am going to record live coding videos to practice my English.

The goal of this article - run Solidus inside docker.

Since I love to keep my projects in Docker, I usually use Nick Janitakis's template. Nick has done an amazing job. Instructions are just beyond expectations. Check it out https://github.com/nickjj/docker-rails-example.

It shouldn't be so hard to make it work. But you never know. Every time you deal with third-party engines of such complexity, things could turn out in an unpredictable way.

Installing Ruby on Rails 7 new project using Docker Compose

So, let's start with the installation of the new Rails application; just follow the instructions from Nick's template.

If you still don't have Docker on your computer, you have to install it.

Don't forget to run docker compose down -v after you rename the project; otherwise, you'll get an error related to the database connection that kept me stuck for a while.

Installing Solidus gem

Add gem "solidus", "~> 4.1.0" to the Gemfile and run ./run bundle:install in a console.

Choose starter - so all the controllers and views will be generated in your project.

Then choose Stripe or Braintree, or another payment system of your choice.

I've encountered a Could not find a JavaScript runtime error in the web Docker container.

Actually, I have a Javascript runtime (Node.js) installed, but in the assets containers. For Solidus, we need it to be installed in the main container as well.

I made some changes in the Dockerfile, so it'll have the assets containers merged into web.

Also, I've received an error message caused by a lack of libraries required by the Braintree payment system.

I've added libxml2-dev to the Dockerfile.

And also, I've added two more libraries for processing media files: glib-2.0 and libvips.

So, the final version of my Dockerfile:

FROM ruby:3.2.2-slim-bullseye AS app  

WORKDIR /app  

ARG UID=1000  
ARG GID=1000  

RUN bash -c "set -o pipefail && apt-get update \  
&& apt-get install -y --no-install-recommends build-essential curl git libpq-dev libxml2-dev glib-2.0 libvips \  
&& curl -sSL https://deb.nodesource.com/setup_18.x | bash - \  
&& curl -sSL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \  
&& echo 'deb https://dl.yarnpkg.com/debian/ stable main' | tee /etc/apt/sources.list.d/yarn.list \  
&& apt-get update && apt-get install -y --no-install-recommends nodejs yarn \  
&& 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"  

USER ruby  

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

COPY --chown=ruby:ruby Gemfile* ./  
RUN 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 . .  

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

EXPOSE 8000  

CMD ["rails", "s"]

and docker-compose.yml:

x-app: &default-app
  build:
    context: "."
    target: "app"
    args:
      - "UID=${UID:-1000}"
      - "GID=${GID:-1000}"
      - "RAILS_ENV=${RAILS_ENV:-production}"
      - "NODE_ENV=${NODE_ENV:-production}"
  depends_on:
    - "postgres"
    - "redis"
  env_file:
    - ".env"
  restart: "${DOCKER_RESTART_POLICY:-unless-stopped}"
  stop_grace_period: "3s"
  tty: true
  volumes:
    - "${DOCKER_WEB_VOLUME:-./public:/app/public}"

services:
  postgres:
    deploy:
      resources:
        limits:
          cpus: "${DOCKER_POSTGRES_CPUS:-0}"
          memory: "${DOCKER_POSTGRES_MEMORY:-0}"
    environment:
      POSTGRES_USER: "${POSTGRES_USER}"
      POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
    image: "postgres:15.3-bullseye"
    profiles: ["postgres"]
    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.0.11-bullseye"
    profiles: ["redis"]
    restart: "${DOCKER_RESTART_POLICY:-unless-stopped}"
    stop_grace_period: "3s"
    volumes:
      - "redis:/data"

  web:
    <<: *default-app
    deploy:
      resources:
        limits:
          cpus: "${DOCKER_WEB_CPUS:-0}"
          memory: "${DOCKER_WEB_MEMORY:-0}"
    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"]

  cable:
    <<: *default-app
    command: "puma -p 28080 cable/config.ru"
    entrypoint: []
    deploy:
      resources:
        limits:
          cpus: "${DOCKER_CABLE_CPUS:-0}"
          memory: "${DOCKER_CABLE_MEMORY:-0}"
    ports:
      - "${DOCKER_CABLE_PORT_FORWARD:-127.0.0.1:28080}:28080"
    profiles: ["cable"]

volumes:
  postgres: {}
  redis: {}

Also, we need to comment out one line in the file /bin/docker-entrypoint-web

cp -r /public /app

Useful Resources