วิธีการเมาท์ไฟล์เดียวในโวลุ่ม


259

ฉันกำลังพยายามเชื่อมต่อแอปพลิเคชัน php เข้าด้วยกัน ใน dockerfile ฉันจะดาวน์โหลดไฟล์เก็บถาวรแยกมันออกเป็นต้น

ทุกอย่างใช้งานได้ดี แต่ถ้ามีเวอร์ชั่นใหม่ออกมาและฉันอัปเดต dockerfile ฉันต้องติดตั้งแอปพลิเคชันใหม่เนื่องจาก config.php ถูกเขียนทับ

ดังนั้นฉันคิดว่าฉันสามารถเมานไฟล์เป็นไดรฟ์เหมือนที่ฉันทำกับฐานข้อมูล

ฉันลองสองวิธีด้วยระดับเสียงและเส้นทางโดยตรง

นักเทียบท่า-เขียน:

version: '2'
services:
  app:
    build: src
    ports:
      - "8080:80"
    depends_on:
      - mysql
    volumes:
      -  app-conf:/var/www/html/upload
      -  app-conf:/var/www/html/config.php
    environment:
      DB_TYPE: mysql
      DB_MANAGER: MysqlManager

  mysql:
    image: mysql:5.6
    container_name: mysql
    volumes:
      - mysqldata:/var/lib/mysql
    ports:
      - 3306:3306
    environment:
      MYSQL_ROOT_PASSWORD:
      MYSQL_DATABASE:
      MYSQL_USER:
      MYSQL_PASSWORD:

volumes:
  mysqldata:
  app-conf:

ซึ่งส่งผลให้เกิดข้อผิดพลาด:

และฉันลองกับเส้นทางที่กำหนดเป็นไดรฟ์ข้อมูลที่ติดตั้ง

/src/docker/myapp/upload:/var/www/html/upload
/src/docker/myapp/upload:/var/www/html/config.php

อย่างไรก็ตามทั้งสองวิธีไม่ทำงาน ฉันเห็นว่าการอัพโหลดได้ถูกสร้างขึ้น

แต่แล้วก็ล้มเหลวด้วย

/var/www/html/config.php \\ "เกิดจาก \\" ไม่ใช่ไดเรกทอรี \\ "\" "

ถ้าฉันลองด้วย

/src/docker/myapp/upload/config.php:/var/www/html/config.php

นักเทียบท่าสร้างโฟลเดอร์อัพโหลดแล้วเป็นโฟลเดอร์ config.php ไม่ใช่ไฟล์

หรือมีวิธีอื่นในการกำหนดค่ายังคงอยู่หรือไม่


ในกรณีของฉันฉันง่ายที่จะ "สัมผัส" ไฟล์ว่างเปล่าก่อนที่จะสร้างภาชนะ / ปริมาณ หากไฟล์นั้นไม่มีอยู่มันจะสร้างไดเรกทอรี
FreeSoftwareServers

คำตอบ:


314

TL; DR / หมายเหตุ:

หากคุณพบไดเรกทอรีที่สร้างขึ้นแทนไฟล์ที่คุณพยายามเมาต์คุณอาจล้มเหลวในการระบุพา ธ ที่ถูกต้องและแน่นอน นี่เป็นข้อผิดพลาดทั่วไปที่เกิดขึ้นกับโหมดล้มเหลวที่เงียบและสับสน

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

    volumes:
      - /src/docker/myapp/upload:/var/www/html/upload
      - /src/docker/myapp/upload/config.php:/var/www/html/config.php

คุณยังสามารถทำสิ่งต่อไปนี้

    volumes:
      - ${PWD}/upload:/var/www/html/upload
      - ${PWD}/upload/config.php:/var/www/html/config.php

หากคุณเปิดใช้งานนักเขียนจาก/src/docker/myappโฟลเดอร์


81
อย่างที่ฉันบอกว่าถ้าฉันลอง /src/docker/myapp/upload/config.php:/var/www/html/config.php Docker จะสร้างโฟลเดอร์อัพโหลดขึ้นมาและโฟลเดอร์ config.php ไม่ใช่ไฟล์
Jakub Juszczak

9
ในโพสต์ของคุณคุณเขียนแตกต่างกัน หากไฟล์อยู่ที่นั่นก็ควรจะเมานต์เป็นไฟล์
BlackStork

16
เพื่อให้การทำงานนี้ฉันต้องจัดหาเส้นทางที่แน่นอน เคล็ดลับในการใช้ PWD ช่วยได้มากที่นี่ขอบคุณ!
Steve Smith

