Skip to content

Upgrade base image to Ubuntu 20.04 #134

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

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 issues are discovered in a library.

## [Unreleased]

### Changed

- Updated base image to Ubuntu 20.04. Major thanks to @asaaki for figuring out why the check for successful static linking was returning false negatives.

## 2021-12-23

### Added
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Use Ubuntu 18.04 LTS as our base image.
FROM ubuntu:18.04
# Use Ubuntu 20.04 LTS as our base image.
FROM ubuntu:20.04

# The Rust toolchain to use when building our image. Set by `hooks/build`.
ARG TOOLCHAIN=stable
Expand Down
31 changes: 25 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@
- [Source on GitHub](https://github.com/emk/rust-musl-builder)
- [Changelog](https://github.com/emk/rust-musl-builder/blob/master/CHANGELOG.md)

**UPDATED:** We are now running builds on GitHub, including scheduled builds of `stable` and `beta` every Thursday!
**UPDATED:**

However, **[`rustls`](rustls) now works well** with most of the Rust ecosystem, including `reqwest`, `tokio`, `tokio-postgres`, `sqlx` and many others. The only major project which still requires `libpq` and OpenSSL is [Diesel](https://diesel.rs/). If you don't need `diesel` or `libpq`:
- We are now using Ubuntu 20.04 as our base image!
- We are now running builds on GitHub, including scheduled builds of `stable` and `beta` every Thursday!

- See if you can switch away from OpenSSL, typically by using `features` in `Cargo.toml` to ask your dependencies to use [`rustls`](rustls) instead.
- If you don't need OpenSSL, try [`cross build --target=x86_64-unknown-linux-musl --release`](https://github.com/rust-embedded/cross) to cross-compile your binaries for `libmusl`. This supports many more platforms, with less hassle!

[rustls]: https://github.com/rustls
See our [CHANGELOG](https://github.com/emk/rust-musl-builder/blob/main/CHANGELOG.md) for more details.

## What is this?

Expand All @@ -29,6 +27,27 @@ This command assumes that `$(pwd)` is readable and writable by uid 1000, gid 100

For a more realistic example, see the `Dockerfile`s for [examples/using-diesel](./examples/using-diesel) and [examples/using-sqlx](./examples/using-sqlx).

## Should you use this to distribute your Rust program?

In general, linking against OpenSSL and/or `libpq` will limit your portability and bring you extra headaches. In an ideal world, you would avoid C libraries, replace OpenSSL with [`rustls`][rustls], and build your binary using [`cross`](https://github.com/rust-embedded/cross). It's a super nice workflow:

```sh
# What you would ideally do instead of using rust-musl-builder.
cross build --target=x86_64-unknown-linux-musl --release
```

`cross` is a drop-in replacement for `cargo`, and it will allow you cross-compile for many different platforms. Even better, it's supported by the Rust Tools team. The downside: It doesn't support OpenSSL, or anything which requires OpenSSL. So if you want to do this, you'll need to configure libraries like `hyper`, `reqwest` and `tokio-postgres` to use [`rustls`][rustls] instead. See the documentation for each library for instructions. This is often the least painful choice.

### Use case 1 for `rust-musl-builder`: You need to link `libpq` and OpenSSL for `diesel`

The standard PostgreSQL client library for C is `libpq`. The popular [Diesel](https://diesel.rs/) crate uses `libpq`. And `libpq` links against OpenSSL. So in order to use `diesel`, you need to link against OpenSSL. If you want to link OpenSSL and `libpq` statically, then you can't use `cross`. But you can use `rust-musl-builder`.

### Use case 2 for `rust-musl-builder`: You need to support weird TLS certificates

[`rustls`][rustls] is a fantastic crate and it's very easy to work with. However, it relies on `webpki` to parse TLS certificates, and `webpki` may break if it encounters weird certificates. For example, [it requires a valid `subjectAltName`](https://github.com/briansmith/webpki/issues/11). Unfortunately, hosted PostgreSQL servers tend to omit `subjectAltName`. This is known to be a problem with the soon-to-be-defunct Citus Data, and with Google's Cloud PostgreSQL solution. In these cases, you'll probably need OpenSSL for now.

[rustls]: https://github.com/rustls

## Deploying your Rust application

With a bit of luck, you should be able to just copy your application binary from `target/x86_64-unknown-linux-musl/release`, and install it directly on any reasonably modern x86_64 Linux machine. In particular, you should be able make static release binaries using TravisCI and GitHub, or you can copy your Rust application into an [Alpine Linux container][]. See below for details!
Expand Down
1 change: 1 addition & 0 deletions examples/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/bin/
58 changes: 32 additions & 26 deletions test-image
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,46 @@ docker build -t ekidd/rust-musl-builder .
# Make sure we can build our example derived container.
docker build -t rust-musl-zlib examples/adding-a-library

# Make sure we can build a multi-stage container.
docker build -t rust-musl-builder-using-diesel examples/using-diesel
docker run --rm rust-musl-builder-using-diesel

echo "==== Verifying static linking"

# Helper function to verify static linking.
function check_static_linking() {
local image="$1"
local container_bin_path="$2"

local bin_basename="$(basename $container_bin_path)"
local bin_path="examples/bin/$bin_basename"

echo -e "--- Test case for $bin_basename:"
local container="$(docker create "$1")"
docker cp "$container:$container_bin_path" "$bin_path"
docker rm -f "$container"
echo 'ldd says:'
ldd "$bin_path" > .tmp-ldd-output
if ! grep "statically linked" .tmp-ldd-output ; then
rm .tmp-ldd-output
echo "[FAIL] $bin_path is not static!" 1>&2
exit 1
fi
rm .tmp-ldd-output
echo -e "[PASS] $bin_path binary is statically linked.\n"
}

mkdir -p examples/bin

# Make sure we can build a static executable using `diesel`.
docker build -t rust-musl-builder-using-diesel examples/using-diesel
docker run --rm rust-musl-builder-using-diesel
check_static_linking rust-musl-builder-using-diesel /usr/local/bin/using-diesel

# 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'
"
check_static_linking rust-musl-builder-using-sqlx /usr/local/bin/using-sqlx

# 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 "
set -euo pipefail
cd /home/rust/src

echo -e '--- Test case for libgit2:'
echo 'ldd says:'
if ldd target/x86_64-unknown-linux-musl/debug/linking-with-git2; then
echo '[FAIL] Executable is not static!' 1>&2
exit 1
fi
echo -e '[PASS] libgit2 binary is statically linked.\n'
"
check_static_linking rust-musl-builder-linking-with-git2 /home/rust/src/target/x86_64-unknown-linux-musl/debug/linking-with-git2

# We're good.
echo 'OK. ALL TESTS PASSED.' 1>&2