rust-lang / docker-rust

The official Docker images for Rust
428 stars 89 forks source link

Latest Alpine images break SQL CLI build #167

Closed mrsarm closed 4 months ago

mrsarm commented 6 months ago

Not sure whether this is an issue related to changes in how the Rust Alpine image is generated, but I'm able to build the latest version of sqlx-cli without problems in older versions of Alpine with Docker, and with my local Ubuntu machine using latest Rust as well.

Using a not so old Alpine image rust:1.71-alpine3.18 the following Dockerfile works:

FROM rust:1.71-alpine3.18

RUN apk add --no-cache --purge openssl-dev musl-dev \
    && cargo install sqlx-cli \
         --target x86_64-unknown-linux-musl \
         --no-default-features \
         --features native-tls,postgres

ENTRYPOINT ["/usr/local/cargo/bin/sqlx"]

I can build the executable, and run a container with the resulting image:

# Build with:
docker build -t sqlx-cli .
# ...
# Run with:
docker run -it --rm sqlx-cli --version
sqlx-cli 0.7.3

Changing the image to rust:1.72-alpine3.18, rust:1.73-alpine3.18 or the latest Alpine version rust:1.74.1-alpine3.18 the build fails with the following:

docker build -t sqlx .

...
53.02    Compiling sqlx v0.7.3
53.06    Compiling sqlx-cli v0.7.3
...
80.60 
80.76 error: could not compile `sqlx-cli` (bin "cargo-sqlx") due to previous error
80.76 warning: build failed, waiting for other jobs to finish...
81.08 error: linking with `cc` failed: exit status: 1
81.08   |
81.08   = note: LC_ALL="C" PATH="/usr/local/rustup/toolchains/1.74.1-x86_64-unkn...
...
80.60   = note: /usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: cannot find -lssl: No such file or directory
80.60           /usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: cannot find -lcrypto: No such file or directory
80.60           collect2: error: ld returned 1 exit status
80.60           
80.60 
80.76 error: could not compile `sqlx-cli` (bin "cargo-sqlx") due to previous error
80.76 warning: build failed, waiting for other jobs to finish...
81.08   |
...
ERROR: failed to solve: process "/bin/sh -c apk add --no-cache --purge openssl-dev musl-dev     && cargo install sqlx-cli          --target x86_64-unknown-linux-musl          --no-default-features          --features native-tls,postgres" did not complete successfully: exit code: 101

CC @abonander @mehcode

tyilo commented 4 months ago

Still the same issue with the rust:1.76.0-alpine image. You can't use the openssl-sys crate:

$ docker run --rm -it rust:1.76.0-alpine
# apk add pkgconfig libc-dev openssl-dev
# cargo new test-openssl-sys
# cd test-openssl-sys
# cargo add openssl-sys
# cat > src/main.rs 
fn main() {
    let ptr = unsafe { openssl_sys::OPENSSL_malloc(8) };
    dbg!(ptr);
}
^D
# cargo build
   Compiling pkg-config v0.3.30
   Compiling cc v1.0.88
   Compiling vcpkg v0.2.15
   Compiling libc v0.2.153
   Compiling openssl-sys v0.9.101
   Compiling test-openssl-sys v0.1.0 (/test-openssl-sys)
