วิธีการใช้ sudo ภายในตู้เทียบท่า?


259

ปกติภาชนะนักเทียบท่าจะทำงานโดยใช้ผู้ใช้ราก ฉันต้องการใช้ผู้ใช้อื่นซึ่งไม่มีปัญหาในการใช้คำสั่ง USER ของนักเทียบท่า แต่ผู้ใช้รายนี้ควรใช้sudoภายในคอนเทนเนอร์ได้ คำสั่งนี้หายไป

นี่คือ Dockerfile ง่าย ๆ สำหรับจุดประสงค์นี้:

FROM ubuntu:12.04

RUN useradd docker && echo "docker:docker" | chpasswd
RUN mkdir -p /home/docker && chown -R docker:docker /home/docker

USER docker
CMD /bin/bash

ใช้ภาชนะนี้ฉันเข้าสู่ระบบด้วยผู้ใช้ 'นักเทียบท่า' เมื่อฉันพยายามใช้ sudo คำสั่งไม่พบ ดังนั้นฉันจึงพยายามติดตั้งแพ็กเกจsudoใน Dockerfile ของฉันโดยใช้

RUN apt-get install sudo

ส่งผลให้ไม่สามารถระบุตำแหน่งแพ็กเกจ sudo ได้


เพียงแค่ให้กลุ่ม sudo กับผู้ใช้ askubuntu.com/questions/7477/…
Regan

คำตอบ:


242

เพิ่งได้รับมัน รีแกนชี้ให้เห็นว่าฉันต้องเพิ่มผู้ใช้ไปยังกลุ่ม sudoers แต่เหตุผลหลักคือฉันลืมที่จะอัพเดทแคชที่เก็บดังนั้น apt-get หาแพ็คเกจ sudo ไม่ได้ มันใช้งานได้แล้ว นี่คือรหัสที่สมบูรณ์:

FROM ubuntu:12.04

RUN apt-get update && \
      apt-get -y install sudo

RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo

USER docker
CMD /bin/bash

8
ไม่ทำงานใน centos adduserคำสั่งถ่มน้ำลายออกมาใช้ความช่วยเหลือuseradd
Emad

สำหรับ CentOS คุณสามารถเพิ่มผู้ใช้และกลุ่มจากนั้นสร้างไฟล์ shard ภายใต้/etc/sudoers.d/และตั้งค่าการอนุญาตเป็น440บนไฟล์นั้น จากนั้นผู้ใช้จะสามารถเข้าถึง sudo ได้ภายใต้ CentOS, 6 ขึ้นไป 5 คุณจะต้องเพิ่ม#includedir /etc/sudoers.dคำสั่งใน/etc/sudoers
FilBot3

ไม่ได้ผลสำหรับฉัน ฉันมีข้อผิดพลาดเหล่านั้น: E: ไม่สามารถเปิดไฟล์ล็อค / var / lib / apt / list / lock - เปิด (13: ปฏิเสธสิทธิ์) E: ไม่สามารถล็อคไดเรกทอรี / var / lib / apt / list /
Marosinho

1
ดูเหมือนว่านี่จะใช้งานไม่ได้กับ Ubuntu 18.04 ภาพนักเทียบท่า
viggy

100

เมื่อทั้ง sudo และ apt-get ไม่มีอยู่ใน container คุณสามารถข้ามไปยัง container ที่รันด้วยผู้ใช้ root โดยใช้คำสั่ง

docker exec -u root -t -i container_id /bin/bash

นี่เป็นทางออกที่ดีกว่าสำหรับสิ่งที่ OP ต้องการเพื่อให้บรรลุแม้ว่าคำตอบที่ยอมรับจะให้โซลูชันที่ร้องขอ อย่างน้อยที่สุดมันเป็นคำตอบที่ฉันต้องการ!
spikyjt

79

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

นี่คือรุ่น TL; DR:

RUN apt-get update \
 && apt-get install -y sudo

RUN adduser --disabled-password --gecos '' docker
RUN adduser docker sudo
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

USER docker

# this is where I was running into problems with the other approaches
RUN sudo apt-get update 

ฉันใช้FROM node:9.3สิ่งนี้ แต่ฉันสงสัยว่าฐานภาชนะอื่นที่คล้ายกันจะทำงานได้ดี


ubuntu:bionic-20180724.1ฉันใช้ ฉันใช้วิธีการนี้ แต่หลังจากข้างต้นไม่อนุญาตให้ฉันติดตั้งแพ็กเกจอื่น ฉันท้ายบรรทัดเดียวกับข้างต้นเพื่อติดตั้งแพคเกจกับ:Dockerfile RUN apt-get install -y treeอย่างไรก็ตามข้อผิดพลาดนี้ทำให้ฉัน:Step xxxx/xxxx : RUN apt-get install -y tree ---> Running in j5e6gsvwfafa Reading package lists... E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied) E: Unable to lock directory /var/lib/apt/lists/
edesz

