Cách gắn ổ đĩa cục bộ vào máy docker


85

Tôi đang cố gắng sử dụng docker-machine với docker-soạn. Tệp docker-compo.yml có các định nghĩa như sau:

web:
  build: .
  command: ./run_web.sh
  volumes:
    - .:/app
  ports:
    - "8000:8000"
  links:
    - db:db
    - rabbitmq:rabbit
    - redis:redis

Khi chạy docker-compose up -dmọi thứ suôn sẻ cho đến khi cố gắng thực thi lệnh và lỗi được tạo ra:

Không thể khởi động vùng chứa b58e2dfa503b696417c1c3f49e2714086d4e9999bd71915a53502cb6ef43936d: [8] Lỗi hệ thống: execute: "./run_web.sh": stat ./run_web.sh: không có tệp hoặc thư mục nào như vậy

Ổ đĩa cục bộ không được gắn vào máy từ xa. Chiến lược được đề xuất để gắn kết khối lượng cục bộ với mã của ứng dụng web là gì?


Cấu trúc của dự án và docker
compo.yml

1
Điều này nên có trong các tài liệu do trình soạn thảo soạn thảo như một gợi ý hữu ích cho những người có thể bắt đầu sử dụng tính năng soạn thư cục bộ. Sẽ giúp tôi tiết kiệm hàng giờ đồng hồ WTF khi cố gắng tìm ra lý do tại sao đường dẫn tệp của tôi bị sai hoặc không được tìm thấy. Không, tôi chỉ cảm thấy ngớ ngẩn.
timbrown

Câu trả lời:


93

Docker-machine tự động tính toán thư mục người dùng ... Nhưng đôi khi chỉ như vậy là chưa đủ.

Tôi không biết về docker 1.6, nhưng trong 1.8, bạn CÓ THỂ thêm một mount bổ sung vào docker-machine

Thêm điểm gắn máy ảo (phần 1)

CLI : (Chỉ hoạt động khi máy dừng)

VBoxManage sharedfolder add <machine name/id> --name <mount_name> --hostpath <host_dir> --automount

Vì vậy, một ví dụ trong windows sẽ là

/c/Program\ Files/Oracle/VirtualBox/VBoxManage.exe sharedfolder add default --name e --hostpath 'e:\' --automount

GUI : (KHÔNG yêu cầu dừng máy)

  1. Khởi động "Oracle VM VirtualBox Manager"
  2. Nhấp chuột phải <machine name>(mặc định)
  3. Cài đặt ...
  4. Thư mục chia sẻ
  5. Thư mục + Biểu tượng ở bên phải (Thêm Chia sẻ)
  6. Đường dẫn thư mục: <host dir>(e :)
  7. Tên thư mục: <mount name>(e)
  8. Kiểm tra "Tự động gắn kết" và "Đặt vĩnh viễn" (Chỉ đọc nếu bạn muốn ...) (Tự động gắn kết hiện tại là vô nghĩa ...)

Gắn trong boot2docker (phần 2)

Gắn kết thủ công trong boot2docker :

  1. Có nhiều cách khác nhau để đăng nhập, sử dụng "Show" trong "Oracle VM VirtualBox Manager" hoặc ssh / putty vào docker theo địa chỉ IP docker-machine ip default, v.v.
  2. sudo mkdir -p <local_dir>
  3. sudo mount -t vboxsf -o defaults,uid=`id -u docker`,gid=`id -g docker` <mount_name> <local_dir>

Nhưng điều này chỉ tốt cho đến khi bạn khởi động lại máy và khi đó mount bị mất ...

Thêm một số tự động vào boot2docker :

Trong khi đăng nhập vào máy

  1. Chỉnh sửa / tạo (với tư cách là người chủ) /mnt/sda1/var/lib/boot2docker/bootlocal.sh, sda1 có thể khác với bạn ...
  2. Thêm vào

    mkdir -p <local_dir>
    mount -t vboxsf -o defaults,uid=`id -u docker`,gid=`id -g docker` <mount_name> <local_dir>
    

Với những thay đổi này, bạn sẽ có một điểm gắn kết mới. Đây là một trong số ít các tệp tôi có thể tìm thấy được gọi khi khởi động và liên tục. Cho đến khi có một giải pháp tốt hơn, điều này sẽ hoạt động.


