เพิ่มระดับเสียงใน Docker แต่ไม่รวมโฟลเดอร์ย่อย


210

/hostFolderควรฉันมีภาชนะเทียบท่าและโฟลเดอร์บนโฮสต์ของฉัน ตอนนี้ถ้าฉันต้องการเพิ่มโฟลเดอร์นี้ลงในคอนเทนเนอร์ Docker เป็นโวลุ่มฉันก็สามารถทำได้โดยใช้ADDในDockerfileหรือติดตั้งเป็นโวลุ่ม

จนถึงตอนนี้ดีมาก

ขณะนี้/hostFolderมีโฟลเดอร์ย่อย, /hostFolder/subFolder.

ฉันต้องการเมานต์/hostFolderลงในคอนเทนเนอร์ Docker (ไม่ว่าจะเป็นอ่าน - เขียนหรืออ่านอย่างเดียวไม่สำคัญว่าทำงานได้ทั้งฉัน) แต่ฉันไม่ต้องการรวมไว้/hostFolder/subFolderด้วย ฉันต้องการยกเว้นสิ่งนี้และฉันต้องการให้ Docker container สามารถทำการเปลี่ยนแปลงในโฟลเดอร์ย่อยนี้ได้โดยไม่ต้องมีการเปลี่ยนแปลงในโฮสต์เช่นกัน

เป็นไปได้ไหม ถ้าเป็นเช่นนั้นได้อย่างไร


2
@AbhijitSarkar ที่ไม่ได้เป็นความคิดเห็นที่สร้างสรรค์มาก (หรือในทางใดทางหนึ่งที่เป็นประโยชน์)
kano

1
@Kano มันเป็นความเห็นไม่ใช่คำตอบ
Abhijit Sarkar

คำตอบ:


397

การใช้ docker-compose ฉันสามารถใช้ node_modules แบบโลคัล แต่ไม่ต้องสนใจมันใน container docker โดยใช้ไวยากรณ์ต่อไปนี้ใน docker-compose.yml

volumes:
   - './angularApp:/opt/app'
   - /opt/app/node_modules/

ดังนั้นทุกอย่างที่./angularAppแมปไป/opt/appแล้วฉันจะสร้างวอลลุ่มเมานต์อื่น/opt/app/node_modules/ซึ่งตอนนี้เป็นไดเร็กตอรี่ว่าง - แม้ว่าในเครื่องท้องถิ่นของฉัน./angularApp/node_modulesจะไม่ว่างเปล่า


3
ใช้งานได้ แต่ฉันไม่สามารถลบ dirs เหล่านี้ภายในคอนเทนเนอร์ตัวอย่างเช่น: ฉันต้องการแทนที่/opt/app/node_modules/ด้วยไดเรกทอรีอื่นที่มีชื่อเดียวกัน ข้อผิดพลาดเกิดขึ้น: 'ปริมาณไม่ว่าง'
Stepan Yudin

32
อย่าลืมสแลชท้าย! เช่น. / opt / app / node_modules ไม่ทำงานมันจะถูกเขียนทับโดย. / triangleApp/node_modules
Stingus

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

8
ขอบคุณ! คุณบันทึกวันของฉัน! ในกรณีที่ใช้นักเทียบท่าแบบเรียบง่ายไม่ใช้การประพันธ์มันจะมีลักษณะดังนี้: -v $(pwd):/build/ -v /build/node_modules
Bogdan Mart

3
ผมพบว่าเอกสารdocs.docker.com/storage/volumes/... If you start a container which creates a new volume, as above, and the container has files or directories in the directory to be mounted (such as /app/ above), the directory’s contents are copied into the volume.
ฮิโรชิ

118

หากคุณต้องการให้ไดเรกทอรีย่อยถูกละเว้นโดยนักเทียบท่า แต่เรียบเรียงคุณสามารถทำสิ่งต่อไปนี้ในdocker-compose.yml:

volumes:
  node_modules:
services:
  server:
    volumes:
      - .:/app
      - node_modules:/app/node_modules

สิ่งนี้จะเมานต์ไดเรกทอรีปัจจุบันของคุณเป็นโวลุ่มที่ใช้ร่วมกัน แต่เมานต์ไดรฟ์ข้อมูลที่ต่อเนื่องแบบถาวรแทนที่node_modulesไดเรกทอรีท้องถิ่นของคุณ นี่คล้ายกับคำตอบของ @kernix แต่สิ่งนี้จะช่วยให้node_modulesคงอยู่ระหว่างการdocker-compose upรันซึ่งน่าจะเป็นพฤติกรรมที่ต้องการ


20
โวลุ่มที่มีชื่อเป็นวิธีการที่เหนือกว่า Protip: ตรวจสอบให้แน่ใจว่าคุณไม่ได้ใช้ชื่อวอลุ่มที่ใส่ยัติภังค์ คุณจะใช้ชีวิตส่วนเล็ก ๆ ของคุณในฝันร้ายของการดีบั๊กเพียงเพื่อจะพบว่าคุณถูกหลอกอีกครั้งโดยความแตกต่างที่ไร้สาระ
dustintheweb

