Building just mysqlclient on Alpine from scratch
Today I needed to install an old mysql ruby gem. I’m building it all in a lightweight Alpine Docker image, but I hit the problem that newer Alpine has settled on mariadb, and I was getting all sorts of issues with binding against the correct shared libraries.
I knew that I could use mysqlclient
v5.6.51, so I decided to try and
ditch the Alpine apks
mariadb-dev and build from the
old mysql source instead.
mysql builds with
cmake so I needed a few extra packages:
apk add bash build-base autoconf openssl openssl-dev ncurses ncurses-dev wget cmake.
Then you cd into the the unpacked mysql source directory and call
cmake -DWITHOUT_SERVER:BOOL=ON && make && make install.
When I’d initially built and installed it, everything looked good, until the ruby gem was called:
Error loading shared library libmysqlclient.so.18: No such file or directory (needed by /lib/ruby/gems/1.8/gems/mysql-2.7/lib/mysql.so)
Oh no. I could see that I did have the shared library - it was in
the mysql install defaults to a
/user/local/mysql install prefix.
You can tell Alpine where else to look for shared library code by creating an
/etc/ld-musl-$(ARCH).path file (i.e.
/etc/ld-musl-aarch64.path) which I discovered thanks to this Stackoverflow comment. It defaults to
/lib:/usr/local/lib:/usr/lib if it’s not present, so I created
/etc/ld-musl-aarch64.path with these paths:
/lib:/usr/local/lib:/usr/lib:/usr/local/mysql/lib and then when I called
ldd /lib/ruby/gems/1.8/gems/mysql-2.7/lib/mysql.so it could find the shared libraries. This seemed OK, but a little messy.
By changing the options you pass to
cmake, you can change where the shared libraries are installed to:
cmake -DWITHOUT_SERVER:BOOL=ON -DCMAKE_INSTALL_PREFIX=/ && \ make && make install
libmysqlclient files are all to be found in the
/lib folder and
you don’t need the
Here’s the final Dockerfile:
FROM alpine:latest RUN apk add --no-cache bash build-base autoconf openssl openssl-dev ncurses ncurses-dev wget cmake && \ wget -O /tmp/mysql-5.6.51.tar.gz https://cdn.mysql.com/archives/mysql-5.6/mysql-5.6.51.tar.gz && \ cd /tmp && tar -zxf /tmp/mysql-5.6.51.tar.gz && \ cd /tmp/mysql-5.6.51 && cmake -DWITHOUT_SERVER:BOOL=ON -DCMAKE_INSTALL_PREFIX=/ && \ make && make install && \ rm -rf /tmp/mysql* && rm -rf /var/cache/apk/*
All links, in order of mention:
- Alpine has settled on mariadb: https://gist.github.com/x-yuri/17f9875b41ca0f4f0f43ddfabd3a59d6
- Stackoverflow comment: https://stackoverflow.com/questions/36990951/ldconfig-seems-no-functional-under-alpine-3-3#comment90275118_39459749