4
สำหรับฉันกำลังสร้างโฟลเดอร์มากกว่าไฟล์ แต่ฉันคิดว่าเพราะไฟล์นั้นถูกคัดลอกในภายหลังในเส้นทางนั้นมีวิธีใดที่จะเลื่อนการผูกหรือไม่
eKelvin

18
หาก /src/docker/myapp/upload/config.php ไม่มีอยู่ใน host docker จะสร้างโฟลเดอร์ ... สิ่งที่ฉันกำลังทำคือการสร้างสคริปต์ที่สร้างไฟล์เปล่าก่อนที่จะรัน docker run - จะเป็นอุดมคติ ถ้าฉันสามารถสั่งนักเทียบท่าให้ทำเพื่อฉันผ่านทางบรรทัด cmd
Cancerbero

78

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

ฉันหมายความว่าฉันคิดว่าคำสั่งด้านล่างจะแมป$(pwd)/config.pyจากโฮสต์ Docker /root/app/config.pyลงในคอนเทนเนอร์เป็นไฟล์

docker run -v $(pwd)/config.py:/root/app/config.py my_docker_image

อย่างไรก็ตามมันจะสร้างไดเรกทอรีที่ชื่อconfig.pyไม่ใช่ไฟล์เสมอ

ในขณะที่มองหาเบาะแสฉันพบเหตุผล (จากที่นี่ )

หากคุณใช้ -v หรือ --volume เพื่อผูกไฟล์หรือไดเรกทอรีที่ยังไม่มีอยู่ในโฮสต์ Docker -v จะสร้างจุดสิ้นสุดสำหรับคุณ มันถูกสร้างขึ้นเป็นไดเรกทอรีเสมอ

$(pwd)/config.pyดังนั้นจึงถูกสร้างขึ้นเสมอเป็นไดเรกทอรีเนื่องจากโฮสต์นักเทียบท่าของฉันไม่ได้มี

แม้ว่าฉันจะสร้าง config.py ในโฮสต์นักเทียบท่า $(pwd)/config.pyเพียง overwirte ไม่ได้การส่งออก/root/app/config.py/root/app/config.py


16
ฉันเพียงแค่เพิ่มtouch path/to/fileในDockerfileเพื่อที่ว่าเมื่อผมติดมันจะยังคงเป็นไฟล์ (ไม่ได้เป็นผบสร้าง)
Shadi

8
ด้านซ้ายของ:ต้องเป็นเส้นทางแบบเต็ม มันทำงานได้ด้วยวิธีนี้
sdkks

touchเป็นคำตอบที่ทำในปริมาณ Dockerfile แล้วนักเทียบท่า-เขียนของคุณติดจะทำงานอย่างถูกต้องโดยไม่ต้องสร้างไดเรกทอรี
ctrlbrk

27

ใช้mount ( --mount) แทนvolume ( -v)

ข้อมูลเพิ่มเติม: https://docs.docker.com/storage/bind-mounts/

ตัวอย่าง:

ตรวจสอบให้แน่ใจว่า /tmp/a.txt อยู่ในโฮสต์ของนักเทียบท่า

docker run -it --mount type=bind,source=/tmp/a.txt,target=/root/a.txt alpine sh

ขอบคุณ Subbu, @Jakub Juszczak นี่ควรเป็นคำตอบที่ได้รับการยอมรับมันเป็นคำตอบเดียวที่ตอบคำถามได้ทั้งหมดและมันใช้ได้กับฉันด้วย
neokyle

2
นี่ไม่ได้ตอบคำถามจริงๆ ปริมาณจะทำงานได้เช่นกัน (เพราะปัญหาอยู่ในเส้นทางที่แน่นอน) ข้อแตกต่างระหว่าง--mountและ-vคือพฤติกรรมเมื่อส่วนโฮสต์ของโวลุ่มยังไม่มีอยู่ ตามลิงค์ของคุณ:> หากคุณใช้ -v หรือ --volume เพื่อผูกไฟล์หรือไดเรกทอรีที่ยังไม่มีอยู่ในโฮสต์ Docker -v จะสร้างจุดปลายสำหรับคุณ มันถูกสร้างขึ้นเป็นไดเรกทอรีเสมอ
เจ้าพ่อ

2
ฉันไม่ทราบวิธีการแปลนี้เป็นนักเทียบท่าเขียน 'ช่วยหน่อยได้ไหม?
msanford

@msanford ฉันได้เพิ่มตัวอย่างนักเทียบท่าลงในคำตอบ
sebisnow

10