1
@WR RUN sudo apt-get install -y treeฉันคิดว่าคุณต้องเปลี่ยนสายที่จะอ่าน หลังจากตั้งค่าเป็นUSERอย่างอื่นrootคุณจะต้องใช้sudoคำสั่งใด ๆ ที่ต้องการrootสิทธิ์พิเศษ
M. Scott Ford

อ้าขอบคุณ! คิดถึงว่า ฉันไม่คิดว่าsudoได้รับอนุญาตใน Dockerfile
edesz

สมบูรณ์แบบสิ่งที่ฉันต้องการ
Arin Ekandem

25

สำหรับผู้ที่มีปัญหากับคอนเทนเนอร์ที่ใช้งานอยู่แล้วและพวกเขาไม่ต้องการสร้างใหม่คำสั่งต่อไปนี้จะเชื่อมต่อกับคอนเทนเนอร์ที่กำลังทำงานด้วยสิทธิ์พิเศษของรูท:

docker exec -ti -u root container_name bash

นอกจากนี้คุณยังสามารถเชื่อมต่อโดยใช้ ID แทนชื่อโดยค้นหาด้วย:

docker ps -l

หากต้องการบันทึกการเปลี่ยนแปลงของคุณเพื่อให้การเปลี่ยนแปลงเหล่านั้นยังคงอยู่ที่นั่นเมื่อคุณเปิดใช้งานคอนเทนเนอร์ครั้งต่อไป (หรือคลัสเตอร์ที่ประกอบด้วยนักเทียบท่า):

docker commit container_id image_name

ในการเริ่มต้นคอนเทนเนอร์ที่ไม่ได้ทำงานและเชื่อมต่อในฐานะรูท:

docker run -ti -u root --entrypoint=/bin/bash image_id_or_name -s

หากต้องการคัดลอกจากคอนเทนเนอร์ที่ทำงานอยู่:

docker cp <containerId>:/file/path/within/container /host/path/target

วิธีส่งออกสำเนาภาพ:

docker save container | gzip > /dir/file.tar.gz

ซึ่งคุณสามารถกู้คืนการติดตั้ง Docker อื่นโดยใช้:

gzcat /dir/file.tar.gz | docker load

มันเร็วกว่ามาก แต่ใช้พื้นที่มากขึ้นในการไม่บีบอัดโดยใช้:

docker save container | dir/file.tar

และ:

cat dir/file.tar | docker load

17

ถ้าคุณต้องการที่จะเชื่อมต่อกับภาชนะและติดตั้งบางสิ่งบางอย่าง
โดยใช้ apt-get
first ดังคำตอบข้างต้นจากพี่ชายของเรา "TomášZáluský"

docker exec -u root -t -i container_id /bin/bash

จากนั้นลอง

RUN apt-get update หรือ apt-get 'ทุกสิ่งที่คุณต้องการ'

มันทำงานร่วมกับฉันหวังว่าจะเป็นประโยชน์สำหรับทุกคน


5

หากไม่สามารถเข้าถึงSUDOหรือapt-getได้ภายในคอนเทนเนอร์คุณสามารถใช้ตัวเลือกด้านล่างในการเรียกใช้คอนเทนเนอร์

docker exec -u root -it f83b5c5bf413 ash

" f83b5c5bf413" คือ ID คอนเทนเนอร์ของฉันและนี่คือตัวอย่างการทำงานจากเทอร์มินัลของฉัน:

ป้อนคำอธิบายรูปภาพที่นี่


3

นี่คือวิธีที่ฉันตั้งค่าผู้ใช้ที่ไม่ใช่รูทด้วยอิมเมจพื้นฐานของubuntu:18.04:

RUN \
    groupadd -g 999 foo && useradd -u 999 -g foo -G sudo -m -s /bin/bash foo && \
    sed -i /etc/sudoers -re 's/^%sudo.*/%sudo ALL=(ALL:ALL) NOPASSWD: ALL/g' && \
    sed -i /etc/sudoers -re 's/^root.*/root ALL=(ALL:ALL) NOPASSWD: ALL/g' && \
    sed -i /etc/sudoers -re 's/^#includedir.*/## **Removed the include directive** ##"/g' && \
    echo "foo ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \
    echo "Customized the sudoers file for passwordless access to the foo user!" && \
    echo "foo user:";  su - foo -c id

