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 && \
|
||||
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/ && \
|
||||
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
|
||||
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 && \
|
||||
rm -r /tmp/*
|
||||
|
||||
ENV OPENSSL_DIR=/usr/local/musl/ \
|
||||
OPENSSL_INCLUDE_DIR=/usr/local/musl/include/ \
|
||||
DEP_OPENSSL_INCLUDE=/usr/local/musl/include/ \
|
||||
OPENSSL_LIB_DIR=/usr/local/musl/lib/ \
|
||||
OPENSSL_STATIC=1 \
|
||||
ENV X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_DIR=/usr/local/musl/ \
|
||||
X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_STATIC=1 \
|
||||
PQ_LIB_STATIC_X86_64_UNKNOWN_LINUX_MUSL=1 \
|
||||
PG_CONFIG_X86_64_UNKNOWN_LINUX_GNU=/usr/bin/pg_config \
|
||||
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/)
|
||||
|
||||
- [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?
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
|
@ -36,20 +43,10 @@ In general, we provide the following tagged Docker images:
|
|||
Rust, please file an issue.
|
||||
|
||||
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
|
||||
|
||||
### 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
|
||||
|
||||
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:
|
||||
|
||||
```rust
|
||||
extern crate openssl_probe;
|
||||
|
||||
fn main() {
|
||||
openssl_probe::init_ssl_cert_env_vars();
|
||||
//... your code
|
||||
|
@ -205,7 +200,7 @@ This is missing many of the libraries used by the `x86_64` build, and it should
|
|||
|
||||
## 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
|
||||
|
||||
|
|
|
@ -9,3 +9,4 @@ diesel = { version = "1", features = ["postgres", "sqlite"] }
|
|||
libsqlite3-sys = { version = "*", features = ["bundled"] }
|
||||
# Needed for Postgres.
|
||||
openssl = "*"
|
||||
openssl-probe = "0.1.2"
|
||||
|
|
|
@ -46,6 +46,8 @@ where
|
|||
}
|
||||
|
||||
fn main() {
|
||||
openssl_probe::init_ssl_cert_env_vars();
|
||||
|
||||
println!("Hello, world!");
|
||||
|
||||
// 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
|
||||
|
||||
# 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 \
|
||||
--build-arg BASE_IMAGE="$IMAGE_NAME" \
|
||||
-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'
|
||||
"
|
||||
|
||||
# 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`.
|
||||
docker build -t rust-musl-builder-linking-with-git2 examples/linking-with-git2
|
||||
docker run --rm rust-musl-builder-linking-with-git2 bash -c "
|
||||
|
|
Loading…
Reference in a new issue