'Adding libvips to a Rails 7 Docker image

I'm new to Docker and trying to create a Dockerfile for this new Rails 7 app. I'm using vips instead of imagemagick for the memory benefits.

and my local machine is a mac so brew install vips takes care of my non docker development flow, but it hasn't gone so well using the ruby-vips gem, or installing from source.

Running $ docker compose up results in:

/usr/local/bundle/gems/ffi-1.15.5/lib/ffi/library.rb:145:in block in ffi_lib': Could not open library 'vips.so.42': vips.so.42: cannot open shared object file: No such file or directory. (LoadError)

With the following docker-compose.yml:

version: "3.9"
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db

and a Dockerfile:

FROM ruby:3.0.1
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN gem install ruby-vips
RUN bundle install

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Configure the main process to run when running the image
CMD ["rails", "server", "-b", "0.0.0.0"]

I've also tried installing from source (https://www.libvips.org/install.html) install of using ruby-vips with no luck.



Solution 1:[1]

TLDR; ruby-vips need libvips42 installed on your docker image.

Update your Dockerfile to use the following:

RUN apt-get update -qq && apt-get install -y --no-install-recommends nodejs postgresql-client libvips42

PS: run docker compose down and docker compose up --build to force a rebuild of your docker images.

Solution 2:[2]

I don't think you're actually installing libvips in your dockerfile. Try this:

FROM ruby:3.0.1
RUN apt-get update -qq \
    && apt-get install -y nodejs postgresql-client
RUN apt install -y --no-install-recommends libvips42
WORKDIR /myapp
...

However, this will install the libvips that comes with buster, and it's 8.7.x from five years ago (!!). Debian does not move quickly.

I would build current libvips from source. Something like this:

# based on buster
FROM ruby:3.0.1

RUN apt-get update && apt-get install -y \
        build-essential \
        unzip \
        wget \
        git \
        pkg-config

# stuff we need to build our own libvips ... this is a pretty random selection
# of dependencies, you'll want to adjust these
RUN apt-get install -y \
        glib-2.0-dev \
        libexpat-dev \
        librsvg2-dev \
        libpng-dev \
        libgif-dev \
        libjpeg-dev \
        libexif-dev \
        liblcms2-dev \
        liborc-dev

ARG VIPS_VERSION=8.12.2
ARG VIPS_URL=https://github.com/libvips/libvips/releases/download

RUN apt-get install -y \
        wget

RUN cd /usr/local/src \
        && wget ${VIPS_URL}/v${VIPS_VERSION}/vips-${VIPS_VERSION}.tar.gz \
        && tar xzf vips-${VIPS_VERSION}.tar.gz \
        && cd vips-${VIPS_VERSION} \
        && ./configure --disable-deprecated \
        && make -j 4 V=0 \
        && make install

RUN gem install ruby-vips

That won't include support for GIF save, or for formats like HEIC or PDF. You'll probably want to adjust it a bit. And of course you should not build packages in your deployment docker image, you'd want to do that in a separate dockerfile.

Hopefully ruby-vips deployment will become more automated over the next few months now that's it's the rail7 default. It's rather manual right now.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2