3
"โปรดทราบว่านักเทียบท่าที่เขียนลงจะฆ่าโวลุ่มเหล่านี้" สิ่งนี้ไม่เป็นความจริงใน Docker สำหรับ Mac v 17.0.5+ (และอาจเป็นรุ่นที่เก่ากว่า) docker-compose downจะลบภาชนะบรรจุ แต่ปริมาณจะยังคงอยู่จนกว่าคุณจะเรียกใช้บางอย่างเช่นdocker system prune
BrDaHa

3
ในกรณีที่มีคนสนใจที่จะเข้าใจว่าทำไมการใช้node_modules:ปริมาณที่มีชื่อ "ละเว้น" /app/node_modulesในภาชนะนักเทียบท่าอาจพบโพสต์นี้มีประโยชน์นักเทียบท่าจัดการเมาท์หลายประเภทอย่างไร
ira

3
ฉันไม่ทราบว่าฉันกำลังทำสิ่งผิดปกติหรือไม่ แต่ถ้าฉันทำสิ่งนี้เริ่มต้นคอนเทนเนอร์แล้วเรียกใช้การติดตั้ง npm บนเครื่อง HOST จะเปลี่ยน node_modules ภายใน CONTAINER ด้วย ฉันไม่สามารถจินตนาการได้ว่าทำไมทุกคนต้องการทำเช่นนั้น แต่ถึงกระนั้นฉันก็กำลังมองหาการแยกที่สะอาด
Renra

3
@ Renra มีปัญหาเดียวกันที่แน่นอนเครื่องโฮสต์ของฉันจะเขียนอย่างต่อเนื่องผ่าน node_modules แม้ว่าฉันจะมีปริมาณการตั้งชื่อ ... ทำให้เกิดปัญหาความไม่ลงรอยกันทุกประเภท เลิกซ่อมมันและแก้ไขมันด้วยการคัดลอกโฟลเดอร์ src ของฉันแทน repo ทั้งหมด
dancypants

19

หากต้องการยกเว้นไฟล์ให้ใช้ดังต่อไปนี้

volumes:
   - /hostFolder:/folder
   - /dev/null:/folder/fileToBeExcluded

6
โซลูชั่นที่สมบูรณ์แบบสำหรับสิ่งที่ฉันต้องการ (เพื่อไม่จับคู่ node_modules กับโฮสต์เพราะสิ่งที่ symlink แตกบนโฮสต์ Windows) การชี้ไปที่ / dev / null ไม่ได้ผล แต่การสร้างไดเรกทอรีว่างและการแมปไปยังสิ่งนั้นทำงานได้อย่างสมบูรณ์และแก้ไขปัญหาที่ฉันมี - ขอบคุณสำหรับแนวคิดนี้
เลียมแฮมเมตต์

1
นี้ไม่ได้ทำงานในหางสำหรับ Mac Cannot start service xxx: OCI runtime create failed: container_linux.go:348: starting container process caused "process_linux.go:402: container init caused \"rootfs_linux.go:58: mounting \\\"/dev/null\\\" to rootfs \\\"/var/lib/docker/overlay2/d15ed56ad020d408c63a1f6a6365dbb88d5d3b78a4605980d3faa9861102ef21/merged\\\" at [...] unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type18.09.0: การเพิ่มเครื่องหมายสแลชต่อท้ายไม่ได้ช่วยอะไร
Blaise

ฉันสามารถยืนยันได้ว่ามันไม่ทำงานบน Ubuntu 16.04 กับ Docker 18.09.3
เดิร์ค

นั่นไม่ได้ผลสำหรับฉัน สิ่งที่มันทำคือคัดลอก/dev/nullลงในคอนเทนเนอร์เป็นไฟล์อุปกรณ์
Radon Rosborough

1
โปรดทราบว่านี่ใช้งานได้เฉพาะการยกเว้น FILES! / dev / null เป็นไฟล์และควรเป็นเป้าหมายข้อความแสดงข้อผิดพลาดค่อนข้างชัดเจนในเรื่องนี้: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type. นี่ไม่ใช่สิ่งที่ OP ต้องการ แต่มันมีประโยชน์มากสำหรับฉันเนื่องจากฉันต้องการยกเว้นไฟล์เดียว
Avius

13

ก่อนอื่นการใช้ADDคำสั่งใน Dockerfile นั้นแตกต่างจากการใช้วอลลุ่มมาก (ไม่ว่าจะผ่านทาง-vอาร์กิวเมนต์docker runหรือVOLUMEคำสั่งใน Dockerfile) ADDและCOPYคำสั่งเพียงแค่ใช้สำเนาของไฟล์ในเวลาที่docker buildมีการเรียกใช้ ไฟล์เหล่านี้ไม่ได้รับการอัพเดตจนกว่าจะสร้างอิมเมจใหม่ด้วยdocker buildคำสั่ง ในทางตรงกันข้ามการใช้โวลุ่มนั้นสำคัญว่า "ไดเรกทอรีนี้ไม่ควรเก็บไว้ในอิมเมจคอนเทนเนอร์ แต่ควรใช้ไดเรคทอรีบนโฮสต์แทน"; เมื่อใดก็ตามที่ไฟล์ภายในปริมาตรเปลี่ยนไปทั้งโฮสต์และคอนเทนเนอร์จะเห็นไฟล์ทันที

