Dockerfileで複数行を改行付きでechoする際にハマったので共有しておきます
はじめに
最近Dockerfileを作成したときに、 RUN
コマンド内で改行付き情報を echo
したかったのですが、多少ハマってしまったので共有します。
「2019-07-17 追記」コメント欄より
コメントを下さった Nig さん、ありがとうございます。勉強になりました。
以下のような構文を利用する際に、シングルクォーテーション( '
)で記述しないといけない部分がダブルクォーテーション( "
)になっていたことが原因とのことでした。
*※debian系のLinuxOSを利用している場合、シングルクォーテーションの前の $
を削除しないといけないようです。不要な $
が出力されてしまいました。
FROM centos:centos7
RUN echo $'\n\
alias ll="ls -l"\n\
alias la="ls -a"\n\
alias lla="ls -l -a"\n\
' >> /root/.bashrc
※上記のスタイル以外で記述したい方は、当エントリを読み進めいただく意義はあるかと思います。
検証環境
$ uname -moi
x86_64 MacBookPro11,4 Darwin
$ docker --version
Docker version 18.09.2, build 6247962
経緯(失敗例)
Dockerイメージ作成のために「Dockerfile」を作成しました。
その際に、.bashrc
ファイルにalias
を追加したかったので、 ネット上に転がっている情報を参考に 以下のように記述しました。
FROM centos:centos7
RUN echo $"\n\
alias ll='ls -l'\n\
alias la='ls -a'\n\
alias lla='ls -l -a'\n\
" >> /root/.bashrc
echo
コマンドの引数として渡す情報の各行末に \n\
と記述することで、以下の命令と同等の出力が行われるとのことでした。
$ echo $"
alias ll='ls -l'
alias la='ls -a'
alias lla='ls -l -a'
" >> /root/.bashrc
実際に試してみると...
イメージをビルドし、起動してみます。
# ビルド
$ docker build . --tag=genzouw/test
# 起動
$ docker run --rm -it genzouw/test bash
bash: nalias: command not found
[root@19775d30756e /]#
一応起動はできたのですが、エラーが発生しています。~/.bashrc
を確認してみます。
[root@19775d30756e /]# tail ~/.bashrc
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
\nalias ll='ls -l'\nalias la='ls -a'\nalias lla='ls -l -a'\n
最終行の alias
の内容がめちゃくちゃですね。
うまく改行できていないことがわかります。
echo -e
で対処する
「Dockerfile」を以下のように書き換えることで対処できました。
FROM centos:centos7
RUN echo -e "\n\
alias ll='ls -l'\n\
alias la='ls -a'\n\
alias lla='ls -l -a'\n\
" >> /root/.bashrc
ビルドしてイメージを作成後、起動すると今度は問題なく動作しました。
echo -e
とは?
マニュアルを引いてみる。
$ man echo
一部抜粋すると以下のように書かれている。
-e enable interpretation of backslash escapes
...
If -e is in effect, the following sequences are recognized:
...
\n new line
-e
オプションを付けないと \n
を改行として取り扱ってくれないようですね。
他のGithubリポジトリではどうしている?
ちなみに、他のGithubリポジトリではどうしているのか知りたくありませんか?
ためしに WordPress のリポジトリを覗いてみました。
非常に簡潔で、echo
コマンドを連発するという方法をとっています。
以下、一部抜粋
...
RUN { \
echo 'opcache.memory_consumption=128'; \
echo 'opcache.interned_strings_buffer=8'; \
echo 'opcache.max_accelerated_files=4000'; \
echo 'opcache.revalidate_freq=2'; \
echo 'opcache.fast_shutdown=1'; \
} > /usr/local/etc/php/conf.d/opcache-recommended.ini
...
{...}
のシェル構文でecho
コマンドの実行結果をグルーピングし、ファイルにリダイレクト、という方法をとっています。見やすいですね。
ひとこと
環境に依存するのかな?
なぜ他の方々は -e
オプション無しで問題が起きてないのか。
ディスカッション
コメント一覧
コメント機能が直ったようで、よかったです。
エスケープシーケンスが働かない件ですが、$”stirng”になっているためかと思います。
man bashを叩くと、QUOTINGの項で$’string’と$”string”についての解説があります。
$’string’ですと、エスケープシーケンスが展開されます。
>> Nigさん
ありがとうございます!問題が解決しました。
勉強になりました。