Go to file
Eric Kidd 388941cd8a Update Ubuntu and other dependencies
We update our base image to Ubuntu 18.04, and update all of our
dependencies to the latest released versions. This includes:

- gcc-multilib-arm-linux-gnueabihf (latest distro version)
- mdbook 0.2.1 (0.2.3 is out, but there's no binary build)
- OpenSSL 1.1.1b
- libpq 11.2
2019-04-18 12:10:44 -04:00
examples examples/using-diesel: Fix link errors 2019-04-18 11:34:20 -04:00
hooks Update Ubuntu and other dependencies 2019-04-18 12:10:44 -04:00
.gitignore Add working example and test case for diesel 2017-10-24 09:05:22 -04:00
.travis.yml [test][chore] add travis config and use git2 dependency in test 2018-03-26 09:10:17 +02:00
Dockerfile Update Ubuntu and other dependencies 2019-04-18 12:10:44 -04:00
LICENSE-APACHE.txt Add licenses 2016-04-17 07:45:08 -04:00
LICENSE-MIT.txt Add licenses 2016-04-17 07:45:08 -04:00
README.md examples/using-diesel: Fix link errors 2019-04-18 11:34:20 -04:00
cargo-config.toml Update Ubuntu and other dependencies 2019-04-18 12:10:44 -04:00
git-credential-ghtoken Add support for accessing private GitHub repositories 2018-02-28 06:59:21 -05:00
sudoers Overhaul extensively and add test script 2016-04-17 07:42:09 -04:00
test-image Merge branch 'fix/link_zlib_with_test' of https://github.com/mriehl/rust-musl-builder 2018-04-08 13:42:02 -04:00

README.md

rust-musl-builder: Docker container for easily building static Rust binaries

Docker Image

Do you want to compile a completely static Rust binary with no external dependencies? If so, try:

alias rust-musl-builder='docker run --rm -it -v "$(pwd)":/home/rust/src ekidd/rust-musl-builder'
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.

To target ARM hard float (Raspberry Pi):

rust-musl-builder cargo build --target=armv7-unknown-linux-musleabihf --release

Binaries will be written to target/$TARGET_ARCHITECTURE/release. By default it targets x86_64-unknown-linux-musl unless specified with --target.

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!

Caching builds

You may be able to speed up build performance by adding the following -v commands to the rust-musl-builder alias:

-v cargo-git:/home/rust/.cargo/git
-v cargo-registry:/home/rust/.cargo/registry
-v target:/home/rust/src/target

You will also need to fix the permissions on the mounted volumes:

rust-musl-builder sudo chown -R rust:rust \
  /home/rust/.cargo/git /home/rust/.cargo/registry /home/rust/src/target

How it works

rust-musl-builder uses musl-libc, musl-gcc, and the new rustup target support. It includes static versions of several libraries:

This library also sets up the environment variables needed to compile popular Rust crates using these libraries.

Extras

This image also supports the following extra goodies:

  • Basic compilation for armv7 using musl-libc. Not all libraries are supported at the moment, however.
  • mdbook for building searchable HTML documentation from Markdown files. Build manuals to use alongside your cargo doc output!
  • cargo audit to check your Rust project for known security issues.

Making OpenSSL work

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 as follows:

extern crate openssl_probe;

fn main() {
    openssl_probe::init_ssl_cert_env_vars();
    //... your code
}

Making Diesel work

In addition to setting up OpenSSL, you'll need to add the following lines to your Cargo.toml:

[dependencies]
diesel = { version = "1", features = ["postgres", "sqlite"] }

# Needed for sqlite.
libsqlite3-sys = { version = "*", features = ["bundled"] }

# Needed for Postgres.
openssl = "*"

For PostgreSQL, you'll also need to include diesel and openssl in your main.rs in the following order (in order to avoid linker errors):

extern crate openssl;
#[macro_use]
extern crate diesel;

If this doesn't work, you might be able to fix it by reversing the order. See this PR for a discussion of the latest issues involved in linking to diesel, pq-sys and openssl-sys.

Making static releases with Travis CI and GitHub

These instructions are inspired by rust-cross.

First, read the Travis CI: GitHub Releases Uploading page, and run travis setup releases as instructed. Then add the following lines to your existing .travis.yml file, replacing myapp with the name of your package:

language: rust
sudo: required
os:
- linux
- osx
rust:
- stable
services:
- docker
before_deploy: "./build-release myapp ${TRAVIS_TAG}-${TRAVIS_OS_NAME}"
deploy:
  provider: releases
  api_key:
    secure: "..."
  file_glob: true
  file: "myapp-${TRAVIS_TAG}-${TRAVIS_OS_NAME}.*"
  skip_cleanup: true
  on:
    rust: stable
    tags: true

Next, copy build-release into your project and run chmod +x build-release.

Finally, add a Dockerfile to perform the actual build:

FROM ekidd/rust-musl-builder

# We need to add the source code to the image because `rust-musl-builder`
# assumes a UID of 1000, but TravisCI has switched to 2000.
ADD . ./
RUN sudo chown -R rust:rust .

CMD cargo build --release

When you push a new tag to your project, build-release will automatically build new Linux binaries using rust-musl-builder, and new Mac binaries with Cargo, and it will upload both to the GitHub releases page for your repository.

For a working example, see faradayio/cage.

Making tiny Docker images with Alpine Linux and Rust binaries

Docker now supports multistage builds, which make it easy to build your Rust application with rust-musl-builder and deploy it using Alpine Linux. For a working example, see examples/using-diesel/Dockerfile.

Adding more C libraries

If you're using Docker crates which require specific C libraries to be installed, you can create a Dockerfile based on this one, and use musl-gcc to compile the libraries you need. For an example, see examples/adding-a-library/Dockerfile. This usually involves a bit of experimentation for each new library, but it seems to work well for most simple, standalone libraries.

If you need an especially common library, please feel free to submit a pull request adding it to the main Dockerfile! We'd like to support popular Rust crates out of the box.

Development notes

After modifying the image, run ./test-image to make sure that everything works.xs

Other ways to build portable Rust binaries

If for some reason this image doesn't meet your needs, there's a variety of other people working on similar projects:

License

Either the Apache 2.0 license, or the MIT license.