โดยทั่วไปปัญหาเกี่ยวกับสิทธิ์ของการเมานต์ไดรฟ์ข้อมูลโฮสต์เป็นเพราะ uid / gid ภายในคอนเทนเนอร์ไม่มีการเข้าถึงไฟล์ตามการอนุญาต uid / gid ของไฟล์บนโฮสต์ อย่างไรก็ตามกรณีเฉพาะนี้แตกต่างกัน
จุดที่ท้ายสุดของสตริงการอนุญาตdrwxr-xr-x.
แสดงว่า SELinux ได้รับการกำหนดค่า เมื่อใช้โฮสต์เมาท์กับ SELinux คุณจะต้องผ่านตัวเลือกพิเศษไปยังจุดสิ้นสุดของคำจำกัดความของโวลุ่ม:
z
ตัวเลือกที่แสดงให้เห็นว่าผูกติดเนื้อหาที่ใช้ร่วมกันระหว่างหลายคอนเทนเนอร์
Z
ตัวเลือกที่แสดงให้เห็นว่าเนื้อหาที่ผูกติดเป็นส่วนตัวและยกเลิกการแชร์
คำสั่งเพิ่มความดังของคุณจะมีลักษณะดังนี้:
sudo docker run -i -v /data1/Downloads:/Downloads:z ubuntu bash
ดูข้อมูลเพิ่มเติมเกี่ยวกับการติดตั้งโฮสต์ด้วย SELinux ได้ที่: https://docs.docker.com/storage/#configure-the-selinux-label
สำหรับคนอื่น ๆ ที่เห็นปัญหานี้กับคอนเทนเนอร์ที่ทำงานเป็นผู้ใช้อื่นคุณต้องแน่ใจว่า uid / gid ของผู้ใช้ที่อยู่ในคอนเทนเนอร์นั้นได้รับอนุญาตให้ใช้ไฟล์บนโฮสต์ บนเซิร์ฟเวอร์ที่ใช้งานจริงมักจะทำโดยการควบคุม uid / gid ในกระบวนการสร้างอิมเมจเพื่อจับคู่ uid / gid บนโฮสต์ที่มีการเข้าถึงไฟล์ (หรือดีกว่าไม่ใช้โฮสต์เมานต์ในการผลิต)
ไดรฟ์ข้อมูลที่มีชื่อมักจะต้องการโฮสต์เมาต์เนื่องจากจะเริ่มต้นไดเรกทอรีไดรฟ์ข้อมูลจากไดเรกทอรีรูปภาพรวมถึงความเป็นเจ้าของแฟ้มและสิทธิ์ สิ่งนี้จะเกิดขึ้นเมื่อปริมาตรว่างเปล่าและสร้างภาชนะด้วยปริมาตรที่ตั้งชื่อไว้
ขณะนี้ผู้ใช้ MacOS มีOSXFSซึ่งจัดการ uid / gid โดยอัตโนมัติระหว่างโฮสต์ Mac และคอนเทนเนอร์ ที่เดียวที่ไม่ช่วยคือไฟล์จากภายใน VM ที่ฝังไว้ซึ่งติดตั้งในคอนเทนเนอร์เช่น /var/lib/docker.sock
สำหรับสภาพแวดล้อมการพัฒนาที่โฮสต์ uid / gid อาจเปลี่ยนแปลงต่อผู้พัฒนาโซลูชันที่ฉันต้องการคือเริ่มต้นคอนเทนเนอร์ด้วยจุดเข้าใช้งานเป็น root ให้แก้ไข uid / gid ของผู้ใช้ภายในคอนเทนเนอร์เพื่อจับคู่ปริมาณโฮสต์ uid / gid และ จากนั้นใช้gosu
เพื่อดร็อปจากรูทไปยังผู้ใช้คอนเทนเนอร์เพื่อรันแอ็พพลิเคชันภายในคอนเทนเนอร์ สคริปต์ที่สำคัญสำหรับสิ่งนี้อยู่fix-perms
ในสคริปต์ภาพพื้นฐานของฉันซึ่งสามารถดูได้ที่: https://github.com/sudo-bmitch/docker-base
บิตที่สำคัญจากfix-perms
สคริปต์คือ:
# update the uid
if [ -n "$opt_u" ]; then
OLD_UID=$(getent passwd "${opt_u}" | cut -f3 -d:)
NEW_UID=$(stat -c "%u" "$1")
if [ "$OLD_UID" != "$NEW_UID" ]; then
echo "Changing UID of $opt_u from $OLD_UID to $NEW_UID"
usermod -u "$NEW_UID" -o "$opt_u"
if [ -n "$opt_r" ]; then
find / -xdev -user "$OLD_UID" -exec chown -h "$opt_u" {} \;
fi
fi
fi
ที่ได้รับ uid ของผู้ใช้ภายในภาชนะและ uid ของไฟล์และหากพวกเขาไม่ตรงกันโทรusermod
เพื่อปรับ uid ในที่สุดมันจะค้นหาแบบเรียกซ้ำเพื่อแก้ไขไฟล์ใด ๆ ที่ไม่ได้เปลี่ยน uid ฉันชอบสิ่งนี้ดีกว่าการใช้คอนเทนเนอร์ที่มีการ-u $(id -u):$(id -g)
ตั้งค่าสถานะเนื่องจากรหัสจุดเข้าใช้งานด้านบนไม่ต้องการให้นักพัฒนาแต่ละคนเรียกใช้สคริปต์เพื่อเริ่มการทำงานของคอนเทนเนอร์และไฟล์ใด ๆ ที่อยู่นอกไดรฟ์ข้อมูลที่เป็นเจ้าของโดยผู้ใช้
คุณยังสามารถให้นักเทียบท่าเริ่มต้นไดเรกทอรีโฮสต์จากอิมเมจโดยใช้โวลุ่มที่ตั้งชื่อซึ่งดำเนินการเชื่อมต่อแบบผูก ไดเรกทอรีนี้จะต้องมีอยู่ล่วงหน้าและคุณต้องระบุเส้นทางที่แน่นอนไปยังไดเรกทอรีโฮสต์ซึ่งแตกต่างจากปริมาณโฮสต์ในไฟล์เขียนซึ่งสามารถเป็นเส้นทางญาติ ไดเรกทอรีจะต้องว่างเปล่าเพื่อให้นักเทียบท่าเริ่มต้นได้ สามอ็อพชันที่แตกต่างกันสำหรับการกำหนดวอลุ่มที่กำหนดชื่อให้กับ bind mount มีลักษณะดังนี้:
# create the volume in advance
$ docker volume create --driver local \
--opt type=none \
--opt device=/home/user/test \
--opt o=bind \
test_vol
# create on the fly with --mount
$ docker run -it --rm \
--mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=none,volume-opt=o=bind,volume-opt=device=/home/user/test \
foo
# inside a docker-compose file
...
volumes:
bind-test:
driver: local
driver_opts:
type: none
o: bind
device: /home/user/test
...
สุดท้ายถ้าคุณลองใช้เนมสเปซผู้ใช้คุณจะพบว่าโฮสต์ปริมาณมากมีปัญหาเรื่องสิทธิ์เนื่องจากคอนเทนเนอร์ของ uid / gid ถูกเปลี่ยน ในสถานการณ์สมมตินั้นอาจเป็นเรื่องที่ง่ายที่สุดในการหลีกเลี่ยงปริมาณโฮสต์และใช้ชื่อโวลุ่มเท่านั้น