Phương pháp cũ: Ít được khuyến nghị hơn , nhưng được để như một phương pháp thay thế

  • Chỉnh sửa (với tư cách là người chủ) /mnt/sda1/var/lib/boot2docker/profile, sda1 có thể khác với bạn ...
  • Thêm vào

    add_mount() {
      if ! grep -q "try_mount_share $1 $2" /etc/rc.d/automount-shares ; then
        echo "try_mount_share $1 $2" >> /etc/rc.d/automount-shares
      fi
    }
    
    add_mount <local dir> <mount name>
    

Phương án cuối cùng , bạn có thể sử dụng giải pháp thay thế tẻ nhạt hơn một chút và bạn chỉ có thể sửa đổi hình ảnh khởi động.

  • git -c core.autocrlf=false clone https://github.com/boot2docker/boot2docker.git
  • cd boot2docker
  • git -c core.autocrlf=false checkout v1.8.1 # hoặc phiên bản thích hợp của bạn
  • Biên tập rootfs/etc/rc.d/automount-shares
  • Thêm try_mount_share <local_dir> <mount_name>dòng ngay trước fi ở cuối. Ví dụ

    try_mount_share /e e
    

    Chỉ cần đảm bảo không đặt thành bất kỳ thứ gì hệ điều hành cần, như / bin, v.v.

  • docker build -t boot2docker . # Quá trình này sẽ mất khoảng một giờ trong lần đầu tiên :(
  • docker run --rm boot2docker > boot2docker.iso
  • Sao lưu boot2docker.iso cũ và sao chép cái mới của bạn vào vị trí của nó, trong ~ / .docker / machine / machine /

Điều này thực sự hiệu quả, nó chỉ dài và phức tạp

phiên bản docker 1.8.1, docker-máy phiên bản 0.4.0


Đối với bất kỳ ai gặp vấn đề với điều này, tôi khá chắc chắn rằng mình phải làm cho các đường dẫn cục bộ khớp với các đường dẫn trong docker-machine. Ngoài ra, docker-compos có vẻ thành công trong việc gắn các ổ đĩa trong khi docker thông thường thì không - không rõ tại sao.
spieden

3
Đã tạo một tập lệnh cho giải pháp được đề cập ở đây. Hoạt động trên docker 1.10 mới nhất và docker-machine 0.6.0 gist.github.com/cristobal/fcb0987871d7e1f7449e
cristobal

Các nguồn khác nhau nói về việc sử dụng /mnt/sda1/var/lib/boot2docker/profile, bạn có thể giải thích lý do tại sao bạn chuyển sang sử dụng /mnt/sda1/var/lib/boot2docker/bootlocal.sh? Ngoài ra, nổi bật qua nhiều văn bản này không góp phần làm cho câu trả lời của bạn dễ đọc ;-)
Forage

1
@Forage Điểm đã thực hiện về định dạng của tôi :). Tôi không nhớ rõ tại sao tôi đề xuất bootlocal.shphương pháp này nữa. Tất cả những gì tôi có thể nói là nó trông gọn gàng hơn khi chỉ sử dụng một lệnh mount như tôi đã làm trong bootlocal.shhồ sơ. Ngoài ra, thông thường, tôi tin rằng nó profilecó thể được chạy nhiều lần và một thú cưỡi chỉ cần được chạy một lần, vì vậy nó có ý nghĩa hơn. Nhưng cả hai đều có thể hoạt động.
Andy

YÊU NÓ! Cảm ơn bạn!
Qorbani

28

Cũng gặp phải sự cố này và có vẻ như ổ đĩa cục bộ không được gắn kết khi sử dụng docker-machine. Một giải pháp hack là

  1. lấy thư mục làm việc hiện tại của phiên bản docker-machine docker-machine ssh <name> pwd

  2. sử dụng một công cụ dòng lệnh như rsyncđể sao chép thư mục vào hệ thống từ xa

    rsync -avzhe ssh --progress <name_of_folder> username@remote_ip:<result _of_pwd_from_1>.
    

Pwd mặc định là / root nên lệnh trên sẽ là rsync -avzhe ssh --progress <name_of_folder> username@remote_ip:/root

