Merge pull request #99 from emk/sqlx
Add support for static linking of `sqlx`
This commit is contained in:
commit
8b9a2d2e3e
47
CHANGELOG.md
Normal file
47
CHANGELOG.md
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). We do not use Semantic Versioning, because our images are tagged based on Rust releases. However, we try to maintain as much backwards compatibility as possible.
|
||||||
|
|
||||||
|
For maximum stablity, use images with tags like `ekidd/rust-musl-builder:1.46.0` or `ekidd/rust-musl-builder:nightly-2020-08-26`. These may occasionally be rebuilt, but only while they're "current", or possibly if they're recent and serious security are discovered in a library.
|
||||||
|
|
||||||
|
## 2020-09-04
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added `examples/using-sqlx`.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Our OpenSSL configuration now uses environment variables prefixed with `X86_64_UNKNOWN_LINUX_MUSL_`. See [sfackler/rust-openssl#1337](https://github.com/sfackler/rust-openssl/issues/1337) and [launchbadge/sqlx#670](https://github.com/launchbadge/sqlx/issues/670) for background. This allows us to support static builds of `sqlx`, but it may break very old versions of `openssl-sys` (which were probably already broken when OpenSSL 1.0 reached its end-of-life).
|
||||||
|
|
||||||
|
## 2020-08-27
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update to `cargo deny` 0.7.3.
|
||||||
|
- Update to PostgreSQL 11.9.
|
||||||
|
|
||||||
|
## 2020-07-16
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update to `mdbook` version 0.4.1.
|
||||||
|
- Update to `cargo deny` 0.7.0.
|
||||||
|
|
||||||
|
## 2020-06-05
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Previously, `stable` included OpenSSL 1.0.2, and `stable-openssl11` included OpenSSL 1.1.1. However, OpenSSL 1.0.2 is **no longer receiving security fixes,** so the new tagging system will be:
|
||||||
|
- `stable`: OpenSSL 1.1.1 and the latest stable Rust.
|
||||||
|
- **DEPRECATED** `stable-openssl11`: OpenSSL 1.1 and Rust 1.42.0. This will no longer be updated. Use `stable` instead.
|
||||||
|
- **DEPRECATED** `1.42.0-openssl10` and `nightly-2020-03-12-openssl10`: OpenSSL 1.0.2. These will not be updated to newer Rust. You will still be able to build newer OpenSSL 1.0.2 images manually.
|
||||||
|
|
||||||
|
I hate to break compatibility with projects that require OpenSSL 1.0.2, but since it will receive no future security updates, I no longer feel comfortable supplying pre-built images.
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update to `cargo deny` 0.6.7.
|
||||||
|
- Update to PostgreSQL 11.8.
|
|
@ -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 \
|
||||||
|
|
27
README.md
27
README.md
|
@ -2,9 +2,16 @@
|
||||||
|
|
||||||
[![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)
|
||||||
|
- [Changelog](https://github.com/emk/rust-musl-builder/blob/master/CHANGELOG.md)
|
||||||
|
|
||||||
|
**UPDATED:** The OpenSSL configuration has changed to support `sqlx`. This may break very old versions of the `openssl` crate. If this affects you, please file an issue. See the [Changelog](https://github.com/emk/rust-musl-builder/blob/master/CHANGELOG.md) for details.
|
||||||
|
|
||||||
## What is this?
|
## What is this?
|
||||||
|
|
||||||
Do you want to compile a completely static Rust binary with no external dependencies? If so, try:
|
This image allows you to build static Rust binaries using `diesel`, `sqlx` or `openssl`. These images can be distributed as single executable files with no dependencies, and they should work on any modern Linux system.
|
||||||
|
|
||||||
|
To try it, run:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
alias rust-musl-builder='docker run --rm -it -v "$(pwd)":/home/rust/src ekidd/rust-musl-builder'
|
alias rust-musl-builder='docker run --rm -it -v "$(pwd)":/home/rust/src ekidd/rust-musl-builder'
|
||||||
|
@ -13,7 +20,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`s for [examples/using-diesel](./examples/using-diesel) and [examples/using-sqlx](./examples/using-sqlx).
|
||||||
|
|
||||||
## Deploying your Rust application
|
## Deploying your Rust application
|
||||||
|
|
||||||
|
@ -36,20 +43,10 @@ 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
|
||||||
|
|
||||||
### OpenSSL security note
|
|
||||||
|
|
||||||
Previously, `stable` included OpenSSL 1.0.2, and `stable-openssl11` included OpenSSL 1.1.1. However, OpenSSL 1.0.2 is **no longer receiving security fixes,** so the new tagging system will be:
|
|
||||||
|
|
||||||
- `stable`: OpenSSL 1.1.1 and the latest stable Rust.
|
|
||||||
- **DEPRECATED** `stable-openssl11`: OpenSSL 1.1 and Rust 1.42.0. This will no longer be updated. Use `stable` instead.
|
|
||||||
- **DEPRECATED** `1.42.0-openssl10` and `nightly-2020-03-12-openssl10`: OpenSSL 1.0.2. These will not be updated to newer Rust. You will still be able to build newer OpenSSL 1.0.2 images manually.
|
|
||||||
|
|
||||||
I hate to break compatibility with projects that require OpenSSL 1.0.2, but since it will receive no future security updates, I no longer feel comfortable supplying pre-built images.
|
|
||||||
|
|
||||||
## Caching builds
|
## Caching builds
|
||||||
|
|
||||||
You may be able to speed up build performance by adding the following `-v` commands to the `rust-musl-builder` alias:
|
You may be able to speed up build performance by adding the following `-v` commands to the `rust-musl-builder` alias:
|
||||||
|
@ -94,8 +91,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
|
||||||
|
@ -205,7 +200,7 @@ This is missing many of the libraries used by the `x86_64` build, and it should
|
||||||
|
|
||||||
## Development notes
|
## Development notes
|
||||||
|
|
||||||
After modifying the image, run `./test-image` to make sure that everything works.xs
|
After modifying the image, run `./test-image` to make sure that everything works.
|
||||||
|
|
||||||
## Other ways to build portable Rust binaries
|
## Other ways to build portable Rust binaries
|
||||||
|
|
||||||
|
|
|
@ -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