コンテナのPythonからMySQLにzstd圧縮を有効にして接続する

mysql-connector-python を使えば簡単なのですが、あえて mysqlclient を使う場合の話です。

まず、Pythonの公式DockerイメージはDebianベースになっていますが、Debianではデフォルトではapt-getでMySQLをインストールできません。 (Debian sid では MySQL が復活していますが、stableになるには時間がかかります)

代わりにmariadbのクライアントライブラリ(libmariadb)はインストールできるのですが、MariaDBはzstd圧縮に対応しておらず、そのせいかクライアントライブラリはzstd圧縮に対応しているもののDebian bookwormのパッケージには入っていないので使えません。

なので標準の apt-get だけでzstd圧縮を使う方法がありません。代わりにライブラリをインストールする必要があります。

まず MySQL なんですが、8.0からMySQL Connector/Cの配布を止めてしまっていて、MySQLを入れろというふうになっていて面倒です。 また apt レポジトリも公開してくれているのですが、 i386amd64 はあるのに arm64 がないのでそれも面倒です。

次に MariaDB ですが、次のダウンロードページを見てみると、Debian用のバイナリをarm64とamd64でバイナリパッケージを tar.gz で提供してくれています。

https://mariadb.com/downloads/connectors/

これを使ってmysqlclientを用意してみます。

FROM python:3.13

# 先にデフォルトのlibmariadbを消しておく。 python:3.13-slim の場合は省略可能
RUN apt-get -y purge libmariadb3 libmariadb-dev

# MariaDB Connector/C をインストールする
WORKDIR /usr/local
ADD https://dlm.mariadb.com/4234446/Connectors/c/connector-c-3.4.5/mariadb-connector-c-3.4.5-debian-bookworm-aarch64.tar.gz /usr/local/mariadb-connector.tar.gz
# AMD64の場合はこっち
# ADD https://dlm.mariadb.com/4234464/Connectors/c/connector-c-3.4.5/mariadb-connector-c-3.4.5-debian-bookworm-amd64.tar.gz /usr/local/mariadb-connector.tar.gz

RUN tar xf mariadb-connector.tar.gz --strip-components=1 && rm mariadb-connector.tar.gz

# /usr/local/lib/mariadb の下のライブラリはデフォルトで見つけてくれないので、 libmariadb.so(.3) へのsymlink を ld.so.conf で指定されているディレクトリに作る
# または下にある方法で rpath を設定しても良い
WORKDIR /usr/local/lib
RUN ln -s mariadb/libmariadb.so* . && ldconfig

# mysqlclient をインストール
WORKDIR /home
RUN pip install -v mysqlclient

# rpath を設定する場合
#RUN MYSQLCLIENT_CFLAGS=$(/usr/local/bin/mariadb_config --cflags) \
#    MYSQLCLIENT_LDFLAGS="$(/usr/local/bin/mariadb_config --libs) -Wl,-rpath=/usr/local/lib/mariadb" \
#    pip install -v mysqlclient

これで zstd 接続ができているかを確認しましょう。

$ docker run --network host --name mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:8.0

$ docker build -t hoge .
$ docker run --network host -it hoge bash

root@colima:/home# ldd /usr/local/lib/python3.13/site-packages/MySQLdb/_mysql.cpython-313-aarch64-linux-gnu.so
        linux-vdso.so.1 (0x0000fc6873027000)
        libmariadb.so.3 => /usr/local/lib/libmariadb.so.3 (0x0000fc6872f40000)
        libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000fc6872d90000)
        libssl.so.3 => /lib/aarch64-linux-gnu/libssl.so.3 (0x0000fc6872cd0000)
        libcrypto.so.3 => /lib/aarch64-linux-gnu/libcrypto.so.3 (0x0000fc6872800000)
        /lib/ld-linux-aarch64.so.1 (0x0000fc6872fea000)

root@colima:/home# python
Python 3.13.3 (main, Apr  9 2025, 02:20:29) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import MySQLdb
>>> con = MySQLdb.connect(host="127.0.0.1", user="root", password="my-secret-pw", compress=True)
>>> cur = con.cursor()
>>> cur.execute('SHOW STATUS LIKE "Compress%"')
3
>>> for v in cur:
...     print(v)
...
('Compression', 'ON')
('Compression_algorithm', 'zstd')
('Compression_level', '3')
>>>
このブログに乗せているコードは引用を除き CC0 1.0 で提供します。