NB: bạn cần cung cấp mật khẩu cho hệ thống từ xa. Bạn có thể nhanh chóng tạo một bằng ssh vào hệ thống từ xa và tạo mật khẩu.

  1. thay đổi điểm gắn kết âm lượng trong docker-compose.ymltệp của bạn từ .:/appthành/root/<name_of_folder>:/app

  2. chạy docker-compose up -d

NB khi các thay đổi được thực hiện cục bộ, đừng quên chạy lại rsyncđể đẩy các thay đổi vào hệ thống từ xa.

Nó không hoàn hảo nhưng nó hoạt động. Một sự cố đang diễn ra https://github.com/docker/machine/issues/179

Dự án khác cố gắng giải quyết vấn đề này bao gồm docker-rsync


rsync cần được cài đặt trên hệ thống từ xa. -45 / rsync / io.c (453) [sender = 2.6.9] `Bạn làm cách nào để nó hoạt động?
krinker

1
rsync cần phải được cài đặt trên hệ thống địa phương của bạn
gbozee

Việc sử dụng các bước này sẽ khóa hoàn toàn máy chủ digitalocean của tôi. Các tệp truyền tải tốt nhưng khi tôi cố gắng kết nối lại với máy chủ lưu trữ bằng docker-machine, tôi nhận được exit status 255và phải tạo lại hoàn toàn máy.
dsifford

1
Đã tạo một tập lệnh cho giải pháp được đề cập ở đây. Hoạt động trên trang mới nhất docker 1.10docker-machine 0.6.0 gist.github.com/cristobal/fcb0987871d7e1f7449e
cristobal

@cristobal có vẻ như bạn đã viết kịch bản giải pháp mount, không phải giải pháp rsync?
Andy

14

Hiện tại, tôi thực sự không thể thấy bất kỳ cách nào để gắn khối lượng trên máy tính, vì vậy cách tiếp cận bây giờ là bằng cách nào đó sao chép hoặc đồng bộ hóa các tệp bạn cần vào máy.

Có các cuộc trò chuyện về cách giải quyết vấn đề này trên github repo của docker-machine. Ai đó đã đưa ra yêu cầu kéo triển khai scp trên docker-machine và nó đã được hợp nhất trên master, vì vậy rất có thể bản phát hành tiếp theo sẽ bao gồm nó.

Vì nó chưa được phát hành nên bây giờ tôi khuyên bạn rằng nếu bạn có mã của mình được lưu trữ trên github, chỉ cần sao chép repo của bạn trước khi bạn chạy ứng dụng

web:
  build: .
  command: git clone https://github.com/my/repo.git; ./repo/run_web.sh
  volumes:
    - .:/app
  ports:
    - "8000:8000"
  links:
    - db:db
    - rabbitmq:rabbit
    - redis:redis

Cập nhật: Xem xét thêm, tôi thấy rằng tính năng này đã có sẵn trong các tệp nhị phân mới nhất , khi bạn nhận được chúng, bạn sẽ có thể sao chép dự án cục bộ của mình bằng cách chạy lệnh như sau:

docker-machine scp -r . dev:/home/docker/project

Đây là hình thức chung:

docker-machine scp [machine:][path] [machine:][path]

Vì vậy, bạn có thể sao chép tệp từ, đến và giữa các máy.

Chúc mừng! 1


tài liệu cho docker-machine scp: docs.docker.com/machine/reference/scp
Anthony Dahanne

2
phương pháp này rất chậm :(
Sergej Jevsejev

5

Kể từ tháng 10 năm 2017, có một lệnh mới cho docker-machine thực hiện thủ thuật này, nhưng hãy đảm bảo rằng không có gì trong thư mục trước khi thực hiện nó, nếu không nó có thể bị mất:

docker-machine mount <machine-name>:<guest-path> <host-path>

Kiểm tra tài liệu để biết thêm thông tin: https://docs.docker.com/machine/reference/mount/

PR với sự thay đổi: https://github.com/docker/machine/pull/4018


1
Thật không thể tin được, từ tài liệu Docker Machine (mà bạn đã liên kết), - theo nghĩa đen - không thể biết rằng thứ tự trong lệnh là ...:<guest-path> <host-path>(thay vì ngược lại). Một cái gì đó đơn giản và quan trọng như vậy cần lưu ý trong tài liệu ... chỉ là không!
Dan Nissenbaum

Tôi đoán nó không rõ ràng lắm, bạn nói đúng. Nó phải được đoán từ danh sách các lệnh
Jorge

Nó thực hiện thủ thuật, nhưng theo cách khác. Nó cho phép gắn docker-machine dir trên máy cục bộ của bạn. Thật không may, nó không cho phép theo cách khác :(
ravenwing

4

Nếu bạn chọn tùy chọn rsync với docker-machine, bạn có thể kết hợp nó với docker-machine ssh <machinename>lệnh như sau:

rsync -rvz --rsh='docker-machine ssh <machinename>' --progress <local_directory_to_sync_to> :<host_directory_to_sync_to>

Nó sử dụng định dạng lệnh này của rsync, để HOSTtrống:

rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST

( http://linuxcommand.org/man_pages/rsync1.html )


1

Cuối cùng đã tìm ra cách nâng cấp Hộp công cụ Windows Docker lên v1.12.5 và giữ cho các ổ đĩa của tôi hoạt động bằng cách thêm một thư mục được chia sẻ trong trình Oracle VM VirtualBoxquản lý và tắt chuyển đổi đường dẫn. Nếu bạn có Windows 10+ thì tốt nhất bạn nên sử dụng Docker mới hơn cho Windows.

Lần đầu tiên nâng cấp Pain:

  1. Gỡ cài đặt VirtualBox trước.
    • Đúng vậy có thể làm hỏng nội dung trong các công cụ khác như Android Studio. Cảm ơn Docker :(
  2. Cài đặt phiên bản mới của Hộp công cụ Docker.

Ví dụ về cơ sở dữ liệu Redis: redis: image: redis:alpine container_name: redis ports: - "6379" volumes: - "/var/db/redis:/data:rw"

Trong Docker Quickstart Terminal ....

  1. run docker-machine stop default- Đảm bảo máy ảo được hỗ trợ

Trong Oracle VM VirtualBox Manager ...

  1. Đã thêm một thư mục được chia sẻ trong defaultVM thông qua hoặc dòng lệnh
    • D:\Projects\MyProject\db => /var/db

Trong docker-compose.yml...

  1. Âm lượng redis được ánh xạ dưới dạng: "/var/db/redis:/data:rw"

Trong Docker Quickstart Terminal ....

  1. Đặt COMPOSE_CONVERT_WINDOWS_PATHS=0(cho phiên bản Hộp công cụ> = 1.9.0)
  2. chạy docker-machine start defaultđể khởi động lại máy ảo.
  3. cd D:\Projects\MyProject\
  4. docker-compose up nên làm việc ngay bây giờ.

Bây giờ tạo cơ sở dữ liệu redis trong D:\Projects\MyProject\db\redis\dump.rdb

Tại sao phải tránh các đường dẫn máy chủ tương đối?

Tôi đã tránh các đường dẫn máy chủ lưu trữ tương đối cho Hộp công cụ Windows vì chúng có thể giới thiệu các ký tự '\' không hợp lệ. Nó không tốt bằng việc sử dụng các đường dẫn liên quan đến docker-compose.ymlnhưng ít nhất các nhà phát triển đồng nghiệp của tôi có thể dễ dàng làm điều đó ngay cả khi thư mục dự án của họ ở nơi khác mà không phải hack docker-compose.ymltệp (không tốt cho SCM).

Vấn đề ban đầu

FYI ... Đây là lỗi ban đầu tôi gặp phải khi tôi sử dụng các đường dẫn tương đối sạch đẹp mà trước đây chỉ hoạt động tốt cho các phiên bản cũ hơn. Ánh xạ âm lượng của tôi từng là"./db/redis:/data:rw"

ERROR: for redis Cannot create container for service redis: Invalid bind mount spec "D:\\Projects\\MyProject\\db\\redis:/data:rw": Invalid volume specification: 'D:\Projects\MyProject\db\redis:/data

Điều này bị phá vỡ vì hai lý do ..

  1. Nó không thể truy cập D: ổ đĩa
  2. Đường dẫn âm lượng không thể bao gồm \ ký tự
    • docker-compose thêm chúng và sau đó đổ lỗi cho bạn về điều đó !!
    • Sử dụng COMPOSE_CONVERT_WINDOWS_PATHS=0để ngăn chặn điều vô nghĩa này.

Tôi khuyên bạn nên ghi lại bản đồ thư mục chia sẻ VM bổ sung trong docker-compose.ymltệp của bạn vì bạn có thể cần gỡ cài đặt lại VirtualBox và đặt lại thư mục được chia sẻ và dù sao thì các nhà phát triển đồng nghiệp của bạn cũng sẽ thích bạn vì nó.


bạn ạ, là một người tốt
AaronHS

1

Tất cả các câu trả lời khác đều tốt vào thời điểm đó nhưng bây giờ (Hộp công cụ Docker v18.09.3) tất cả đều hoạt động tốt. Bạn chỉ cần thêm một thư mục chia sẻ vào VirtualBox VM.

Hộp công cụ Docker tự động thêm C:\Usersdưới dạng thư mục chia sẻ /c/Userstrong máy Linux ảo (sử dụng tính năng Thư mục chia sẻ Hộp ảo), vì vậy nếu docker-compose.ymltệp của bạn nằm ở đâu đó dưới đường dẫn này và bạn chỉ gắn các thư mục của máy chủ theo đường dẫn này - tất cả sẽ hoạt động tốt.

Ví dụ:

C:\Users\username\my-project\docker-compose.yml:

...
  volumes:
    - .:/app
...

Đường .dẫn sẽ được tự động chuyển đổi thành đường dẫn tuyệt đối C:\Users\username\my-projectvà sau đó đến /c/Users/username/my-project. Và đây chính xác là cách đường dẫn này được nhìn thấy từ quan điểm của máy ảo linux (bạn có thể kiểm tra nó: docker-machine sshvà sau đó ls /c/Users/username/my-project). Vì vậy, thú cưỡi cuối cùng sẽ là/c/Users/username/my-project:/app .

Tất cả hoạt động minh bạch cho bạn.

Nhưng điều này không hoạt động nếu đường dẫn gắn kết máy chủ của bạn không nằm trong C:\Usersđường dẫn. Ví dụ, nếu bạn đặt cùng một docker-compose.ymlbên dưới D:\dev\my-project.

Điều này có thể được khắc phục một cách dễ dàng.

  1. Dừng máy ảo ( docker-machine stop).
  2. Mở Virtual Box GUI, mở Cài đặt của Máy ảo có tên default, mở Shared Foldersphần và thêm thư mục chia sẻ mới:

    • Đường dẫn thư mục: D:\dev
    • Tên thư mục: d/dev

    Nhấn OKhai lần và đóng GUI Hộp ảo.

  3. Khởi động máy ảo ( docker-machine start).

Đó là tất cả. Tất cả các đường dẫn của máy chủ bên dưới D:\devsẽ hoạt động ngay trong docker-compose.ymlmount.


1

Nó có thể là sự kết hợp phù thủy done của ba công cụ: docker-machine mount, rsync,inotifywait

TL; DR

Tập lệnh dựa trên tất cả bên dưới là ở đây

Giả sử bạn có docker-compose.ymlrun_web.shtrong/home/jdcaballerov/web

  1. Gắn kết thư mục trên máyđường dẫn giống như bạn có trên máy chủ của bạndocker-machine machine:/home/jdcaballerov/web /tmp/some_random_dir
  2. Đồng bộ hóa thư mục được gắn kết với dir trên máy chủ của bạn rsync -r /home/jdcaballerov/web /tmp/some_random_dir
  3. Đồng bộ hóa trên mọi thay đổi của tệp trong thư mục của bạn:

    inotifywait -r -m -e close_write --format '%w%f' /home/jdcaballerov/web | while read CHANGED_FILE
    do
        rsync /home/jdcaballerov/web /tmp/some_random_dir
    done
    

HÃY NHẬN THỨC - có hai thư mục có cùng đường dẫn - một là trên máy cục bộ (máy chủ) của bạn, thứ hai là trên máy docker.


0

Tôi cho rằng run_web.shtệp nằm trong cùng thư mục với docker-compose.ymltệp của bạn . Sau đó, lệnh nên được command: /app/run_web.sh.

Trừ khi Dockerfile(mà bạn không tiết lộ) quan tâm đến việc đưa run_web.shtệp vào hình ảnh Docker.


cảm ơn câu trả lời của bạn. Nó nằm trên cùng một thư mục. Tuy nhiên, tôi nhận thấy âm lượng không được gắn kết. Các tệp không có sẵn và đó là câu hỏi. Làm thế nào để thêm chúng. Cấu trúc tương tự như syncano.com/…
jdcaballerov

Đảm bảo rằng bạn có phiên bản mới nhất của cả docker và dicker -omp.
Thomasleveil

docker: Docker phiên bản 1.6.0, bản dựng 4749651, docker-machine phiên bản 0.2.0 (8b9eaf2),
docker

Bạn đã sửa đổi Dockerfile từ syncano.com/… theo bất kỳ cách nào chưa?
Thomasleveil

1
Có, tôi thêm mã, tạo thư mục. Rắc rối là khi docker-compin thực thi nó sẽ ghi đè lên volume: volume: -.: / App và để lại một thư mục trống. Tôi đã nhận xét các tập trong sáng tác và nó hoạt động.
jdcaballerov

0

Sau khi tóm tắt các bài đăng ở đây, tập lệnh cập nhật đính kèm, để tạo thêm điểm gắn kết trên máy chủ và số tự động khi Virtualbox khởi động lại. Môi trường làm việc ngắn gọn như sau: - Windows 7 - docker-machine.exe phiên bản 0.7.0 - VirtualBox 5.0.22

    #!env bash

    : ${NAME:=default}
    : ${SHARE:=c/Proj}
    : ${MOUNT:=/c/Proj}
    : ${VBOXMGR:=C:\Program Files\Oracle\VirtualBox\VBoxManage.exe}
    SCRIPT=/mnt/sda1/var/lib/boot2docker/bootlocal.sh

    ## set -x
    docker-machine stop $NAME
    "$VBOXMGR" sharedfolder add $NAME --name c/Proj --hostpath 'c:\' --automount 2>/dev/null || :
    docker-machine start $NAME
    docker-machine env $NAME

    docker-machine ssh $NAME 'echo "mkdir -p $MOUNT" | sudo tee $SCRIPT'
    docker-machine ssh $NAME 'echo "sudo mount -t vboxsf -o rw,user $SHARE $MOUNT" |  sudo tee -a $SCRIPT'
    docker-machine ssh $NAME 'sudo chmod +x /mnt/sda1/var/lib/boot2docker/bootlocal.sh'
    docker-machine ssh $NAME 'sudo /mnt/sda1/var/lib/boot2docker/bootlocal.sh'
    #docker-machine ssh $NAME 'ls $MOUNT'

0

Tôi đang sử dụng docker-machine 0.12.2 với ổ đĩa virtualbox trên máy cục bộ của mình. Tôi thấy rằng có một thư mục /hosthome/$(user name)mà từ đó bạn có quyền truy cập vào các tệp cục bộ.


0

Tôi chỉ nghĩ rằng tôi đã đề cập đến việc tôi đã sử dụng 18.03.1-ce-win65 (17513) trên Windows 10 và tôi nhận thấy rằng nếu trước đó bạn đã chia sẻ ổ đĩa và lưu trữ thông tin đăng nhập, khi bạn thay đổi trình cắm mật khẩu của mình sẽ bắt đầu có khối lượng được gắn trong các thùng chứa dưới dạng trống.

Nó không đưa ra dấu hiệu nào cho thấy những gì đang thực sự xảy ra là nó hiện không thể truy cập vào thông tin đăng nhập được chia sẻ trong bộ nhớ cache cũ. Giải pháp trong trường hợp này là đặt lại thông tin xác thực thông qua giao diện người dùng (Cài đặt-> Ổ đĩa dùng chung) hoặc tắt tính năng chia sẻ ổ đĩa sau đó bật lại và nhập mật khẩu mới.

Sẽ rất hữu ích nếu docker-soạn gặp lỗi trong những trường hợp này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.