ฉันไม่เชื่อว่าคุณสามารถบรรลุสิ่งที่คุณต้องการโดยใช้โวลุ่มคุณจะต้องคิดใหม่โครงสร้างไดเรกทอรีของคุณถ้าคุณต้องการทำเช่นนี้

อย่างไรก็ตามมันค่อนข้างง่ายในการใช้งานCOPY(ซึ่งควรเป็นที่ต้องการADD) คุณสามารถใช้.dockerignoreไฟล์เพื่อแยกไดเรกทอรีย่อยหรือคุณสามารถCOPYทำไฟล์ทั้งหมดแล้วทำRUN rm blaเพื่อลบไดเรกทอรีย่อย

โปรดจำไว้ว่าไฟล์ใด ๆ ที่คุณเพิ่มในภาพที่มีCOPYหรือADDจะต้องอยู่ภายในเช่นการสร้างบริบทในหรือด้านล่างของไดเรกทอรีที่คุณเรียกใช้docker buildจาก


1
เรียนรู้สิ่งใหม่ทุกวัน :-) COPY และ ADD ทำงานจากบริบทการสร้าง (ไม่ใช่โฮสต์) เป็นไปได้ไหมที่จะใช้วอลลุ่มเพื่อปิดบังโฟลเดอร์ย่อย? OP ต้องการเมาต์ / hostFolder (ฉันคิดว่า) และทำให้ / hostFolder / โฟลเดอร์ย่อยถูกตัดการเชื่อมต่อ หากมี VOLUME สำหรับแต่ละคน แต่ hostFolder เท่านั้นที่ถูก 'mount' (-v) นั่นจะแยกการเปลี่ยนแปลงโฟลเดอร์ย่อยออกจากคอนเทนเนอร์หรือไม่
เกร็ก

ฉันไม่แน่ใจว่าฉันไม่เคยลองทำรังปริมาณ ฉันไม่เชื่อว่ามันเป็นความคิดที่ดี แต่ฉันต้องดูมัน
Adrian Mouat

1
ฉันไม่สามารถหาตัวอย่างได้ทุกที่ที่จะใส่ใน.dockerignoreไฟล์เพื่อแยกไดเรกทอรีย่อย (หรือแม้แต่ไดเรกทอรี) ระบุว่าเป็นวัตถุประสงค์ที่ระบุไว้ของไฟล์มันค่อนข้างแปลก
Lukas Oberhuber

1
เมื่อคุณเพิ่มไฟล์ใด ๆ พวกเขายังคงจบลงในบางเลเยอร์ ดังนั้นการลบออกจะไม่ช่วยให้คุณซ่อนหากความปลอดภัยหรือลดขนาดภาพ (เพราะมันจะอยู่ในเลเยอร์พื้นฐาน) มีตัวเลือกให้squashกับเลเยอร์ หนึ่งคือgithub.com/goldmann/docker-squashและอีกอันใช้oc ex dockerbuildจากโครงการ openshift
akostadinov

6

ดูเหมือนว่าวิธีการแก้ปัญหาแบบเก่าจะไม่ทำงานอีกต่อไป (อย่างน้อยสำหรับฉัน) การสร้างโฟลเดอร์เปล่าและโฟลเดอร์เป้าหมายการจับคู่กับมันช่วยได้

volumes:
   - ./angularApp:/opt/app
   - .empty:/opt/app/node_modules/

ใช้งานไม่ได้กับฉันด้วยdocker-compose 1.25.0-rc3ไวยากรณ์ไฟล์ v3
thisismydesign

6

ด้วยบรรทัดคำสั่งนักเทียบท่า:

docker run \
    --mount type=bind,src=/hostFolder,dst=/containerFolder \
    --mount type=volume,dst=/containerFolder/subFolder \
    ...other-args...

-vตัวเลือกที่อาจจะใช้ (เครดิตกับBogdan Mart ) แต่--mountเป็นที่ชัดเจนและแนะนำ


6

สำหรับผู้ที่มีปัญหาว่าโฟลเดอร์ node_modules จะยังคงเขียนทับจากระบบโลคัลของคุณและวิธีอื่น ๆ

volumes:
  node_modules:
services:
  server:
    volumes:
      - .:/app
      - node_modules:/app/node_modules/

นี่คือการแก้ปัญหาด้วยการต่อท้าย/หลังจาก node_modules การแก้ไข


0

ในการแยกไฟล์ที่เมานต์ที่มีอยู่ในโวลุ่มของเครื่องคุณจะต้องเขียนทับมันด้วยการจัดสรรโวลุ่มไปที่ไฟล์เดียวกันนี้ ในไฟล์ปรับแต่งของคุณ:

services:
  server:
    build : ./Dockerfile
    volumes:
      - .:/app

ตัวอย่างใน dockerfile คุณ:

# Image Location
FROM node:13.12.0-buster
VOLUME /app/you_overwrite_file
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.