Docker :: Arch Linux(Manjaro Linux)でCentOS6.*のイメージが起動しない場合の対処法


この記事について

  • Arch LinuxとManjaro LinuxにCentOS6.* ベースのDockerコンテナを構築しようとしたけど起動できなかった時のメモ

背景

  • CentOS6系で動いていた古いWebアプリを動かしたくなり、Dockerの勉強の一環として、そのWebアプリをDocker化してみようと思った
  • CentOSの公式のdockerイメージは6.6から公開されているので、それを利用して当該アプリを構築しようと思った

前提条件/環境

  • ホストOS: Arch Linux @ Conoha VPS / Manjaro Linux @ Virtual Box on Windows 10
    • ※複数環境で試しました。
  • Dockerのバージョン :  18.09.1-ce (両環境とも)
  • 対象とするCentOSベースイメージ : CentOS6.6 / CentOS6.7 / CentOS6.9

問題

  • dockerイメージのpullまで成功するが、docker run やdocker startコマンド実行しても起動しない(正確には、起動直後に終了する)

結論

  • 起動直後にコンテナが終了するのは、CentOS6.*のバイナリ/ライブラリの実行に必要なvsyscallが、ホストOSで無効になっているため
  • ブート時のカーネルパラメータオプションに "vsyscall=emulated"を追加することで起動できるようになった

今後

  • 公式ドキュメントはちゃんとよく読むようにする
  • Linuxのシステムコール周りを理解していきたい
  • 引き続きDockerの勉強を深めたい

詳細

問題に直面した時にやったこと

  • Arch Linux / Manjaro Linux にdocker とdocker-compose をインストール
  • centos:6.6 からイメージをプルして実行(-i -t オプション)
bash
 $ docker run -i -t centos:6.6 /bin/bash
  • イメージをダウンロードするところまでは成功しているようだけど、起動できない。
  • "docker ps -a "を実行すると"Exited"になっている
  • よくよく見ると"dockr run 実行時に コード(139)でExitedしている

解決しなかったけど試したこと

  • "docker exit 139"とかで検索
  • プログラミングのQAサイトで似たような問題への対処法として"dockerはLinuxディストリビューションによってbuggyだからubuntuあたりで試して見ては"とあることを発見
  • ひとまずVirtual Boxでubuntuの仮想マシンを作成し、同様にdocker run実行
  • 結局ubuntuでも同じ現象になることを確認

解決に至った経緯

  • もう一度原点に戻って公式(Arch Linux, CentOSのdocker image配布サイト)の記述を再確認(英語なのでかなり流し読みしていた)
  • Arch Linux のdocker関連開設ページにも、CentOSの公式docker配布サイトにも書いてあった
    • CentOSの6.*系のイメージのバイナリやライブラリは vsyscallマッピングというのを経由てのアクセスを想定しているので、vsyscallマッピングが無効になっているディストリビューションでは、runしてもすぐに止まってしまう場合があるとのこと。
    • 解決するには、カーネルパラメータに "vsyscall=emulate"を追加する。

具体的な作業

  1. /etc/default/grubを開き、カーネルオプションを追加

    grub
           ...
           GRUB_CMDLINE_LINUX_DEFAULT="quiet splash <...> vsyscall=emulate"
           ...
    

    ※スペース区切りで追加するらしい

  2. grub.cfg ファイルを自動生成

    bash
        # grub-mkconfig -o /boot/grub/grub.cfg
    
  3. ホストOS再起動

参考URL / 引用

A note about vsyscall
CentOS 6 binaries and/or libraries are built to expect some system calls to be accessed via vsyscall mappings. Some linux distributions have opted to disable vsyscall entirely (opting exclusively for more secure vdso mappings), causing segmentation faults.

If running docker run --rm -it centos:centos6.7 bash immediately exits with status code 139, check to see if your system has disabled vsyscall:

$ cat /proc/self/maps | egrep 'vdso|vsyscall'
7fffccfcc000-7fffccfce000 r-xp 00000000 00:00 0 [vdso]
$
vs

$ cat /proc/self/maps | egrep 'vdso|vsyscall'
7fffe03fe000-7fffe0400000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
If you do not see a vsyscall mapping, and you need to run a CentOS 6 container, try adding vsyscall=emulated to the kernel options in your bootloader

Further reading : lwn.net

*Arch Linux Wiki/Dockerより引用

ノート: linux 4.15.0-1 の時点で、特定のプログラム(apt-get など)で必要な vsyscalls は、カーネルの設定ではデフォルトで無効になっています。再度有効にするには、vsyscall=emulate をカーネルパラメータに追加します。さらに詳しい情報は FS#57336 を参照。

*Arch Linux Wiki より引用

/boot/grub/grub.cfg を開いて上と同じ行を編集することもできますが、初心者におすすめの方法は:
/etc/default/grub を開きカーネルオプションを GRUB_CMDLINE_LINUX_DEFAULT 行に追加:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"

そして grub.cfg ファイルを自動生成します:

# grub-mkconfig -o /boot/grub/grub.cfg

GRUB の設定について、詳しくは GRUB を見て下さい。

最後に...教訓

  • 公式ドキュメントは、英語でしんどくても、ちゃんと読むのが近道。