สำหรับใครก็ตามที่ใช้ Windows container อย่างฉันรู้ว่าคุณไม่สามารถผูกหรือเมานต์ไฟล์เดียวโดยใช้ windows container

ตัวอย่างต่อไปนี้จะล้มเหลวเมื่อใช้คอนเทนเนอร์ที่ใช้ Windows เป็นปลายทางของไดรฟ์ข้อมูลหรือผูกติดอยู่ภายในคอนเทนเนอร์ต้องเป็นหนึ่งใน: ไดเรกทอรีไม่มีอยู่หรือไดเรกทอรีว่างเปล่า หรือไดรฟ์อื่นที่ไม่ใช่ C: นอกจากนี้แหล่งที่มาของการผูกติดจะต้องเป็นไดเรกทอรีท้องถิ่นไม่แฟ้ม

net use z: \\remotemachine\share

docker run -v z:\foo:c:\dest ...

docker run -v \\uncpath\to\directory:c:\dest ...

docker run -v c:\foo\somefile.txt:c:\dest ...

docker run -v c:\foo:c: ...

docker run -v c:\foo:c:\existing-directory-with-contents ...

มันยากที่จะมองเห็น แต่มันอยู่ที่นั่น

เชื่อมโยงไปยังปัญหา Github เกี่ยวกับการแมปไฟล์ลงในคอนเทนเนอร์ Windows


9

วิธีที่ใช้งานได้สำหรับฉันก็คือการใช้อุปกรณ์bindยึด

  version: "3.7"    
  services:
  app:
    image: app:latest
    volumes:
      - type: bind
        source: ./sourceFile.yaml
        target: /location/targetFile.yaml

ขอบคุณไมค์ผสมพันธุ์สำหรับคำตอบที่: Mount ไฟล์เดียวจากปริมาณการใช้นักเทียบท่าประกอบ

คุณต้องใช้ "ไวยากรณ์ยาว" เพื่อแสดงการbindเมานต์: https://docs.docker.com/compose/compose-file/#long-syntax


7

ในฐานะที่เป็นไฟล์ประกอบรุ่นเทียบท่าเทียบท่า 3.2 คุณสามารถระบุปริมาณการเมานต์ของประเภท "ผูก" (แทนที่จะเป็น "ปริมาณ" ประเภทเริ่มต้น) ที่ช่วยให้คุณสามารถเมาท์ไฟล์เดียวลงในภาชนะ ค้นหา "ผูกติด" ในเอกสารปริมาณนักเทียบท่า: https://docs.docker.com/compose/compose-file/#volumes

ในกรณีของฉันฉันกำลังพยายามติดตั้งไฟล์ ".secrets" ไฟล์เดียวในแอปพลิเคชันของฉันซึ่งมีความลับสำหรับการพัฒนาและทดสอบในท้องถิ่นเท่านั้น ในการผลิตแอปพลิเคชันของฉันดึงข้อมูลความลับเหล่านี้จาก AWS แทน

หากฉันติดตั้งไฟล์นี้เป็นโวลุ่มโดยใช้ไวยากรณ์ชวเลข:

volumes:
 - ./.secrets:/data/app/.secrets

นักเทียบท่าจะสร้างไดเรกทอรี ".secrets" ภายในคอนเทนเนอร์แทนที่จะจับคู่กับไฟล์นอกคอนเทนเนอร์ รหัสของฉันจะเพิ่มข้อผิดพลาดเช่น "IsADirectoryError: [Errno 21] เป็นไดเรกทอรี: '.secrets'"

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

volumes:
 - type: bind
   source: ./.secrets
   target: /data/app/.secrets
   read_only: true

ตอนนี้นักเทียบท่าติดตั้งไฟล์. secrets ของฉันลงในคอนเทนเนอร์อย่างถูกต้องแล้วสร้างไฟล์ภายในคอนเทนเนอร์แทนที่จะเป็นไดเรกทอรี หวังว่าคนอื่นจะเห็นว่าตัวอย่างนี้มีประโยชน์!


ขอบคุณมาก! นั่นเป็นทางออกที่ฉันต้องใช้เพื่อติดตั้งไฟล์ WordPress wp-config.php ของฉัน (และหยุดสร้างเป็นไดเรกทอรี)
Jono

6

คุณสามารถใช้พา ธ สัมพัทธ์กับdocker-compose.ymlไฟล์ของคุณเช่นนี้ (ทดสอบบนโฮสต์ Windows, คอนเทนเนอร์ Linux)

 volumes:
      - ./test.conf:/fluentd/etc/test.conf

