お久しぶりです. Omni Hub チームの shunten31 です. 早朝に散歩する習慣があるのですが、 朝の風がひんやりしてきましたね.
今回は、 Sentry に Rust アプリケーションの Debug Information File をアップロードするように、デプロイフローを改修したので、その方法について紹介していきます.
Sentry では、 アプリケーションの実行ファイルに対応する Debug Information Files を事前にアップロードすることで、 エラー発生時の Sentry イベントにスタックトレース情報を付加できるのですが、実際のデプロイフローにおいて Sentry に Debug Information File アップロードする具体的方法や事例が、 英語・日本語問わず見当たりませんでした. 紹介する方法が最善かはわかりませんが、どなたかの参考になればと思い、実施方法を紹介させていただきます.
現状の Docker イメージのビルドフロー
現在利用している Dockerfile から、 関連部分を抜粋したものを以下に示します.
マルチステージビルドを用いており、 rust-builder ステージでビルドを行い、 app ステージが最終的な実行環境となります.
Dockerfile
FROM amazonlinux-base AS rust-builder
WORKDIR /app
COPY . .
RUN cargo build --release --bin server --bin worker \
&& mkdir -p /dist \
&& (find target/release -maxdepth 1 -type f | xargs -I{} cp "{}" /dist)
FROM amazonlinux-base AS app
WORKDIR /app
COPY --from=rust-builder /dist bin
CMD ["bin/server"]
EXPOSE 5000 5001
上記 Dockerfile の app ステージは、 GitHub Actions を利用して ECR にアップロードしています.
GitHub Actions
- uses: docker/build-push-action@v6 id: docker_build with: builder: ${{ steps.docker-builder.outputs.name }} context: . target: app push: true
Debug Information File の作成
公式ドキュメント に従って、 Debug Information File を作成します.
まず、 Cargo.toml を編集して、 release build にもデバッグ情報が含まれるようにします.
[profile.release] debug = true
次に、 実行ファイル(この例では server と worker)からデバッグファイルを抽出します.
objcopy --only-keep-debug target/release/app{,.d}
objcopy --strip-debug --strip-unneeded target/release/app
objcopy --add-gnu-debuglink target/release/app{.d,}
各コマンドの役割は以下の通りです.
appのデバッグ情報をapp.dへ抽出しますappからデバッグ情報などの不要情報を削ります. これで実行ファイルが軽くなりますappバイナリにapp.dというデバッグシンボルファイルが存在するというリンク情報を埋め込みます
この処理を Docker イメージのビルドステップに組み込みます.
FROM amazonlinux-base AS rust-builder
WORKDIR /app
COPY . .
RUN cargo build --release --bin server --bin worker \
&& mkdir -p /dist \
&& objcopy --only-keep-debug target/release/server{,.d} \
&& objcopy --strip-debug --strip-unneeded target/release/server \
&& objcopy --add-gnu-debuglink target/release/server{.d,} \
&& objcopy --only-keep-debug target/release/worker{,.d} \
&& objcopy --strip-debug --strip-unneeded target/release/worker \
&& objcopy --add-gnu-debuglink target/release/worker{.d,} \
&& (find target/release -maxdepth 1 -type f | xargs -I{} cp "{}" /dist) \
Debug Information File の抽出
現状では、 Debug Information File は Docker イメージのビルドステップ内部にしか存在しません. そのため、 必要なファイルをビルドの外部へエクスポートする必要があります.
これを行うには、Export binaries | Docker Docs を参考に、 エクスポート用のビルドステージを定義します. なお、 scratch イメージは最小構成の空イメージです.
FROM amazonlinux-base AS rust-builder WORKDIR /app COPY . . RUN cargo build --release --bin server --bin worker \ - && mkdir -p /dist \ + && mkdir -p /dist /target/release \ && objcopy --only-keep-debug target/release/server{,.d} \ && objcopy --strip-debug --strip-unneeded target/release/server \ && objcopy --add-gnu-debuglink target/release/server{.d,} \ @@ && objcopy --add-gnu-debuglink target/release/worker{.d,} \ && (find target/release -maxdepth 1 -type f | xargs -I{} cp "{}" /dist) \ + && cp target/release/server target/release/server.d \ + target/release/worker target/release/worker.d \ + /target/release/ + FROM scratch AS export + COPY --from=rust-builder /target /target
build-push-action@v6 を利用することで、 export ステージをビルドしています.
outputs: type=local,dest=./target-export を設定しているので、 export ステージのファイルが、 CI 実行マシン上の ./target-export にコピーされます.
※ なお、 push: false に設定されているので、 ビルドしたイメージはレポジトリにプッシュされることはありません.
さらに、 コピーされたファイルを後続ジョブで利用できるよう artifact としてアップロードしておきます.
- uses: docker/build-push-action@v6 id: export_target with: builder: ${{ steps.docker-builder.outputs.name }} context: . target: export push: false outputs: type=local,dest=./target-export - name: Upload artifact uses: actions/upload-artifact@v4 with: name: target-export path: ./target-export/target retention-days: 14
Debug Information File を Sentry にアップロード
別のジョブで、 先ほど artifact として保存したファイルを取得し、 Sentry にアップロードします.
upload-debug-files: name: Upload debug files runs-on: ubuntu-22.04 needs: app # artifact を upload したジョブ名 steps: - name: Download artifact uses: actions/download-artifact@v4 with: name: target-export - name: Install Sentry CLI env: SENTRY_CLI_VERSION: 2.54.0 run: | curl -sL https://sentry.io/get-cli/ | sh - name: Upload debug files to Sentry env: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_ORG: "***" SENTRY_PROJECT: server run: | sentry-cli debug-files upload --include-sources ./release
動作確認
このフローで作成したアプリケーションのイメージをデプロイすれば、 Sentry の Issue 上で事前にアップロードした Debug Information File が自動的に検知され、スタックトレース情報が表示されます.
