新しい行を保持しながら、Dockerfileで複数行のコマンドを作成するにはどうすればよいですか?


86

Dockerfileに次のRUNコマンドを書きたい。しかし、dockerは新しいラインを保持していません。

RUN echo "[repo] \
name            = YUM Repository \
baseurl         = https://example.com/packages/ \
enabled         = 1 \
gpgcheck        = 0" > /etc/yum.repos.d/Repo.repoxyz

\各行の終わりで新しい行をエスケープすることを私は知っています。しかし、新しい行を保持して複数の行を書くことができる方法はありますか?


* nix以外のプラットフォームを使用していますか?Linuxではこれで問題なく動作するからです。
ユーザー

@user、私はLinuxを使用していました。
Venkata Jaswanth 2017年

回答:


115

と呼ばれる「ANSI-Cquoting」を使用できます$'...'元々はksh93の機能でしたが、現在はbash、zsh、mksh、FreeBSD shbusyboxのashで利用できます(ただし、ENABLE_ASH_BASH_COMPATでコンパイルされている場合のみ)。

以下のようRUNが使用する/bin/shデフォルトのシェルとして、あなたは最初SHELL命令を使用してbashのようなものに切り替えることを要求されています。

コマンドを$'で開始し、で終了して'、次のよう\n\に改行に使用します。

SHELL ["/bin/bash", "-c"]

RUN echo $'[repo] \n\
name            = YUM Repository \n\
baseurl         = https://example.com/packages/ \n\
enabled         = 1 \n\
gpgcheck        = 0' > /etc/yum.repos.d/Repo.repoxyz

4
これはbash構文です。詳細については、この質問を参照してください:stackoverflow.com/a/11966402/1395437
Daniel Zolnai 2015年

13
、あなたがやっていることを説明し、ちょうど不透明な溶液をドロップしないでください
エドゥアール・ロペス

25
注意:この$' ... \n\ 手法は、dockerがRUN使用するシェルによって異なりbashます。一部のシステム(Ubuntuなど)では、RUNが使用するシェル/bin/shは、リンクdashではないことが多くbash$'構文を理解していません。
アノン2018

2
@Anonが言ったように、bash以外の場所で実行した場合、これは機能しません。(で動作しないOh My Zshのいずれか)
ラファ

1
@Anonは、シェルを使用するAlpine linux(現在は3.10.2を使用しています)でも機能します。
suchoss

53

使用しましたprintf。「\ n」を使用してすべてのテキストを1行に書き込みます。

実行中:

RUN printf 'example \ntext \nhere' >> example.txt

挿入物:

example
text
here

example.txtで


19

次を使用できます。

RUN echo -e "\
[repo] \n\
name            = YUM Repository \n\
baseurl         = https://example.com/packages/ \n\
enabled         = 1 \n\
gpgcheck        = 0\
" > /etc/yum.repos.d/Repo.repoxyz

このようにして、ファイルの内容をすばやく確認することができます。すべての行をで終了\\n、必要に応じて挿入する必要があることに注意する必要があります。


1
これにはecho -e解釈が必要です\n
PatrickBergner19年

7

新しい行\nがで機能しなかったため、上記の例を組み合わせて使用​​することになりましたecho

RUN printf 'example \n\
text \n\
here' >> example.txt

予想どおり、次のように生成されます。

example
text
here

1
あなたの答えはCTodeaの答えとどう違うのですか?
ゴッドファーザー

@TheGodfatherこれは複数行の例です。元の質問にもよく答えます。
セルゲイ

2

それはあなたを助けるかもしれません(https://github.com/jen-soft/pydocker

[Dockerfile.py]

from pydocker import DockerFile  # sudo pip install -U pydocker

d = DockerFile(base_img='debian:8.2', name='jen-soft/custom-debian:8.2')

d.RUN_bash_script('/opt/set_repo.sh', r'''
cat >/etc/apt/sources.list <<EOL
deb     http://security.debian.org/ jessie/updates main
deb-src http://security.debian.org/ jessie/updates main
EOL
apt-get clean && apt-get update
''')

d.EXPOSE = 80
d.WORKDIR = '/opt'
d.CMD = ["python", "--version"]

# d.generate_files()
d.build_img()

# sudo wget -qO- https://get.docker.com/ | sh

python Dockerfile.py
docker images

-1

RUNを数回実行して、ファイルを完成させることができます。

RUN echo "[repo]" >> /etc/yum.repos.d/Repo.repoxyz
RUN echo "name            = YUM Repository" >> /etc/yum.repos.d/Repo.repoxyz
RUN echo "baseurl         = https://example.com/packages/" >> /etc/yum.repos.d/Repo.repoxyz
RUN echo "enabled         = 1" >> /etc/yum.repos.d/Repo.repoxyz
RUN echo "gpgcheck        = 0" >> /etc/yum.repos.d/Repo.repoxyz

これは、RUNコマンドごとに新しいレイヤーを作成するため、最適なソリューションではない可能性があります。それでも、すべてのレイヤーは、行った変更と同じ大きさになります。この場合は、バイトのオーダーになります(最初のRUNレイヤーは7バイトである必要があります)。

このソリューションの利点は、すべてのシェルで機能することです。


2
おそらく、より良いでこれらのコマンドをCONCATするため&&、より良いキャッシュのために減少し、ロギングと高速Dockerfileビルド時間を
JohannesB
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.