1
ฉันทดสอบสิ่งนี้บน Mac โดยมีการversion: '3.7'ระบุในdocker-compose.ymlไฟล์ด้วยนักเทียบท่า - รุ่นเขียน 1.24.1, สร้าง 4667896b และมันทำงานได้
คิวเมนตัส

6
ฉันยังคงได้รับไดเรกทอรีแทนไฟล์
chovy

0

สำหรับฉันปัญหาคือว่าฉันมีลิงค์สัญลักษณ์เสียบนไฟล์ที่ฉันพยายามที่จะติดตั้งลงในภาชนะ


0

ฉันมีปัญหาเดียวกันบน Docker 18.06.1-ce-win73 (19507)Windows,

การถอดและเพิ่มไดรฟ์ที่แชร์อีกครั้งผ่านแผงการตั้งค่า Docker และทุกอย่างทำงานได้อีกครั้ง


0

ใน windows หากคุณต้องการตัวแปร $ {PWD} env ใน docker-compose.yml ของคุณคุณสามารถสร้างไฟล์. env ในไดเรกทอรีเดียวกับไฟล์ docker-compose.yml ของคุณจากนั้นใส่ตำแหน่งของโฟลเดอร์ของคุณเอง

CMD (pwd_var.bat):

echo PWD=%cd% >> .env

Powershell (pwd_var.ps1):

$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'; echo "PWD=$(get-location).path" >> .env

มีคุณสมบัติที่ดีมากขึ้นได้ยินสำหรับตัวแปร .env นักเทียบท่า-เขียน: https://docs.docker.com/compose/reference/envvars/โดยเฉพาะอย่างยิ่งสำหรับCOMPOSE_CONVERT_WINDOWS_PATHSตัวแปร env ที่ช่วยให้นักเทียบท่าเขียนจะยอมรับเส้นทางหน้าต่าง "\"baskslash

เมื่อคุณต้องการแชร์ไฟล์บน windows ไฟล์นั้นจะต้องมีอยู่ก่อนที่จะแชร์กับคอนเทนเนอร์


คุณไม่สามารถใช้ PowerShell กับ docker มันสร้างล็อคผู้ขายและทำร้ายชุมชน ...
Matej 'Yin' Gagyi

0

บางทีนี่อาจช่วยใครซักคน

ฉันมีปัญหานี้และลองทุกอย่าง การผูกข้อมูลไดรฟ์ดูดีและแม้ว่าฉันจะติดตั้งไดเรกทอรี (ไม่ใช่ไฟล์) ฉันมีชื่อไฟล์ในไดเรกทอรีที่ติดตั้งอย่างถูกต้อง แต่ติดตั้งเป็น dirs

ฉันพยายามเปิดใช้งานไดรฟ์ที่ใช้ร่วมกันอีกครั้งและ Docker บ่นว่าไฟร์วอลล์เปิดใช้งานอยู่

หลังจากปิดการใช้งานไฟร์วอลล์ทุกอย่างทำงานได้ดี


ขอบคุณสำหรับสิ่งนั้น! โพสต์ของคุณทำให้ฉันรู้ว่า selinux ของฉันถูกกำหนดให้บังคับใช้และนั่นเป็นสาเหตุของปัญหาทั้งหมด ไม่ทราบว่าทำไมคุณถึงถูกโหวต¯_ (ツ) _ / ¯
Octavian

0

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

ในตัวอย่างนี้ฉันกำลังติดตั้งไฟล์คำสั่ง env ซึ่งมีอยู่แล้วในไดเรกทอรีการทำงานของฉัน

$ docker run  --rm -it -v ${PWD}/env-commands:/env-commands aravindgv/eosdt:1.0.5 /bin/bash -c "cat /env-commands"

-1

ฉันมีปัญหาเดียวกันใน Windows 8.1 ของฉัน

มันกลับกลายเป็นว่ามันเป็นเพราะความไวของเส้นทาง ฉันเรียกdocker-compose upจากไดเรกทอรีcd /c/users/alex/และภายในคอนเทนเนอร์ไฟล์ถูกเปลี่ยนเป็นไดเรกทอรี

แต่เมื่อฉันทำcd /c/Users/alex/(ไม่ใช่ผู้ใช้อักษรตัวใหญ่) และเรียกdocker-compose upจากที่นั่นมันทำงานได้

ในระบบของฉันทั้งผู้ใช้ dir และ Alex dir จะเป็นตัวพิมพ์ใหญ่ แต่ดูเหมือนว่าเฉพาะผู้ใช้เท่านั้นที่มีความสำคัญ

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