วิธีการตั้งค่านามแฝง bash สำหรับคอนเทนเนอร์นักเทียบท่าใน Dockerfile


87

ฉันยังใหม่กับนักเทียบท่า ฉันพบว่าเราสามารถตั้งค่าตัวแปรสภาพแวดล้อมโดยใช้คำสั่ง ENV ใน Dockerfile แต่หนึ่งจะตั้งค่านามแฝง bash สำหรับคำสั่งแบบยาวใน Dockerfile ได้อย่างไร?


นามแฝงได้รับการพิจารณาว่าเลิกใช้งานเป็นเวลานานมากแล้ว ใช้ฟังก์ชัน ไม่มีความจำเป็นต้องใด ๆที่เคยใช้นามแฝง วิธีการเหล่านี้ในช่วงปลายยุค 80 ยังคงมีอยู่เป็นเวลานานได้อย่างไร?
William Pursell

19
เพราะสะดวกและเรียบง่ายแน่นอน
Arthur

13
@WilliamPursell บางทีคุณควรอธิบายวิธีใช้ฟังก์ชันแทน
Eric Dela Cruz

2
นามแฝงเป็นเรื่องง่ายสะดวกเปราะบางและเกิดข้อผิดพลาดได้ง่าย ฟังก์ชั่นใช้งานง่ายเหมือนกัน แต่ให้ความยืดหยุ่นและความทนทานมากกว่า มีแหล่งข้อมูลมากมายเกี่ยวกับวิธีการใช้งาน
William Pursell

คำตอบ:


144

โดยทั่วไปเหมือนที่คุณมักจะทำโดยการเพิ่มไปยังผู้ใช้.bashrc:

FROM foo
RUN echo 'alias hi="echo hello"' >> ~/.bashrc

ตามปกติสิ่งนี้จะใช้ได้กับเชลล์แบบโต้ตอบเท่านั้น:

docker build -t test .
docker run -it --rm --entrypoint /bin/bash test hi
/bin/bash: hi: No such file or directory
docker run -it --rm test bash
$ hi
hello

สำหรับเชลล์ที่ไม่โต้ตอบคุณควรสร้างสคริปต์ขนาดเล็กและวางไว้ในเส้นทางของคุณเช่น:

RUN echo -e '#!/bin/bash\necho hello' > /usr/bin/hi && \
    chmod +x /usr/bin/hi

หากนามแฝงของคุณใช้พารามิเตอร์ (เช่น. hi Jim-> hello Jim) ให้เพิ่ม"$@":

RUN echo -e '#!/bin/bash\necho hello "$@"' > /usr/bin/hi && \
    chmod +x /usr/bin/hi

ขอบคุณสำหรับสิ่งนี้คุณสามารถให้ตัวอย่างของเชลล์แบบไม่โต้ตอบได้หรือไม่? ฉันกำลังมองหา ENTRYPOINT และ CMD เพื่อแก้ปัญหานี้
c24b

5
นามแฝง Bash ใช้งานได้ในเชลล์แบบโต้ตอบเท่านั้น เพียงสร้างเชลล์สคริปต์ขนาดเล็กและวางไว้ในเส้นทางของคุณเอฟเฟกต์เดียวกับนามแฝง อัปเดตคำตอบด้วยตัวอย่างง่ายๆ
Erik Dannenberg

1
หมายเหตุ: จากstackoverflow.com/a/8467449คุณควรใช้printfแทนechoเพื่อให้แน่ใจว่ามีพฤติกรรมที่สอดคล้องกันมากขึ้น ดังนั้น printf '#! / bin / bash \ necho hello'> / usr / bin / hi chmod + x / usr / bin / hi
barraq

2
ชอบไอเดียเชลล์สคริปต์ กำลังมองหาการเพิ่มนามแฝง แต่สิ่งนี้ดีกว่ามาก ขอบคุณ.
Blizz

