DockerfileのRUNでExpectスクリプトを実行して、keyboard-configurationパッケージのインストールを自動化する例を記載します。ただし、結論を言えば、Expectスクリプトは別ファイルで用意すべきです。
Table of Contents
1 keyboard-configurationパッケージ
keyboard-configurationパッケージをインストールするとキーボードレイアウトをインタラクティブに設定できます。
keyboard-configurationパッケージの応答は/etc/default/keyboardを用意すればスキップできますが、console-setupパッケージのようにできないケースもあるので、ここではExpectスクリプトを使って応答を自動化します。
2 Expectスクリプトの場合
keyboard-configurationのインストールを自動化するには以下のExpectスクリプトが必要なります。
- "[More]"に対して"\n"を送信します。Expectスクリプトは[と]に対して\\\でエスケープする必要があります。
- "Country of origin for the keyboard: "に対して"50\n"を送信します。
- "Keyboard layout: "に対して"1\n"を送信します。
#!/usr/bin/env expect set timeout -1 spawn apt-get install -y keyboard-configuration expect { "\\\[More\\\]" { send "\n"; exp_continue; } "Country of origin for the keyboard: " { send "50\n"; } } expect { "\\\[More\\\]" { send "\n"; exp_continue; } "Keyboard layout: " { send "1\n" } } expect eof
[More]はキーボード一覧表示がターミナルソフトの高さに到達した場合に表示されます。
Configuring keyboard-configuration ---------------------------------- The layout of keyboards varies per country, with some countries having multiple common layouts. Please select the country of origin for the keyboard of this computer. [More]
3 シェルスクリプトの場合
シェルスクリプトにすると以下のようになります。
- ダブルコーテーション内の\\\が\に変換されます(シングルコーテーションの場合は\\が\に変換されますが、シェル変数を代入できません)。
- printfの場合はシェルでの改行が改行文字として扱われます。
#!/bin/sh apt-get update -y apt-get install -y expect printf " set timeout -1 spawn apt-get install -y keyboard-configuration expect { \"\\\\\\\\\[More\\\\\\\\\]\" { send \"\\\n\"; exp_continue; } \"Country of origin for the keyboard: \" { send \"50\\\n\"; } } expect { \"\\\\\\\\\[More\\\\\\\\\]\" { send \"\\\n\"; exp_continue; } \"Keyboard layout: \" { send \"1\\\n\" } } expect eof " | expect
4 Dockerfileの場合
Dockerfileにすると以下のようになります。
- Dockerfileは行末に\をつけることで複数行に処理を記載できます。
- 複数行に処理を記載してもDockefileでの改行は処理に渡されません。printfの文字列の場合は改行文字の\nを明記する必要があります。複数のコマンドを記載する場合はセミコロンや&&で繋ぐ必要があります。
- [More]の処理は不要になるようです(-tオプションなしでTERMを空にしている?)。
FROM ubuntu:16.04 RUN apt-get update -y && \ apt-get install -y expect && \ printf "\ set timeout -1\n\ spawn apt-get install -y keyboard-configuration\n\ expect {\n\ \"\\\\\\\\\[More\\\\\\\\\]\" { send \"\\\n\"; exp_continue; }\n\ \"Country of origin for the keyboard: \" { send \"50\\\n\"; }\n\ }\n\ expect {\n\ \"\\\\\\\\\[More\\\\\\\\\]\" { send \"\\\n\"; exp_continue; }\n\ \"Keyboard layout: \" { send \"1\\\n\" }\n\ }\n\ expect eof\n\ " | expect
5 まとめ
ExpectスクリプトをDockerfileのRUNで直接使おうとすると余計なコストが掛かります。Expectスクリプトを別に用意し、DockerfileのCOPYやADDでコンテナにコピーしてから実行するようにしましょう。
FROM ubuntu:16.04 RUN apt-get update -y && apt-get instal -y expect COPY keyboard-configuration.exp / RUN expect keyboard-configuration.exp