เกิดอะไรขึ้นกับโค้ดด้านบน:

  • ผู้ใช้และกลุ่มfooถูกสร้างขึ้น
  • ผู้ใช้fooจะถูกเพิ่มในทั้งกลุ่มfooและsudo
  • uidและมีการตั้งค่าของgid999
  • /home/fooไดเรกทอรีบ้านจะถูกกำหนดให้
  • /bin/bashเปลือกมีการตั้งค่า
  • sedคำสั่งไม่อัปเดตแบบอินไลน์ไปยัง/etc/sudoersไฟล์ที่จะอนุญาตfooและrootผู้ใช้ passwordless เข้าถึงsudoกลุ่ม
  • sedคำสั่งปิดการใช้งาน#includedirคำสั่งที่จะช่วยให้ทุกแฟ้มในไดเรกทอรีย่อยเพื่อแทนที่การปรับปรุงแบบอินไลน์เหล่านี้

2

หากคุณมีคอนเทนเนอร์ที่รันในฐานะรูทที่รันสคริปต์ (ซึ่งคุณไม่สามารถเปลี่ยนได้) ที่ต้องการเข้าถึงsudoคำสั่งคุณสามารถสร้างsudoสคริปต์ใหม่ใน$PATHที่เรียกคำสั่งส่งผ่านของคุณได้

เช่นใน Dockerfile ของคุณ:

RUN if type sudo 2>/dev/null; then \ 
     echo "The sudo command already exists... Skipping."; \
    else \
     echo -e "#!/bin/sh\n\${@}" > /usr/sbin/sudo; \
     chmod +x /usr/sbin/sudo; \
    fi

1
ทั้งนี้ขึ้นอยู่กับภาพนักเทียบท่าที่คุณกำลังใช้ (ในกรณีของฉัน Ubuntu: 18.04) คุณอาจต้องลบจาก-e echoมิฉะนั้นจะปรากฏในไฟล์ของตัวเอง
stiller_leser

ความคิดที่เรียบร้อย แต่นี้จะไม่ทำงานหากคำสั่งเดิมโดยใช้ตัวเลือก sudo sudo -E lsเช่น -E lsมันจะพยายามที่จะดำเนินการ
wisbucky

2

สิ่งนี้อาจใช้ไม่ได้กับทุกภาพ แต่บางภาพมีผู้ใช้รูทอยู่แล้วเช่นในอิมเมจ jupyterhub / singleuser ด้วยภาพนั้นเป็นเพียง:

USER root
RUN sudo apt-get update

1

ใช้นามแฝง

alias sudo=''

เรียบง่าย แต่มีประสิทธิภาพ อย่าลืมผนวกเข้ากับ~ / .bash_aliasesเพื่อให้ทำงานได้หลังจากที่คุณเปิดเชลล์ใหม่

nano ~/.bash_aliases
alias sudo=''
#(Ctrl+X)

เนื่องจากผู้ใช้เป็นรูทเริ่มต้นใน Docker การ 'ละเว้น' คำสั่งsudoจึงเป็นวิธีที่ง่ายที่สุด


0

ต่างจากคำตอบที่ยอมรับฉันใช้usermodแทน

สมมติว่าลงชื่อเข้าใช้แล้วในฐานะ root in docker และ "fruit" เป็นชื่อผู้ใช้ที่ไม่ใช่รูทใหม่ที่ฉันต้องการเพิ่มเพียงเรียกใช้คำสั่งนี้:

apt update && apt install sudo
adduser fruit
usermod -aG sudo fruit

อย่าลืมบันทึกภาพหลังการอัพเดต ใช้docker psเพื่อรับ <CONTAINER ID> ของนักเรียกใช้งานปัจจุบันและ <IMAGE> จากนั้นเรียกใช้docker commit -m "added sudo user" <CONTAINER ID> <IMAGE>เพื่อบันทึกภาพนักเทียบท่า

จากนั้นทดสอบด้วย:

su fruit
sudo whoami

หรือทดสอบโดยการล็อกอินโดยตรง (ตรวจสอบให้แน่ใจว่าได้บันทึกภาพไว้ก่อน) ในฐานะผู้ใช้ที่ไม่ใช่รูทเมื่อเปิดตัวนักเทียบท่า:

docker run -it --user fruit <IMAGE>
sudo whoami

คุณสามารถใช้sudo -kเพื่อรีเซ็ตการประทับเวลาถามรหัสผ่าน:

sudo whoami # No password prompt
sudo -k # Invalidates the user's cached credentials
sudo whoami # This will prompt for password
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.