Add support for static linking of sqlx
`sqlx` requires linking against OpenSSL twice: - `sqlx-macros` needs to link against OpenSSL as a shared libary for use at compile time. - `sqlx` needs to link against OpenSSL a static library for use at runtime. You can find the details here: https://github.com/launchbadge/sqlx/issues/670 https://github.com/sfackler/rust-openssl/issues/1337 We go with the fix proposed by @sfackler, and add a test program that we can use to verify everything works correctly. We remove a few `OPENSSL`-related variables that were added 4 years ago, and that no longer appear to be needed.
This commit is contained in:
parent
9f6efa542f
commit
727d912b3b
|
@ -67,7 +67,7 @@ RUN apt-get update && \
|
||||||
curl -fLO https://github.com/EmbarkStudios/cargo-deny/releases/download/$CARGO_DENY_VERSION/cargo-deny-$CARGO_DENY_VERSION-x86_64-unknown-linux-musl.tar.gz && \
|
curl -fLO https://github.com/EmbarkStudios/cargo-deny/releases/download/$CARGO_DENY_VERSION/cargo-deny-$CARGO_DENY_VERSION-x86_64-unknown-linux-musl.tar.gz && \
|
||||||
tar xf cargo-deny-$CARGO_DENY_VERSION-x86_64-unknown-linux-musl.tar.gz && \
|
tar xf cargo-deny-$CARGO_DENY_VERSION-x86_64-unknown-linux-musl.tar.gz && \
|
||||||
mv cargo-deny-$CARGO_DENY_VERSION-x86_64-unknown-linux-musl/cargo-deny /usr/local/bin/ && \
|
mv cargo-deny-$CARGO_DENY_VERSION-x86_64-unknown-linux-musl/cargo-deny /usr/local/bin/ && \
|
||||||
rm -rf cargo-deny-$CARGO_DENY_VERSION-x86_64-unknown-linux-musl cargo-deny-$CARGO_DENY_VERSION-x86_64-unknown-linux-musl.tar.gz
|
rm -rf cargo-deny-$CARGO_DENY_VERSION-x86_64-unknown-linux-musl cargo-deny-$CARGO_DENY_VERSION-x86_64-unknown-linux-musl.tar.gz
|
||||||
|
|
||||||
# Static linking for C++ code
|
# Static linking for C++ code
|
||||||
RUN sudo ln -s "/usr/bin/g++" "/usr/bin/musl-g++"
|
RUN sudo ln -s "/usr/bin/g++" "/usr/bin/musl-g++"
|
||||||
|
@ -142,11 +142,8 @@ RUN echo "Building libpq" && \
|
||||||
cd ../../bin/pg_config && make && sudo make install && \
|
cd ../../bin/pg_config && make && sudo make install && \
|
||||||
rm -r /tmp/*
|
rm -r /tmp/*
|
||||||
|
|
||||||
ENV OPENSSL_DIR=/usr/local/musl/ \
|
ENV X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_DIR=/usr/local/musl/ \
|
||||||
OPENSSL_INCLUDE_DIR=/usr/local/musl/include/ \
|
X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_STATIC=1 \
|
||||||
DEP_OPENSSL_INCLUDE=/usr/local/musl/include/ \
|
|
||||||
OPENSSL_LIB_DIR=/usr/local/musl/lib/ \
|
|
||||||
OPENSSL_STATIC=1 \
|
|
||||||
PQ_LIB_STATIC_X86_64_UNKNOWN_LINUX_MUSL=1 \
|
PQ_LIB_STATIC_X86_64_UNKNOWN_LINUX_MUSL=1 \
|
||||||
PG_CONFIG_X86_64_UNKNOWN_LINUX_GNU=/usr/bin/pg_config \
|
PG_CONFIG_X86_64_UNKNOWN_LINUX_GNU=/usr/bin/pg_config \
|
||||||
PKG_CONFIG_ALLOW_CROSS=true \
|
PKG_CONFIG_ALLOW_CROSS=true \
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
[![Docker Image](https://img.shields.io/docker/pulls/ekidd/rust-musl-builder.svg?maxAge=2592000)](https://hub.docker.com/r/ekidd/rust-musl-builder/)
|
[![Docker Image](https://img.shields.io/docker/pulls/ekidd/rust-musl-builder.svg?maxAge=2592000)](https://hub.docker.com/r/ekidd/rust-musl-builder/)
|
||||||
|
|
||||||
|
[Source on GitHub](https://github.com/emk/rust-musl-builder)
|
||||||
|
|
||||||
## What is this?
|
## What is this?
|
||||||
|
|
||||||
Do you want to compile a completely static Rust binary with no external dependencies? If so, try:
|
Do you want to compile a completely static Rust binary with no external dependencies? If so, try:
|
||||||
|
@ -13,7 +15,7 @@ rust-musl-builder cargo build --release
|
||||||
|
|
||||||
This command assumes that `$(pwd)` is readable and writable by uid 1000, gid 1000. At the moment, it doesn't attempt to cache libraries between builds, so this is best reserved for making final release builds.
|
This command assumes that `$(pwd)` is readable and writable by uid 1000, gid 1000. At the moment, it doesn't attempt to cache libraries between builds, so this is best reserved for making final release builds.
|
||||||
|
|
||||||
For a more realistic example, see the `Dockerfile` for [examples/using-diesel](./examples/using-diesel).
|
For a more realistic example, see the `Dockerfile` for [examples/using-diesel](./examples/using-diesel) [examples/using-sqlx](./examples/using-sqlx).
|
||||||
|
|
||||||
## Deploying your Rust application
|
## Deploying your Rust application
|
||||||
|
|
||||||
|
@ -36,7 +38,7 @@ In general, we provide the following tagged Docker images:
|
||||||
Rust, please file an issue.
|
Rust, please file an issue.
|
||||||
|
|
||||||
At a minimum, each of these images should be able to
|
At a minimum, each of these images should be able to
|
||||||
compile [examples/using-diesel](./examples/using-diesel).
|
compile [examples/using-diesel](./examples/using-diesel) and [examples/using-sqlx](./examples/using-sqlx).
|
||||||
|
|
||||||
[comp]: https://rust-lang.github.io/rustup-components-history/index.html
|
[comp]: https://rust-lang.github.io/rustup-components-history/index.html
|
||||||
|
|
||||||
|
@ -94,8 +96,6 @@ This image also supports the following extra goodies:
|
||||||
If your application uses OpenSSL, you will also need to take a few extra steps to make sure that it can find OpenSSL's list of trusted certificates, which is stored in different locations on different Linux distributions. You can do this using [`openssl-probe`](https://crates.io/crates/openssl-probe) as follows:
|
If your application uses OpenSSL, you will also need to take a few extra steps to make sure that it can find OpenSSL's list of trusted certificates, which is stored in different locations on different Linux distributions. You can do this using [`openssl-probe`](https://crates.io/crates/openssl-probe) as follows:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
extern crate openssl_probe;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
openssl_probe::init_ssl_cert_env_vars();
|
openssl_probe::init_ssl_cert_env_vars();
|
||||||
//... your code
|
//... your code
|
||||||
|
|
|
@ -9,3 +9,4 @@ diesel = { version = "1", features = ["postgres", "sqlite"] }
|
||||||
libsqlite3-sys = { version = "*", features = ["bundled"] }
|
libsqlite3-sys = { version = "*", features = ["bundled"] }
|
||||||
# Needed for Postgres.
|
# Needed for Postgres.
|
||||||
openssl = "*"
|
openssl = "*"
|
||||||
|
openssl-probe = "0.1.2"
|
||||||
|
|
|
@ -46,6 +46,8 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
openssl_probe::init_ssl_cert_env_vars();
|
||||||
|
|
||||||
println!("Hello, world!");
|
println!("Hello, world!");
|
||||||
|
|
||||||
// Only run our database example if we have a database. Otherwise, we just
|
// Only run our database example if we have a database. Otherwise, we just
|
||||||
|
|
1
examples/using-sqlx/.dockerignore
Normal file
1
examples/using-sqlx/.dockerignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
target
|
1265
examples/using-sqlx/Cargo.lock
generated
Normal file
1265
examples/using-sqlx/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
12
examples/using-sqlx/Cargo.toml
Normal file
12
examples/using-sqlx/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "using-sqlx"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Eric Kidd <git@randomhacks.net>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
openssl-probe = "0.1.2"
|
||||||
|
sqlx = { version = "0.4.0-beta.1", default-features = false, features = ["runtime-tokio", "macros", "offline", "postgres"] }
|
||||||
|
tokio = { version = "0.2", features = ["macros"] }
|
25
examples/using-sqlx/Dockerfile
Normal file
25
examples/using-sqlx/Dockerfile
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
# -*- mode: dockerfile -*-
|
||||||
|
#
|
||||||
|
# An example Dockerfile showing how to build a Rust executable using this
|
||||||
|
# image, and deploy it with a tiny Alpine Linux container.
|
||||||
|
|
||||||
|
# You can override this `--build-arg BASE_IMAGE=...` to use different
|
||||||
|
# version of Rust or OpenSSL.
|
||||||
|
ARG BASE_IMAGE=ekidd/rust-musl-builder:latest
|
||||||
|
|
||||||
|
# Our first FROM statement declares the build environment.
|
||||||
|
FROM ${BASE_IMAGE} AS builder
|
||||||
|
|
||||||
|
# Add our source code.
|
||||||
|
ADD --chown=rust:rust . ./
|
||||||
|
|
||||||
|
# Build our application.
|
||||||
|
RUN cargo build --release
|
||||||
|
|
||||||
|
# Now, we need to build our _real_ Docker container, copying in `using-sqlx`.
|
||||||
|
FROM alpine:latest
|
||||||
|
RUN apk --no-cache add ca-certificates
|
||||||
|
COPY --from=builder \
|
||||||
|
/home/rust/src/target/x86_64-unknown-linux-musl/release/using-sqlx \
|
||||||
|
/usr/local/bin/
|
||||||
|
CMD /usr/local/bin/using-sqlx
|
12
examples/using-sqlx/docker-compose.yml
Normal file
12
examples/using-sqlx/docker-compose.yml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
version: "2.0"
|
||||||
|
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
build: .
|
||||||
|
volumes:
|
||||||
|
- cargo:/home/rust/.cargo
|
||||||
|
- target:/home/rust/src/target
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
cargo: {}
|
||||||
|
target: {}
|
23
examples/using-sqlx/sqlx-data.json
Normal file
23
examples/using-sqlx/sqlx-data.json
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"db": "PostgreSQL",
|
||||||
|
"bf54a84704792059fc3a494889dce274bb09f5cadc8c7be61a9b85abbceb001f": {
|
||||||
|
"query": "SELECT $1::INTEGER AS value",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "value",
|
||||||
|
"type_info": "Int4"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Int4"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
examples/using-sqlx/src/main.rs
Normal file
23
examples/using-sqlx/src/main.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
use sqlx::{Connection, postgres::PgConnection};
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<(), sqlx::Error> {
|
||||||
|
openssl_probe::init_ssl_cert_env_vars();
|
||||||
|
|
||||||
|
let url = env::var("POSTGRES_URL")
|
||||||
|
.unwrap_or_else(|_| "postgresql://postgres@localhost/postgres".to_owned());
|
||||||
|
|
||||||
|
// Create a connection.
|
||||||
|
let mut conn = PgConnection::connect(&url).await?;
|
||||||
|
|
||||||
|
// Make a simple query using the `query!` macro.
|
||||||
|
let row = sqlx::query!("SELECT $1::INTEGER AS value", 2i32)
|
||||||
|
.fetch_one(&mut conn)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
assert_eq!(row.value, Some(2));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# Make sure we can build some of our more important test images.
|
# Make sure we can build some of our more important test images.
|
||||||
for EXAMPLE in using-diesel; do
|
for EXAMPLE in using-diesel using-sqlx; do
|
||||||
docker build \
|
docker build \
|
||||||
--build-arg BASE_IMAGE="$IMAGE_NAME" \
|
--build-arg BASE_IMAGE="$IMAGE_NAME" \
|
||||||
-t rust-musl-builder-"$EXAMPLE" \
|
-t rust-musl-builder-"$EXAMPLE" \
|
||||||
|
|
14
test-image
14
test-image
|
@ -41,6 +41,20 @@ fi
|
||||||
echo -e '[PASS] ARMhf binary is statically linked.\n'
|
echo -e '[PASS] ARMhf binary is statically linked.\n'
|
||||||
"
|
"
|
||||||
|
|
||||||
|
# Make sure we can build a static executable using `sqlx`.
|
||||||
|
docker build -t rust-musl-builder-using-sqlx examples/using-sqlx
|
||||||
|
docker run --rm rust-musl-builder-using-sqlx sh -c "
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo -e '--- Test case for sqlx:'
|
||||||
|
echo 'ldd says:'
|
||||||
|
if ldd /usr/local/bin/using-sqlx; then
|
||||||
|
echo '[FAIL] Executable is not static!' 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo -e '[PASS] using-sqlx binary is statically linked.\n'
|
||||||
|
"
|
||||||
|
|
||||||
# Make sure we can build a static executable using `git2`.
|
# Make sure we can build a static executable using `git2`.
|
||||||
docker build -t rust-musl-builder-linking-with-git2 examples/linking-with-git2
|
docker build -t rust-musl-builder-linking-with-git2 examples/linking-with-git2
|
||||||
docker run --rm rust-musl-builder-linking-with-git2 bash -c "
|
docker run --rm rust-musl-builder-linking-with-git2 bash -c "
|
||||||
|
|
Loading…
Reference in a new issue