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 mysql-client
and 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 /usr/local/mysql/lib
, because
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-x86_64.path
or /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
Now the libmysqlclient
files are all to be found in the /lib
folder and
you don’t need the /etc/ld-musl-$(ARCH).path
file.
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
Recent posts:
- Patch for aarch64 (aka arm64) openssl 1.0.2 'relocation R_AARCH64_PREL64 against symbol OPENSSL_armcap_P error'
- TIL: the `NO_COLOR` informal standard to suppress ANSI colour escape codes
- Copy the contents of a branch into an existing git branch without merging
- Adding search to a static Jekyll site using pagefind
- asdf, python and automatically enabling virtual envs