3
คุณควรใช้ "$ @" แทน $ * สำหรับอาร์กิวเมนต์หลายตัวที่หลบหนี ดูunix.stackexchange.com/questions/248464/…
gnou

14

ในการสร้างนามแฝงของคำสั่งที่มีอยู่อาจใช้ln -s:

ln -s $(which <existing_command>) /usr/bin/<my_command>


7
ฉันจะไม่เรียกสิ่งนี้ว่านามแฝง .. มันคือ soft link / symlink ความสะดวกสบายของนามแฝงคือคุณสามารถส่งผ่านพารามิเตอร์ไปยังคำสั่งalias ll='ls -lh'ที่เป็นไปไม่ได้ด้วย symlink
qwertz

3

หากคุณต้องการใช้นามแฝงใน Dockerfile แต่ไม่ใช่ภายในคอนเทนเนอร์วิธีที่สั้นที่สุดคือENVการประกาศ:

ENV update='apt-get update -qq'
ENV install='apt-get install -qq'

RUN $update && $install apt-utils \
    curl \
    gnupg \
    python3.6

และสำหรับใช้ในคอนเทนเนอร์ตามที่อธิบายไว้แล้ว:

 RUN printf '#!/bin/bash \n $(which apt-get) install -qq $@' > /usr/bin/install
 RUN chmod +x /usr/bin/install

เวลาส่วนใหญ่ฉันใช้นามแฝงในการสร้างพื้นที่และไม่ได้เข้าไปในตู้คอนเทนเนอร์ดังนั้นตัวอย่างแรกคือเร็วกว่าชัดเจนและง่ายกว่าสำหรับการใช้งานทุกวัน


2

ฉันเพิ่งเพิ่มสิ่งนี้ใน app.dockerfile ของฉัน

# setup aliases
ADD ./bashrc_alias.sh /usr/sbin/bashrc_alias.sh
ADD ./initbash_profile.sh /usr/sbin/initbash_profile
RUN chmod +x /usr/sbin/initbash_profile
RUN /bin/bash -C "/usr/sbin/initbash_profile"

และภายในinitbash_profile.shซึ่งต่อท้ายนามแฝงที่กำหนดเองของฉันและไม่จำเป็นต้องซอร์สไฟล์. bashrc

# add the bash aliases
cat /usr/sbin/bashrc_alias.sh >> ~/.bashrc

ทำงานรักษา!

อีกทางเลือกหนึ่งคือใช้ "คำสั่ง docker exec -it" จากภายนอกคอนเทนเนอร์และใช้. bashrc หรือ. bash_profile ของคุณเอง (สิ่งที่คุณต้องการ)

เช่น. docker exec -it docker_app_1 bash


1

คุณสามารถใช้จุดเข้าได้ แต่จะใช้ไม่ได้กับนามแฝงใน Dockerfile ของคุณ:

ADD dev/entrypoint.sh /opt/entrypoint.sh
ENTRYPOINT ["/opt/entrypoint.sh"]

ของคุณ entrypoint.sh

#!/bin/bash
set -e

function dev_run()
{

}

export -f dev_run

exec "$@"

(คัดลอก / วางด่วนขออภัย)


โปรดทราบว่าอิมเมจ Docker บางรูปสามารถลบล้างจุดเริ่มต้นได้แล้ว (เช่นภาพฐานฟิวชัน)
Thomas Decaux

1

ฉันคิดว่าวิธีที่ง่ายที่สุดคือการเมานต์ไฟล์ลงในคอนเทนเนอร์ของคุณที่มีนามแฝงของคุณจากนั้นระบุตำแหน่งที่ bash ควรค้นหา:

docker run \
    -it \
    --rm \
    -v ~/.bash_aliases:/tmp/.bash_aliases \
    [image] \
    /bin/bash --init-file /tmp/.bash_aliases

ตัวอย่างการใช้งาน:

