我编写了以下 Dockerfile,它按照 Snowflake 文档的描述安装和配置 ODBC 驱动程序:https://docs.snowflake.com/en/developer-guide/odbc/odbc-linux
FROM ruby:3.1.4-bullseye
# Setup Snowflake ODBC dependencies
RUN wget https://www.unixodbc.org/unixODBC-2.3.11.tar.gz -P /tmp/unixodbc
WORKDIR /tmp/unixodbc
RUN tar -xzf unixODBC-2.3.11.tar.gz
WORKDIR unixODBC-2.3.11
RUN ./configure && make && make install
RUN wget https://sfc-repo.snowflakecomputing.com/odbc/linuxaarch64/3.1.4/snowflake_linux_aarch64_odbc-3.1.4.tgz -P /tmp/snowflakeodbc
WORKDIR /tmp/snowflakeodbc
RUN gunzip snowflake_linux_aarch64_odbc-3.1.4.tgz
RUN tar -xf snowflake_linux_aarch64_odbc-3.1.4.tar
RUN mkdir -p /opt/snowflake/snowflake_odbc
RUN mv /tmp/snowflakeodbc/snowflake_odbc/* /opt/snowflake/snowflake_odbc
# Configuring SnowflakeODBC with unixODBC
WORKDIR /opt/snowflake/snowflake_odbc
RUN ./unixodbc_setup.sh
如果我构建这个并在容器内获得 bash shell,那么我可以使用 ODBC 连接到 Snowflake:
docker build .
docker run -it 48a9422eb56f91d2e800b0698cfa1ce522eb050dfffb11c268c7f4436ea04e78 bash
安装一些必要的 GEM 来测试 ODBC:
gem install ruby-odbc
gem install sequel
打开 irb 并创建一个测试连接,最后一行的输出表明这是有效的:
require "odbc"
require "sequel"
connection_str = [
'DRIVER=/opt/snowflake/snowflake_odbc/lib/libSnowflake.so;',
'SERVER=<REDACTED>.snowflakecomputing.com;',
'UID=<REDACTED>;',
'PWD=<REDACTED>;',
].join('')
db = Sequel.odbc(drvconnect: connection_str);
db.fetch("select 1;").all
=> [{:"1"=>"1"}]
但是,如果我将 docker 镜像更改为
ruby:3.1.4-alpine3.19
然后安装一些缺少的东西:
FROM ruby:3.1.4-alpine3.19
RUN apk upgrade -U --no-cache && \
apk add --no-cache build-base bash wget
# Setup Snowflake ODBC dependencies
RUN wget https://www.unixodbc.org/unixODBC-2.3.11.tar.gz -P /tmp/unixodbc
WORKDIR /tmp/unixodbc
RUN tar -xzf unixODBC-2.3.11.tar.gz
WORKDIR unixODBC-2.3.11
RUN ./configure && make && make install
RUN wget https://sfc-repo.snowflakecomputing.com/odbc/linuxaarch64/3.1.4/snowflake_linux_aarch64_odbc-3.1.4.tgz -P /tmp/snowflakeodbc
WORKDIR /tmp/snowflakeodbc
RUN gunzip snowflake_linux_aarch64_odbc-3.1.4.tgz
RUN tar -xf snowflake_linux_aarch64_odbc-3.1.4.tar
RUN mkdir -p /opt/snowflake/snowflake_odbc
RUN mv /tmp/snowflakeodbc/snowflake_odbc/* /opt/snowflake/snowflake_odbc
# Configuring SnowflakeODBC with unixODBC
WORKDIR /opt/snowflake/snowflake_odbc
RUN apk add perl # unixodbc_setup.sh uses perl
RUN apk add --no-cache --upgrade grep # grep option -P don't exist in alpine 3.8 which unixodbc_setup.sh uses
RUN ./unixodbc_setup.sh
现在它不再起作用了。当我尝试连接时,我收到这个非常误导性的错误:
db = Sequel.odbc(drvconnect: connection_str)
Can't open lib '/opt/snowflake/snowflake_odbc/lib/libSnowflake.so' : file not found
原来是因为这个:
ldd /opt/snowflake/snowflake_odbc/lib/libSnowflake.so
/lib/ld-musl-aarch64.so.1 (0xffff8dda3000)
libpthread.so.0 => /lib/ld-musl-aarch64.so.1 (0xffff8dda3000)
libdl.so.2 => /lib/ld-musl-aarch64.so.1 (0xffff8dda3000)
libm.so.6 => /lib/ld-musl-aarch64.so.1 (0xffff8dda3000)
libc.so.6 => /lib/ld-musl-aarch64.so.1 (0xffff8dda3000)
Error loading shared library ld-linux-aarch64.so.1: No such file or directory (needed by /opt/snowflake/snowflake_odbc/lib/libSnowflake.so)
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __syslog_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: fcntl64: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __register_atfork: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __snprintf_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __memcpy_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __fprintf_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __vfprintf_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __strcpy_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __sprintf_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __strncpy_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __strcat_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: makecontext: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __memset_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __vsnprintf_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __stpcpy_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: statx: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: backtrace: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __fdelt_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: getcontext: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: setcontext: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __strftime_l: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: backtrace_symbols: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __printf_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __longjmp_chk: symbol not found
我发现添加一堆 glibc 兼容性库只能修复第一个错误,即有关加载共享库的错误:
RUN apk add --no-cache gcompat libc6-compat libstdc++
现在它只是以不同的方式失败了:
db = Sequel.odbc(drvconnect: connection_str);
terminate called after throwing an instance of 'std::system_error'
what(): No error information
Aborted
这很可能与我这样做时的剩余错误有关:
ldd /opt/snowflake/snowflake_odbc/lib/libSnowflake.so
/lib/ld-musl-aarch64.so.1 (0xffff8b405000)
libpthread.so.0 => /lib/ld-musl-aarch64.so.1 (0xffff8b405000)
libdl.so.2 => /lib/ld-musl-aarch64.so.1 (0xffff8b405000)
libm.so.6 => /lib/ld-musl-aarch64.so.1 (0xffff8b405000)
libc.so.6 => /lib/ld-musl-aarch64.so.1 (0xffff8b405000)
ld-linux-aarch64.so.1 => /lib/ld-linux-aarch64.so.1 (0xffff873f5000)
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __syslog_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: fcntl64: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __register_atfork: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __snprintf_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __memcpy_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __fprintf_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __vfprintf_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __strcpy_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __sprintf_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __strncpy_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __strcat_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: makecontext: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __memset_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __vsnprintf_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __stpcpy_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: statx: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: backtrace: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __fdelt_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: getcontext: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: setcontext: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __strftime_l: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: backtrace_symbols: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __printf_chk: symbol not found
Error relocating /opt/snowflake/snowflake_odbc/lib/libSnowflake.so: __longjmp_chk: symbol not found
我在这里运气不好吗?我基本上需要 Snowflake 来发布与 Alpine 兼容的版本(musl 与 glibc)吗?或者除了更改基础图像之外我还能做什么?
ldd /opt/snowflake/snowflake_odbc/lib/libSnowflake.so
/lib/ld-musl-aarch64.so.1 (0xffff8b405000)
您正在尝试使用
libSnowflake.so
,它已在使用 Musl 的系统上与 GLIBC 链接。
那根本行不通。来自Musl常见问题解答:
二进制兼容性受到更多限制,但随着 musl 的新版本,它会稳步增加。目前,一些 glibc 链接的共享库可以使用 musl 加载,但如果将 musl 放入 /lib/ld-linux.so.2 的位置,除了最简单的 glibc 链接应用程序之外的所有应用程序都将失败。
您应该从源代码
构建
libSnowflake.so
并将其链接到Musl。