error: linking with `cc` failed: exit status: 1
  |
  = note: LC_ALL="C" PATH="/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/bin:/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/bin/self-contained:/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" VSLANG="1033" "cc" "-m64" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/self-contained/rcrt1.o" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/self-contained/crti.o" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/self-contained/crtbeginS.o" "/tmp/rustciNGjWW/symbols.o" "/test-openssl-sys/target/debug/deps/test_openssl_sys-13bc5648144e415a.18rcydlk0f7dihw8.rcgu.o" "/test-openssl-sys/target/debug/deps/test_openssl_sys-13bc5648144e415a.1kqeb1wcy2flvgj5.rcgu.o" "/test-openssl-sys/target/debug/deps/test_openssl_sys-13bc5648144e415a.2aawotddvc97nelz.rcgu.o" "/test-openssl-sys/target/debug/deps/test_openssl_sys-13bc5648144e415a.3l7rv7fg9lqv99sx.rcgu.o" "/test-openssl-sys/target/debug/deps/test_openssl_sys-13bc5648144e415a.3uueg7b0qbnozhhu.rcgu.o" "/test-openssl-sys/target/debug/deps/test_openssl_sys-13bc5648144e415a.5eyutxcjpad8lgj0.rcgu.o" "/test-openssl-sys/target/debug/deps/test_openssl_sys-13bc5648144e415a.8baoyz2hrhwijl8.rcgu.o" "/test-openssl-sys/target/debug/deps/test_openssl_sys-13bc5648144e415a.8wwtv5bka6wcer6.rcgu.o" "/test-openssl-sys/target/debug/deps/test_openssl_sys-13bc5648144e415a.1yjl3mod2g43zxy4.rcgu.o" "-Wl,--as-needed" "-L" "/test-openssl-sys/target/debug/deps" "-L" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib" "-Wl,-Bstatic" "/test-openssl-sys/target/debug/deps/libopenssl_sys-bb2d7631146cc568.rlib" "-lssl" "-lcrypto" "/test-openssl-sys/target/debug/deps/liblibc-e2fb7e5f9db08084.rlib" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/libstd-98f4280c64a1a599.rlib" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/libpanic_unwind-d13d73efc17f6dd6.rlib" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/libobject-ab88e6053e9077b0.rlib" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/libmemchr-5ee5d4158fd65092.rlib" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/libaddr2line-3ca9f7703b3ec626.rlib" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/libgimli-aab7bb940914a7df.rlib" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/librustc_demangle-c9968e6029c14d78.rlib" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/libstd_detect-191c35155b89f0bf.rlib" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/libhashbrown-c8206c4fc06a3f03.rlib" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/librustc_std_workspace_alloc-653f596b1234f338.rlib" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/libminiz_oxide-b547a52eac4c0203.rlib" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/libadler-952d2e0b92a06a65.rlib" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/libunwind-c69cd377efef48ab.rlib" "-lunwind" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/libcfg_if-e4ef77e89ab561c6.rlib" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/liblibc-871ce4e5bd18b686.rlib" "-lc" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/liballoc-6a730c82936588fb.rlib" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/librustc_std_workspace_core-93bea63c14ab7ed2.rlib" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/libcore-0cc568faa68233c6.rlib" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/libcompiler_builtins-a35e2d2f7e164f79.rlib" "-Wl,-Bdynamic" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-nostartfiles" "-L" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib" "-L" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/self-contained" "-o" "/test-openssl-sys/target/debug/deps/test_openssl_sys-13bc5648144e415a" "-Wl,--gc-sections" "-static-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/self-contained/crtendS.o" "/usr/local/rustup/toolchains/1.76.0-x86_64-unknown-linux-musl/lib/rustlib/x86_64-unknown-linux-musl/lib/self-contained/crtn.o"
  = note: /usr/lib/gcc/x86_64-alpine-linux-musl/13.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: cannot find -lssl: No such file or directory
          /usr/lib/gcc/x86_64-alpine-linux-musl/13.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: cannot find -lcrypto: No such file or directory
          collect2: error: ld returned 1 exit status

error: could not compile `test-openssl-sys` (bin "test-openssl-sys") due to 1 previous error

This is weird because both /usr/lib/libssl.so and /usr/lib/libcrypto.so exists and you can compile and link a C program:

# cat > a.c
#include<stdio.h>

int main() {
  puts("Hello");
}
# cc -c a.c
# ld -o a.out -dynamic-linker /lib/ld-musl-x86_64.so.1 /usr/lib/crt1.o /usr/lib/crti.o a.o -lc /usr/l
ib/crtn.o -lssl -lcrypto
# ./a.out
Hello
tyilo commented 4 months ago

If we don't use the provided docker image, but manually install rust into the alpine docker image, everything works:

