rubyjs / libv8

Ruby gem binary distribution of the V8 JavaScript engine
269 stars 121 forks source link

Add a Vagrant box for Alpine Linux #221

Closed ignisf closed 7 years ago

ignisf commented 8 years ago

libv8 is currently not tested on Alpine. A Vagrant box would help the libv8 maintainers in making sure it builds successfully.

ignisf commented 8 years ago

Ideally someone would provide either an official Vagrant box (like the ones we use for Linux and FreeBSD) or a script for creating a box from an iso so we can create one ourselves.

aviat commented 8 years ago

What about Docker? The Alpine distribution is quite popular these days: https://hub.docker.com/_/alpine/

ignisf commented 8 years ago

I will look into it, thanks for the idea!

For reference https://www.vagrantup.com/docs/docker/basics.html

ignisf commented 8 years ago

OK, a Vagrantfile such as the one below seems to start up, however I'm not sure how to install the needed packages, start an SSH server and keep the image running so I can use it for testing like a normal Vagrant VM.

Vagrant.configure("2") do |config|
  config.vm.provider "docker" do |d|
    d.image = "library/alpine"
    d.cmd = ['uname']
  end 
end
BrendonW commented 8 years ago

Why not just start with Docker for Mac or Docker for Windows? You can be up & running with an Alpine container in about 2 minutes.

I got here because I'm trying to put together a base-rails Alpine based container for our app. The ExecJS is giving me fits trying to run libv8. I was hoping to use V8 with mini-racer on Alpine 3.4...

ishitatsuyuki commented 7 years ago

The answer is no. Since you're building with glibc, it lacks some GNU internals when used with musl.

One choice is static linking, and another is provide separate binary for musl.

ishitatsuyuki commented 7 years ago

Another note for you: the v8 build system downloads their custom binutils, which also use glibc. What the hell.

ignisf commented 7 years ago

Best part is that I had to start using these binutils because of https://github.com/cowboyd/libv8/issues/227

ishitatsuyuki commented 7 years ago

Linking libc statically should solve this perfectly. Some size growth though.

ishitatsuyuki commented 7 years ago

I'm happy compiling it within a Docker container with basic ruby things + alpine-sdk + findutils, python2, bash, linux-headers, binutils-gold installed. Adding the glibc package makes the custom binutils usable.

ignisf commented 7 years ago

This sounds great, could you possibly collect your changes in a PR and add an alpine how-to to the readme? Maybe start with the docs so I could help you out along the way.

ishitatsuyuki commented 7 years ago

It would be good if you added this as a type of binary release. I currently compile the extension locally and overwrites the one on my server to achieve the same thing.

There's no stable vagrant image for Alpine, so Docker is preferred. The dependencies I mentioned above is enough to compile it.

ignisf commented 7 years ago

This is the way I currently produce Linux binary releases https://github.com/cowboyd/libv8/blob/master/Rakefile#L53-L70. I would appreciate it if you showed me how to extend this process for Docker. I've never used it.

ishitatsuyuki commented 7 years ago

Here's the command:

# replace localgit with the git directory, outdir with the release output
docker run -it --rm -v localgit:/libv8 -v outdir:/out alpine:edge /bin/sh -c 'apk add --update \
 ruby ruby-bigdecimal ruby-bundler ruby-rdoc ruby-io-console ruby-irb ruby-dev \
 alpine-sdk bash ca-certificates libressl libressl-dev findutils python2 linux-headers binutils-gold \
 && wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://raw.githubusercontent.com/sgerrand/alpine-pkg-glibc/master/sgerrand.rsa.pub \
 && wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.23-r3/glibc-2.23-r3.apk \
 && apk add glibc-2.23-r3.apk \
 && git clone /libv8/.git ~/libv8 --recursive \
 && cd ~/libv8 && bundle install --path vendor/bundle \
 && cd ~/libv8 && env MAKEFLAGS+=-j4 bundle exec rake binary \
 && cp ~/libv8/pkg/*.gem /out'

Of course root is needed. By the way, 32bit isn't officially available for Docker, so we can ignore it. (Only a few people runs Alpine on their bare metal, much less 32bit, and they can follow the script to build from source anyway.)

UPDATE: added ruby-dev

mwarkentin commented 7 years ago

I came across this "fix" for alpine here:

I've tested and confirmed that v8 / therubyracer work correctly with the following addition to my Dockerfile:

ENV LIBV8_MAJOR 3.16
ENV LIBV8_VERSION 3.16.14.17-x86_64-linux

