Làm thế nào để viết lệnh có nhiều dòng trong Dockerfile trong khi vẫn giữ nguyên các dòng mới?


84

Tôi muốn viết lệnh RUN sau trong Dockerfile. Tuy nhiên, docker không bảo tồn các dòng mới.

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

Tôi biết rằng \ở cuối mỗi dòng thoát ra khỏi dòng mới. Nhưng, có cách nào để tôi có thể viết nhiều dòng mà vẫn giữ nguyên dòng mới không?


Bạn có đang sử dụng nền tảng không phải * nix không? Bởi vì điều này hoạt động tốt đối với tôi trên Linux.
người dùng

@user, tôi đang sử dụng Linux.
Venkata Jaswanth

Câu trả lời:


114

Bạn có thể sử dụng cái được gọi là "ANSI-C trích dẫn" với $'...'. Ban đầu nó là một tính năng ksh93 nhưng bây giờ nó có sẵn trong bash, zsh, mksh, FreeBSD shtro của busybox (nhưng chỉ khi nó được biên dịch bằng ENABLE_ASH_BASH_COMPAT).

RUN sử dụng /bin/shlàm trình bao theo mặc định, trước tiên bạn bắt buộc phải chuyển sang một thứ gì đó như bash bằng cách sử dụng lệnh SHELL.

Bắt đầu lệnh của bạn bằng $', kết thúc bằng 'và sử dụng \n\cho các dòng mới, như sau:

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
Nó là cú pháp bash. Xem câu hỏi này để biết thêm thông tin: stackoverflow.com/a/11966402/1395437
Daniel Zolnai

13
Xin vui lòng, giải thích những gì bạn đang làm, không chỉ cần thả một giải pháp đục
Édouard Lopez

25
Một lời cảnh báo: $' ... \n\ kỹ thuật phụ thuộc vào shell mà docker RUNsử dụng bash. Trên một số hệ thống (chẳng hạn như Ubuntu), shell mà RUN sử dụng /bin/shthường là một liên kết dashKHÔNG phải bashvà không hiểu $'cú pháp.
Anon

2
như @Anon đã nói, điều này sẽ KHÔNG HOẠT ĐỘNG nếu chạy ở bất kỳ nơi nào khác ngoài bash. (cũng không hoạt động Oh My Zsh)
Rafa

1
@Anon tốt, nó hoạt động trong Alpine linux (hiện tại tôi đang sử dụng 3.10.2) sử dụng shell.
suchoss

52

Tôi đã sử dụng printf. Viết tất cả văn bản trong một dòng bằng "\ n".

Đang thực hiện:

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

phụ trang:

example
text
here

trong example.txt


19

Bạn có thể dùng:

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

Bằng cách này, bạn sẽ có một cách nhanh chóng để kiểm tra nội dung tệp. Bạn chỉ cần lưu ý rằng bạn cần kết thúc mọi dòng \và chèn vào \nkhi cần thiết.


1
Điều này cần echo -ephải giải thích\n
Patrick Bergner

5

Tôi đã kết thúc bằng cách sử dụng kết hợp các ví dụ được liệt kê ở trên vì dòng mới \nkhông hoạt động với echo.

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

Nó tạo ra những điều sau đây, như mong đợi:

example
text
here

Câu trả lời của bạn khác với câu trả lời của CTodea như thế nào?
The Godfather

@TheGodfather Đó là một ví dụ đa dòng. Trả lời tốt hơn câu hỏi ban đầu quá.
Sergey

2

Có thể nó sẽ giúp bạn ( 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

Bạn có thể thực thi RUN nhiều lần để hoàn thành tệp của mình:

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

Đây có thể không phải là giải pháp tối ưu vì nó tạo ra một lớp mới cho mọi lệnh RUN. Tuy nhiên, mọi lớp sẽ lớn như thay đổi mà bạn thực hiện, trong trường hợp này là theo thứ tự của Byte (lớp RUN đầu tiên phải là 7 byte).

Lợi ích của giải pháp này là nó sẽ hoạt động với tất cả các shell.


1
Có lẽ tốt hơn nên kết hợp các lệnh này với &&mục đích lưu vào bộ nhớ đệm tốt hơn, giảm ghi nhật ký và Dockerfilethời gian xây dựng nhanh hơn
JohannesB
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.