$ docker run --rm -it alpine
# apk add pkgconfig libc-dev openssl-dev cargo
# cargo new test-openssl-sys
# cat > src/main.rs 
fn main() {
    let ptr = unsafe { openssl_sys::OPENSSL_malloc(8) };
    dbg!(ptr);
}
^D
# cargo build
  Downloaded pkg-config v0.3.30
  Downloaded cc v1.0.88
  Downloaded openssl-sys v0.9.101
  Downloaded vcpkg v0.2.15
  Downloaded libc v0.2.153
  Downloaded 5 crates (1.1 MB) in 0.72s
   Compiling vcpkg v0.2.15
   Compiling pkg-config v0.3.30
   Compiling cc v1.0.88
   Compiling libc v0.2.153
   Compiling openssl-sys v0.9.101
   Compiling test-openssl-sys v0.1.0 (/workdir/test-openssl-sys)
    Finished dev [unoptimized + debuginfo] target(s) in 3.94s
Muscraft commented 4 months ago

I tried adding openssl-libs-static and it appeared to work. Modify your apk add to be:

apk add pkgconfig libc-dev openssl-dev openssl-libs-static
polarathene commented 4 months ago

Still the same issue with the rust:1.76.0-alpine image. You can't use the openssl-sys crate

You can if you do it properly: https://github.com/sfackler/rust-openssl/issues/1627#issuecomment-1958587430

# Rust alpine container with extra deps added:
docker run --rm -it rust:alpine ash
apk add musl-dev openssl-dev openssl-libs-static

# Minimal project example:
cargo init /example && cd /example
cargo add openssl

# All one command (can paste into terminal without needing `\`)
cat > src/main.rs <<EOF
fn main() {
    println!("Version: {}", openssl::version::version());
}
EOF

# Check builds successfully:
cargo run --release
# OUTPUT:
# Version: OpenSSL 3.1.4 24 Oct 2023

You can replace my main.rs example with your own and use the openssl-sys crate directly instead of openssl and that still works correctly.


This is weird because both /usr/lib/libssl.so and /usr/lib/libcrypto.so exists and you can compile and link a C program

If we don't use the provided docker image, but manually install rust into the alpine docker image, everything works:

I tried adding openssl-libs-static and it appeared to work.

The C program worked because you dynamically linked, while the rust target x86_64-unknown-linux-musl differs from it's *-gnu equivalent, it statically links by default (-C target-feature=+crt-static) and is self contained (-C link-self-contained=yes, this provides crti.o from the rust toolchain instead of distro libs).

The reason it's different when you use the official alpine image directly is because you installed cargo from apk right? Not rustup? They patch their package to dynamically link by default and IIRC it has a different target (_x86_64-alpine-linux-musl or something like that_). There are plans in the future AFAIK to make the *-musl targets dynamic by default to avoid that confusion, but I've no idea when that may actually land.


So there's your answer :)

If you want to use rust:alpine and dynamic link you could use RUSTFLAGS='-C target-feature=-crt-static' cargo build 👍

tyilo commented 4 months ago

@polarathene Thanks for the explanation, that makes perfect sense.

It is quite weird that rust:alpine uses statically linking by default, but alpine's own rust doesn't. But I guess that will be fixed with https://github.com/rust-lang/rust/issues/59302


@mrsarm's issue can also be fixed by either installing openssl-libs-static or using dynamic linking, so maybe this should be closed?

mrsarm commented 4 months ago

Thanks all for the feedback and workarounds, I'll test them Today or Tomorrow and post here the results.

mrsarm commented 4 months ago

Worked !

So for those that need the same, here is the example again fixed, and with the latest Rust image available Today:

FROM rust:1.76-alpine3.19

RUN apk update \
    && apk add --no-cache --purge openssl-dev openssl-libs-static musl-dev libc-dev \
    && cargo install sqlx-cli \
         --target x86_64-unknown-linux-musl \
         --no-default-features \
         --features native-tls,postgres

ENTRYPOINT ["/usr/local/cargo/bin/sqlx"]

This is how to build it, and test it:

# Build with:
docker build -t sqlx-cli .
# ...
# Run with:
docker run -it --rm sqlx-cli --version
sqlx-cli 0.7.3