目的
Apple M1チップ搭載のMac上のDocker環境でRails5を動かしています。ベースのイメージはruby:2.7.3
です。(ちなみにruby:2.5.8
でも同様の現象が生じました。)Rails自体は問題なくインストール、pumaでの起動ができるのですが、問題はBootstrapの導入を試みたときです。世の指南書にあるようにGemでBootstrapをインストールし、サーバを再起動して、適切にapplication.scss
を記述して、いざブラウザ越しにアプリケーションへアクセスすると無残にも「このサイトにアクセスできません」状態となります。
サーバ側のログを確認すると
*** stack smashing detected ***: <unknown> terminated
とのこと。このstack smashing detected
エラーをGoogleで検索してみると、C言語でスタックオーバーラン等が起こった時に出るエラーという解説がたくさん出てきます。Gem使っていてC言語のエラーに遭遇するとか想定外です。
このエラーに対する根本的な解決策を見出すのは困難であると考え、また、楽したいために導入したBootstrapで、そんな苦難の道を進むことになるのは本末転倒ですので、早々にGemを諦めて、もっと気軽にBootstrapを導入する方法を探りました。
というわけで、この文章の対象者は、
- RailsにBootstrapを導入したら
stack smashing detected
エラーに遭遇したが、 - そのエラーの根本解決を望んでいるわけではなく、
- Bootstrapが気軽に導入できればよい、
という状況の方になります。
環境
筆者の環境は以下です。
- Apple M1 Mac
- macOS Big Sur
- Docker Desktop 3.6.0
- イメージ ruby:2.7.3
- Rails 5.2.0
- Bootstrap 4.5.0
おそらくRubyの2系、Rails5(6は不明)、Bootstrap4または5を使用してstack smashing detected
エラーが出るなら同じ状況かと思います。これらのバージョンより、M1のDockerというのが問題なのではないかという気がしています。
とにかく素のBootstrapが入ればいい人向け
この場合は簡単です。(たぶんそういう人はQiita読んでいないと思いますが。)レイアウト等でCDNからbootstrap.css
を引っ張ってくれば良いだけです。具体的には、app/views/layouts/application.html.erb
に
<!DOCTYPE html>
<html>
<head>
<title>Your App</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-\
track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reloa\
d' %>
</head>
<body>
...
</body>
</html>
のような感じで、Bootstrapの公式サイトの導入部分に示されているように、linkタグを埋め込んでしまえば普通に使えます。バージョンはお好きなものを。
CDNからの読み込みを避けたいという人も特に難しくはありません。その場合は上記公式サイトのダウンロードボタンをクリックし、bootstrap.css
をダウンロードしてアプリケーションのapp/assets/stylesheets
ディレクトリに放り込みます。あとはapplication.css
に
*= require_tree .
の記述があれば勝手にアセットパイプラインが働いて、いい感じに処理してくれます。
SCSS使いたい人向け
おそらく本当に困っているのはこちらの人ではないでしょうか。筆者もそうなのですが、Bootstapが入ればいいとはいえ、やっぱりprimary
とかsecondary
の色は変えたい、とかそういう人です。素のCSSを置換して回るのはお手軽ではありません。
この場合にはbootstrap.scss
を導入する必要があります。上記のBootstrapの公式サイトのダウンロードページから、CSSファイルではなくソースファイルのダウンロードをしてください。ダウンロードされたZipを解凍すると、その中にscss
というディレクトリがあります。その中身を全てアプリケーションのapp/assets/stylesheets
の中に放り込みます。bootstrap.scss
、bootstrap-reboot.scss
、bootstrap-grid.scss
や_
から始まる複数のscssファイル、vendor
、utilities
、mixins
の各ディレクトリも全てです。(結構なファイル数です。)
そして、application.css
の拡張子をapplication.scss
とSCSSに変更します。さらにそのファイルを開いて、
*= require_tree .
この行は削除してください。これを削除しないと、Railsのアセットパイプラインが、先程コピーした全ファイルを勝手な順序でコンパイルし始めてエラーが起こりまくります。
あとは手動でSCSSの文法を用いて、先程コピーしたbootstrap.scss
のみをインポートします。
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
* vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*
*= require_self
*/
$theme-colors: (
primary: #000000,
secondary: #ffffff
);
@import "bootstrap";
bootstrap.scss
の中身を見るとわかるのですが、他のSCSSファイルはその中でインポートされます。というか、このbootstrap.scss
自体は他のファイルのインポートしかしていません。ちなみに上記コードの@import
行の前にある$theme-colors
変数の定義は不要です。これはBootstrapのプライマリカラーとセカンダリカラーを変更するためのものです。筆者はこのたったの4行の定義をBootstrapに反映したいために、stack smashing detected
にぶち当たって苦労しました。
まとめ
RailsにBootstrapを導入した時に起こるstack smashing detected
エラーの回避方法を紹介しました。解決方法ではないことに注意してください。おそらく根本的なエラーの解決策を探るならば、Bootstrapを使わないで自力でCSSを書くほうがお手軽なのではないかと思います。エラーの出る理由くらい知りたい気はしますが、Dockerのバージョンアップ等を重ねるうちにいつの間にか解消されていることを期待します。