RUN set -ex \
    \
    && apk add --update --no-cache --virtual .libv8-builddeps \
      make \
      python \
      git \
      bash \
      curl \
      findutils \
      binutils-gold \
      tar \
      linux-headers \
      build-base \
    \
    && git clone -b $LIBV8_MAJOR --recursive git://github.com/cowboyd/libv8.git \
    && cd ./libv8 \
    && sed -i -e 's/Gem::Platform::RUBY/Gem::Platform.local/' libv8.gemspec \
    && gem build --verbose libv8.gemspec \
    && export GYP_DEFINES="$GYP_DEFINES linux_use_bundled_binutils=0 linux_use_bundled_gold=0" \
    && gem install --verbose libv8-$LIBV8_VERSION.gem \
    \
    && apk del --purge .libv8-builddeps \
    \
    && cd ../ \
    && rm -rf ./libv8 \
    && cd /usr/local/bundle/gems/libv8-$LIBV8_VERSION/vendor/ \
    && mkdir -p /tmp/v8 \
    && mv ./v8/out /tmp/v8/. \
    && mv ./v8/include /tmp/v8/. \
    && rm -rf ./v8 ./depot_tools \
    && mv /tmp/v8 . \
    \
    && apk add --update --no-cache libstdc++ \
    && apk add --update --no-cache --virtual=build-dependencies \
      build-base \
    && gem install therubyracer \
    && rm -fr /usr/local/bundle/gems/libv8-$LIBV8_VERSION/vendor \
    && apk del --purge build-dependencies \
    && rm -rf /tmp/* /var/tmp/* /var/cache/apk/*
mwarkentin commented 7 years ago

@ignisf Is this helpful? I'd be happy to open a PR with a Dockerfile of the above.

ignisf commented 7 years ago

Hello, @mwarkentin, thank you for the tip! I still haven't found the time to go through the suggestions here but they do look promising. I'll get back to you.

0xdevalias commented 7 years ago

@mwarkentin I've only done a very basic test of the above mentioned 'ruby-with-therubyracer', but it looks like it will work for my alpine/therubyracer needs. Thanks for the pointer!

Adel-Magebinary commented 6 years ago

hey all, I just hit this issue and it resolved easily in alpine with followings:

context -> build ruby

RUN set -ex \
  && apk add --no-cache --virtual .ruby-builddeps \
    autoconf \
    bison \
    bzip2 \
    bzip2-dev \
    ca-certificates \
    coreutils \
    dpkg-dev dpkg \
    gcc \
    gdbm-dev \
    glib-dev \
    libc-dev \
    libffi-dev \
    libressl \
    libressl-dev \
    libxml2-dev \
    libxslt-dev \
    linux-headers \
    make \
    ncurses-dev \
    procps \
    readline-dev \
    ruby \
    tar \
    xz \
    yaml-dev \
    zlib-dev \
    libffi-dev \
    libstdc++ \
    g++ \
    musl-dev \
    libstdc++ \
    autoconf \
    bison \
    bzip2 \
    bzip2-dev \
    ca-certificates \
    coreutils \
    dpkg-dev dpkg \
    gcc \
    gdbm-dev \
    glib-dev \
    libc-dev \
    libffi-dev \
    libressl \
    libressl-dev \
    libxml2-dev \
    libxslt-dev \
    linux-headers \
    make \
    ncurses-dev \
    procps \
    readline-dev \
    ruby \
    tar \
    xz \
    yaml-dev \
    zlib-dev \
    libffi-dev \
  && wget -O ruby.tar.xz "https://cache.ruby-lang.org/pub/ruby/${RUBY_MAJOR%-rc}/ruby-$RUBY_VERSION.tar.xz" \
  && echo "$RUBY_DOWNLOAD_SHA256 *ruby.tar.xz" | sha256sum -c - \
  && mkdir -p /usr/src/ruby \
  && tar -xJf ruby.tar.xz -C /usr/src/ruby --strip-components=1 \
  && rm ruby.tar.xz \
  && cd /usr/src/ruby \
  && { \
    echo '#define ENABLE_PATH_CHECK 0'; \
    echo; \
    cat file.c; \
  } > file.c.new \
  && mv file.c.new file.c \
  && autoconf \
  && gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" \
  && export ac_cv_func_isnan=yes ac_cv_func_isinf=yes \
  && ./configure \
    --build="$gnuArch" \
    --disable-install-doc \
    --enable-shared \
  && make -j "$(nproc)" \
  && make install \
  && runDeps="$( \
    scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \
      | tr ',' '\n' \
      | sort -u \
      | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
  )" \
  && apk add --no-network --virtual .ruby-rundeps $runDeps \
    bzip2 \
    ca-certificates \
    libffi-dev \
    procps \
    yaml-dev \
    zlib-dev \
  && gem update --system "$RUBYGEMS_VERSION" \
  && gem install bundler --version "$BUNDLER_VERSION" --force

RUN apk add nodejs && gem install libv8 -v '3.16.14.19' -- --with-system-v8 && gem install compass-rails therubyracer

Hope it helps some :)

rafaelmagu commented 6 years ago

@Adel-Magebinary what version of Alpine are you using for your Dockerfile? Would you mind posting the whole file (if possible)?

Adel-Magebinary commented 6 years ago

@rafaelmagu im running alpine 3.7

Below is the latest code that I can successfully build ruby & libv8. Just copy paste below to your Dockerfile.

RUN set -ex \
  \
  && apk add --no-cache --virtual .ruby-builddeps \
    autoconf \
    bison \
    bzip2 \
    bzip2-dev \
    ca-certificates \
    coreutils \
    dpkg-dev dpkg \
    gcc \
    gdbm-dev \
    glib-dev \
    libc-dev \
    libffi-dev \
    libressl \
    libressl-dev \
    libxml2-dev \
    libxslt-dev \
    linux-headers \
    make \
    ncurses-dev \
    procps \
    readline-dev \
    ruby \
    tar \
    xz \
    yaml-dev \
    zlib-dev \
    libffi-dev \
    libstdc++ \
    g++ \
    musl-dev \
    libstdc++ \
    autoconf \
    bison \
    bzip2 \
    bzip2-dev \
    ca-certificates \
    coreutils \
    dpkg-dev dpkg \
    gcc \
    gdbm-dev \
    glib-dev \
    libc-dev \
    libffi-dev \
    libressl \
    libressl-dev \
    libxml2-dev \
    libxslt-dev \
    linux-headers \
    make \
    ncurses-dev \
    procps \
    readline-dev \
    ruby \
    tar \
    xz \
    yaml-dev \
    zlib-dev \
    libffi-dev \
  \
  && wget -O ruby.tar.xz "https://cache.ruby-lang.org/pub/ruby/${RUBY_MAJOR%-rc}/ruby-$RUBY_VERSION.tar.xz" \
  && echo "$RUBY_DOWNLOAD_SHA256 *ruby.tar.xz" | sha256sum -c - \
  \
  && mkdir -p /usr/src/ruby \
  && tar -xJf ruby.tar.xz -C /usr/src/ruby --strip-components=1 \
  && rm ruby.tar.xz \
  \
  && cd /usr/src/ruby \
  \
# hack in "ENABLE_PATH_CHECK" disabling to suppress:
#   warning: Insecure world writable dir
  && { \
    echo '#define ENABLE_PATH_CHECK 0'; \
    echo; \
    cat file.c; \
  } > file.c.new \
  && mv file.c.new file.c \
  \
  && autoconf \
  && gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" \
# the configure script does not detect isnan/isinf as macros
  && export ac_cv_func_isnan=yes ac_cv_func_isinf=yes \
  && ./configure \
    --build="$gnuArch" \
    --disable-install-doc \
    --enable-shared \
  && make -j "$(nproc)" \
  && make install \
  \
  && runDeps="$( \
    scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \
      | tr ',' '\n' \
      | sort -u \
      | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
  )" \
  && apk add --no-network --virtual .ruby-rundeps $runDeps \
    bzip2 \
    ca-certificates \
    libffi-dev \
    procps \
    yaml-dev \
    zlib-dev \
  && gem update --system "$RUBYGEMS_VERSION" \
  && gem install bundler --version "$BUNDLER_VERSION" --force

# install gems & other sass / js compiling stuff.
ADD Gemfile /var/www/html/
RUN apk add nodejs && gem install libv8 -v '3.16.14.19' -- --with-system-v8 && gem install compass-rails therubyracer && bundle install

#clean ups
RUN apk del --no-network .ruby-builddeps \
  && cd / \
  && rm -r /usr/src/ruby \
  \
  && rm -r /root/.gem/
rafaelmagu commented 6 years ago

@Adel-Magebinary do you also use therubyracer gem by any chance? The above does indeed get me a working Ruby + libv8 image, but therubyracer install fails. :/

Adel-Magebinary commented 6 years ago

@rafaelmagu can you please paste the error here?

rafaelmagu commented 6 years ago

Seems the error has already been reported here, though the "solution" (switching to a different non-Alpine base image) isn't really a solution: https://github.com/docker-library/ruby/issues/113

I am experimenting with a few different settings to try and at least get the assets to compile now.

Adel-Magebinary commented 6 years ago

@rafaelmagu Can you please exec to /bin/bash in your docker and try to install it manually with gem. If it throws error and post it here?

rafaelmagu commented 6 years ago

@Adel-Magebinary the gem installation doesn't fail anymore. I have decided to dump therubyracer altogether in favour of mini_racer.

Adel-Magebinary commented 6 years ago

@rafaelmagu Interesting thing is you are from NZ too lol