はじめに

Rustでスタティックリンクなバイナリ(いわゆるシングルバイナリ)を作るときはlibcとしてmuslを使うことができます。
しかしmuslはlibcでしかないので、それ以外のライブラリ(opensslなど)を使っている場合はそれ用のスタティックリンクライブラリをそれぞれ用意しないといけません。

これは結構面倒なので、よく使いそうなライブラリをまとめてDockerコンテナにしたものがrust-musl-builderです。

今回はこれをAzure Pipelinesで使ってみました。

最終結果

いろいろ試行錯誤した結果、以下でOKでした。

jobs:
    - job: musl
      pool:
          vmImage: 'ubuntu-16.04'
      steps:
          - script: |
              chmod 777 .
              docker run --rm -v "$(pwd)":/home/rust/src ekidd/rust-musl-builder cargo build --release --target=x86_64-unknown-linux-musl

chmod 777 .はDockerコンテナ内のUIDとAzureのUIDが異なるので、Docker内からtargetディレクトリを作成できるようにするためです。
また、Dockerコマンドはrust-musl-builderのREADMEなどでは-itオプションがついていますが、これをつけてはいけません。
Azure Pipelinesではscriptは一旦テンポラリのファイルに書かれて/bin/bash –noprofile –norc xxx.shという感じで実行されるため、-itオプションがあるとDockerがttyに接続できずエラーとなります。

コンテナ内ビルド

Azure Pipelinesには以下のようにDockerコンテナ内でビルドする方法もあり、いろいろと試したのですが、これは罠でした。

resources:
    containers:
        - container: musl
            image: ekidd/rust-musl-builder:latest

jobs:
    - job: musl
      pool:
          vmImage: 'ubuntu-16.04'
      container: musl
      steps:
          - script:
              cargo build --release --target=x86_64-unknown-linux-musl

まずrust-musl-builderはRustのツールチェインを一般ユーザrustでインストールして実行もそのユーザで行います。
しかしAzure PipelinesのDockerコンテナ実行スクリプトはvsts_azpcontainerというようなユーザを新規作成して、その権限で動こうとします。このあたりの挙動はAzure Pipelines組み込みであり、ymlで制御することはできません。
そのためrust-musl-builderのDockerfileをいじって通るようにするしかないのですが、大変な割に大したメリットもないです。
(scriptのコマンドが短いくらい?)
素直にdockerコマンドを使うのがいいと思います。

bannerAds