Як писати команди з кількома рядками в Dockerfile, зберігаючи нові рядки?


84

Я хочу написати наступну команду RUN у файлі Docker. Але 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.
Венката Ясвант

Відповіді:


114

Ви можете використовувати те, що називається "цитування ANSI-C" $'...'. Спочатку це була функція ksh93, але тепер вона доступна в bash, zsh, mksh, FreeBSD sh та у золі busybox (але лише тоді, коли вона компілюється за допомогою ENABLE_ASH_BASH_COMPAT).

Оскільки RUN /bin/shза замовчуванням використовує як оболонку, вам потрібно спочатку перейти на щось на зразок bash, скориставшись інструкцією SHELL.

Почніть свою команду з $', закінчіть її 'та використовуйте \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

13
Поясніть, будь ласка, що ви робите, не просто кидайте непрозоре рішення
Едуар Лопес

25
Слово обережності: $' ... \n\ техніка залежить від оболонки, яку RUNвикористовує докер bash. У деяких системах (таких як Ubuntu) оболонка, яку використовує RUN, - /bin/shце часто посилання на dashяке НЕ є bashта не розуміє $'синтаксису.
Анон,

2
як сказав @Anon, це НЕ ПРАЦЮЄ, якщо запускати деінде, окрім bash. (не працює Oh My Zshні в одній з них)
Рафа,

1
@Anon добре це працює в Alpine linux (на даний момент я на 3.10.2), який використовує оболонку.
suchoss

52

Я використовував printf. Написання всього тексту в один рядок за допомогою "\ n".

Виконання:

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

вставки:

example
text
here

у прикладі.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
Патрік Бергнер

5

У підсумку я використав комбінацію наведених вище прикладів, оскільки новий рядок \nне працював echo.

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

Як очікується, він видає наступне:

example
text
here

Чим ваша відповідь відрізняється від відповіді 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-байтовим).

Перевага цього рішення полягає в тому, що воно буде працювати з усіма оболонками.


1
Можливо, краще поєднати ці команди з &&метою кращого кешування, зменшення реєстрації та швидшого Dockerfileзбирання
JohannesB
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.