user@cobalt:~$ echo 'alias what="echo it works"' > my_aliases
user@cobalt:~$ docker run -it --rm -v ~/my_aliases:/tmp/my_aliases ubuntu:18.04 /bin/bash --init-file /tmp/my_aliases
root@565e4a1bdcc0:/# alias
alias what='echo it works'
root@565e4a1bdcc0:/# what
it works

0

ใช้วิธีแก้ปัญหาข้างต้นบางส่วน แต่ไม่รู้จักนามแฝง

ฉันกำลังพยายามตั้งนามแฝงและใช้ทั้งสองอย่างภายในขั้นตอน Dockerfile ในภายหลังและในคอนเทนเนอร์ขณะรันไทม์

RUN echo "alias model-downloader='python3 ${MODEL_DL_PATH}/downloader.py'" >> ~/.bash_aliases && \
    echo "alias model-converter='python3 ${MODEL_DL_PATH}/converter.py'" >> ~/.bash_aliases && \
    source ~/.bash_aliases

# Download the model
RUN model-downloader --name $MODEL_NAME -o $MODEL_DIR --precisions $MODEL_PRECISION;

วิธีแก้ปัญหาสำหรับฉันคือใช้ตัวแปร ENV ที่เก็บเส้นทางโฟลเดอร์แล้วเพิ่มไฟล์ปฏิบัติการที่แน่นอน ฉันสามารถใช้ ARG ได้เช่นกัน แต่สำหรับสถานการณ์อื่น ๆ ของฉันฉันต้องการนามแฝงทั้งในขั้นตอนการสร้างและในรันไทม์ในภายหลัง

ใช้ตัวแปร ENV ร่วมกับสคริปต์ bash ที่รันเมื่อการอ้างอิงได้ ponged และตั้งค่า bash source ตั้งค่าตัวแปร env เพิ่มเติมและอนุญาตให้มีคำสั่งเพิ่มเติมเพื่อไพพ์ผ่าน


ทุกRUNคำสั่งจะถูกดำเนินการในเชลล์ใหม่ดังนั้นในตัวอย่างของคุณไฟล์นามแฝงจะไม่ถูกโหลดอีกต่อไปเมื่อคุณพยายามใช้นามแฝง
Erik Dannenberg

100% @ErikDannenberg ขอบคุณสำหรับความคิดเห็นและสำหรับเตือนฉันว่าฉันต้องโพสต์การอัปเดตนี้ - ฉันได้ค้นพบวิธีแก้ปัญหาและเป็นอย่างที่คุณแนะนำ
alanionita

0

นี่คือฟังก์ชัน Bash ที่จะมีนามแฝงของคุณในทุกคอนเทนเนอร์ที่คุณใช้แบบโต้ตอบ

ducker_it() {
    docker cp ~/bin/alias.sh "$1":/tmp
    docker exec -it "$1" /bin/bash -c "[[ ! -f /tmp/alias.sh.done ]] \
        && [[ -w /root/.bashrc ]] \
        && cat /tmp/alias.sh >> /root/.bashrc \
        && touch /tmp/alias.sh.done"
    docker exec -it "$1" /bin/bash
}

ขั้นตอนที่จำเป็นก่อน:

grep ^alias ~/.zshrc > ~/bin/alias.sh

-1
  1. แก้ไขไฟล์นี้ ~ / .bash_aliases vi ~/.bash_aliases
  2. แหล่งที่มาของไฟล์นี้ ~ / .bash_aliases source ~/.bash_aliases
  3. เสร็จแล้ว

ทุกครั้งที่คุณหมุนคอนเทนเนอร์นักเทียบท่า แต่ชื่อแทนจะไม่อยู่ในครั้งต่อไป หากคุณไม่คิดจะเพิ่มใหม่ทุกครั้งที่โซลูชันนี้ใช้ได้
mikoop

นี่ไม่ใช่คำตอบ แต่เป็นการเยาะเย้ยคนที่ถามคำถาม
bhuvin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.