Last active
November 2, 2024 08:05
-
-
Save cristobal/fcb0987871d7e1f7449e to your computer and use it in GitHub Desktop.
Machine Diskutil to mount/unmont external volumes inside docker machines running on Virtualbox
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env sh | |
# @see http://stackoverflow.com/questions/30040708/how-to-mount-local-volumes-in-docker-machine | |
# @see https://github.com/boot2docker/boot2docker/blob/master/doc/FAQ.md | |
################################################################################ | |
# Dependency Section # | |
# # | |
################################################################################ | |
check_deps() { | |
## Make sure commands are available | |
local name | |
for name in docker-machine VBoxManage grep ; do | |
type $name > /dev/null 2>&1 | |
if [ $? -eq 1 ] ; then | |
echo "Error: Command \`$name\` not found," | |
echo "make sure it is available from your \`\$PATH\`" | |
exit 1 | |
fi | |
done | |
} | |
################################################################################ | |
# Helper Functions # | |
# # | |
################################################################################ | |
volume_exists() { | |
if [ ! -d $volume ] ; then | |
echo "Error: The volume \`$volume\` does not exist," | |
echo "make sure to specify the correct volume path" | |
exit 1 | |
fi | |
} | |
################################################################################ | |
# Machine Helper Functions # | |
# # | |
################################################################################ | |
machine_exists() { | |
docker-machine ls | grep "$machine" > /dev/null 2>&1 | |
if [ $? -ne 0 ] ; then | |
echo "Error: The docker machine \`$machine\` does not exist," | |
echo "make sure to specify the correct docker machine." | |
exit 2 | |
fi | |
} | |
machine_stop() { | |
docker-machine status $machine | grep -E -i 'stopped' > /dev/null 2>&1 | |
if [ $? -ne 1 ] ; then | |
return | |
fi | |
echo "Info: Attempting to stop the docker-machine \`$machine\`." | |
echo "> docker-machine stop $machine" | |
docker-machine stop $machine | |
if [ $? -ne 0 ] ; then | |
echo "Error: Failed to stop the docker-machine \`$machine\`." | |
exit 3 | |
fi | |
echo "[OK]" | |
} | |
machine_start() { | |
docker-machine status $machine | grep -E -i 'running' > /dev/null 2>&1 | |
if [ $? -ne 1 ] ; then | |
return | |
fi | |
echo "Info: Attempting to start the docker-machine \`$machine\`." | |
echo "> docker-machine start $machine" | |
docker-machine start $machine | |
if [ $? -ne 0 ] ; then | |
echo "Error: Failed to start the docker-machine \`$machine\`." | |
exit 4 | |
fi | |
echo "[OK]" | |
} | |
machine_mount_volume() { | |
echo "Info: Attempting to mount the volume \`$volume\`" | |
echo "> docker-machine ssh $machine \"sudo mkdir -p $volume\"" | |
docker-machine ssh $machine "sudo mkdir -p $volume" | |
# create boot point | |
if [ $? -ne 0 ] ; then | |
echo "Error: Could not create the directory \`$volume\`" | |
exit 5 | |
fi | |
echo "[OK]" | |
# mount volume | |
local args="sudo mount -t vboxsf -o defaults,uid=\`id -u docker\`,gid=\`id -g docker\` $volume $volume" | |
echo "> docker-machine ssh $machine \"$args\"" | |
docker-machine ssh $machine "$args" | |
if [ $? -ne 0 ] ; then | |
echo "Error: Could not mount the volume \`$volume\`" | |
exit 5 | |
fi | |
echo "[OK]" | |
} | |
machine_unmount_volume() { | |
# if the the shared folder exists remove it | |
docker machine ssh "sudo ls -l $volume" > /dev/null 2>&1 | |
if [ $? -ne 1 ] ; then | |
return | |
fi | |
echo "Info: Attempting to remove the mount point \`$volume\`" | |
local args="sudo rm -rf $volume" | |
echo "> docker-machine ssh $machine $args" | |
docker-machine ssh $machine $args | |
if [ $? -ne 0 ] ; then | |
echo "Warning: Could not remove the mount point \`$volume\` properly" | |
fi | |
echo "[OK]" | |
} | |
machine_make_volume_bootable() { | |
echo "Info: Attempting to make the volume \`$volume\` automountable" | |
local dir='/var/lib/boot2docker' | |
docker-machine ssh $machine "sudo ls $dir" > /dev/null 2>&1 | |
if [ $? -ne 0 ] ; then | |
echo "Error: Could not make the \`$volume\` automountable," | |
echo "the expected \`$dir\` does not exist." | |
exit 1 | |
fi | |
local file="${dir}/bootlocal.sh" | |
# create the file if it does not exist | |
docker-machine ssh $machine "sudo ls $file" > /dev/null 2>&1 | |
if [ $? -ne 0 ] ; then | |
# create file | |
# make executable | |
# add she-bang | |
docker-machine ssh $machine "sudo touch $file" | |
docker-machine ssh $machine "sudo chmod +x $file" | |
docker-machine ssh $machine "echo \"#!/usr/bin/env sh\" | sudo tee $file" > /dev/null 2>&1 | |
fi | |
# only append if the entry does not already exist in the file | |
docker-machine ssh $machine "sudo cat $file | grep -E -i $volume" > /dev/null 2>&1 | |
if [ $? -ne 0 ] ; then | |
# set make mnt dir | |
# set mount <shared-folder> <mnt dir> | |
docker-machine ssh $machine "echo \"mkdir -p $volume\" | sudo tee -a $file" > /dev/null 2>&1 | |
docker-machine ssh $machine "echo \"mount -t vboxsf -o defaults,uid=\`id -u docker\`,gid=\`id -g docker\` $volume $volume\" | sudo tee -a $file" > /dev/null 2>&1 | |
fi | |
echo "[OK]" | |
echo "Info: \`$file\` configuration is the following:" | |
docker-machine ssh $machine "sudo cat $file" | |
echo "[OK]" | |
} | |
machine_unmake_volume_bootable() { | |
echo "Info: Attempting to unmake the volume \`$volume\` automountable" | |
local file="/var/lib/boot2docker/bootlocal.sh" | |
docker-machine ssh $machine "sudo ls $file" > /dev/null 2>&1 | |
if [ $? -ne 0 ] ; then | |
echo "Warning: the expected \`$file\` does not exist," | |
echo "> no startup entries for automount to remove". | |
echo "[OK]" | |
return | |
fi | |
local total=$(docker-machine ssh $machine "sudo cat $file | wc -l" | xargs) | |
local lines=$(docker-machine ssh $machine "sudo tail -n $(expr $total - 1) $file | grep -E -v $volume" | xargs) | |
# add she-bang | |
# add lines | |
docker-machine ssh $machine "echo \"#!/usr/bin/env sh\" | sudo tee $file" > /dev/null 2>&1 | |
docker-machine ssh $machine "echo \"$lines\" | sudo tee -a $file" > /dev/null 2>&1 | |
echo "[OK]" | |
docker-machine ssh $machine "sudo cat $file | grep -E -i '(mkdir|mount)" > /dev/null 2>&1 | |
if [ $? -eq 0 ] ; then | |
echo "Info: after the changes the configuration for the file \`$file\`," | |
echo "is the following:" | |
docker-machine ssh $machine "sudo cat $file" | |
else | |
docker-machine ssh $machine "sudo rm -f $file" | |
echo "Info: after the changes the configuration for the file \`$file\`," | |
echo "had no entries and was removed." | |
fi | |
echo "[OK]" | |
} | |
################################################################################ | |
# Virtualbox Helper Functions # | |
# # | |
################################################################################ | |
vbox_volume_exists() { | |
VBoxManage showvminfo $machine | grep $volume > /dev/null 2>&1 | |
if [ $? -eq 0 ] ; then | |
echo "Error: The shared folder \`$volume\` already exists on the docker machine," | |
echo "please unmount it first." | |
exit 1 | |
fi | |
} | |
vbox_volume_add() { | |
echo "Info: Attempting to add the volume \`$volume\` as a sharedfolder," | |
echo "to the docker machine \`$machine\`" | |
local args="--automount --name $volume --hostpath $volume" | |
echo "> VBoxManage sharedfolder add $machine $args" | |
VBoxManage sharedfolder add $machine $args | |
if [ $? -ne 0 ] ; then | |
log "Error: Failed to add the shared folder \`$volume\`." | |
exit 1 | |
fi | |
echo "[OK]" | |
} | |
vbox_volume_remove() { | |
echo "Info: Attempting to remove the volume \`$volume\` as sharedfolder," | |
echo "from the docker machine \`$machine\`" | |
VBoxManage showvminfo $machine | grep -E -i $volume > /dev/null 2>&1 | |
if [ $? -ne 0 ] ; then | |
echo "> no shared folder with name \`$volume\` to remove" | |
echo "[OK]" | |
return | |
fi | |
local args="--name $volume" | |
echo "> VBoxManage sharedfolder remove $machine $args" | |
VBoxManage sharedfolder remove $machine $args | |
if [ $? -ne 0 ] ; then | |
echo "Warning: could not remove the shared folder \`$volume\` properly" | |
fi | |
echo "[OK]" | |
} | |
################################################################################ | |
# Mount Section # | |
# # | |
################################################################################ | |
mount_print_help() { | |
cat <<EOF | |
Mount a disk as a shared folder to a docker machine. | |
Usage: mount [MACHINE] [VOLUME] | |
Arguments: | |
MACHINE The name of the machine to mount the volume path. | |
VOLUME The path to the volume to mount. | |
EOF | |
} | |
mount_parse_args() { | |
# ask for help | |
if [ "$1" = '-h' ] || [ "$1" = '--help' ] ; then | |
mount_print_help | |
exit 0 | |
fi | |
# too few arguments | |
if [ $# -lt 2 ] ; then | |
mount_print_help | |
exit 0 | |
fi | |
machine=$1 | |
volume=$(echo $2 | sed "s,/$,," | xargs) | |
} | |
mount_print_header() { | |
cat <<EOF | |
########################## | |
# MACHINE DISKUTIL MOUNT # | |
########################## | |
EOF | |
} | |
mount_run() { | |
machine_exists | |
volume_exists | |
vbox_volume_exists | |
machine_stop | |
vbox_volume_add | |
machine_start | |
machine_mount_volume | |
machine_make_volume_bootable | |
} | |
mount() { | |
mount_parse_args $@ | |
mount_print_header | |
mount_run | |
} | |
################################################################################ | |
# Unmount Section # | |
# # | |
################################################################################ | |
unmount_print_help() { | |
cat <<EOF | |
Unmount a disk that has been mounted as shared folder by this script. | |
Usage: unmount [MACHINE] [VOLUME] | |
Arguments: | |
MACHINE The name of the machine to unmount the volume path from. | |
VOLUME The path to the volume to unmount. | |
EOF | |
} | |
unmount_parse_args() { | |
if [ "$1" = '-h' ] || [ "$1" = '--help' ] ; then | |
unmount_print_help | |
exit 0 | |
fi | |
# too few arguments | |
if [ $# -lt 2 ] ; then | |
unmount_print_help | |
exit 0 | |
fi | |
machine=$1 | |
volume=$(echo $2 | sed "s,/$,," | xargs) | |
} | |
unmount_print_header() { | |
cat <<EOF | |
############################ | |
# MACHINE DISKUTIL UNMOUNT # | |
############################ | |
EOF | |
} | |
unmount_run() { | |
local restart=0 | |
machine_exists | |
docker-machine status $machine | grep -E -i 'running' > /dev/null 2>&1 | |
if [ $? -eq 0 ] ; then | |
restart=1 | |
machine_stop | |
fi | |
vbox_volume_remove | |
machine_start | |
machine_unmount_volume | |
machine_unmake_volume_bootable | |
if [ $restart -ne 1 ] ; then | |
machine_stop | |
fi | |
} | |
unmount() { | |
unmount_parse_args $@ | |
unmount_print_header | |
unmount_run | |
} | |
################################################################################ | |
# MAIN ENTRYPOINT # | |
# # | |
# 1. Parse command # | |
# 2. Run command # | |
# 2.1 Print help command if cmd equals 'help' # | |
# 2.2 Run the command if it's one of [build, tag, login, push] # | |
# 2.3 Print command not found if none of the above. # | |
# # | |
################################################################################ | |
main_print_help() { | |
cat<<EOF | |
Docker Machine Disk utitlity for mounting / unmounting shared folders. | |
Usage: | |
machine-diskutil [COMMAND] [ARGS....] | |
machine-diskutil -h|--help | |
Commands: | |
mount Mount a volume as a shared folder on the virtual machine. | |
unmount Unmount a shared folder from the virtual machine. | |
EOF | |
} | |
main_parse_command() { | |
if [ $# -eq 0 ] ; then | |
cmd='help' | |
return | |
fi | |
if [ "$1" = '-h' ] || [ "$1" = '--help' ] ; then | |
cmd='help' | |
return | |
fi | |
cmd=$1 | |
} | |
main_run_command() { | |
case $cmd in | |
help) | |
main_print_help | |
return | |
;; | |
mount|unmount) | |
;; | |
*) | |
main_print_cmd_not_found | |
exit 1 | |
;; | |
esac | |
check_deps | |
shift | |
$cmd $@ | |
} | |
main_parse_command $@ | |
main_run_command $@ |
my env
[wanghs@db2 machine-diskutil]$ docker version
Client:
Version: 1.11.1
API version: 1.23
Go version: go1.5.4
Git commit: 5604cbe
Built: Wed Apr 27 00:34:42 2016
OS/Arch: linux/amd64
Server:
Version: 1.11.1
API version: 1.23
Go version: go1.5.4
Git commit: 5604cbe
Built: Wed Apr 27 00:34:42 2016
OS/Arch: linux/amd64
[wanghs@db2 machine-diskutil]$ docker-machine version
docker-machine version 0.7.0, build a650a40
i am trying to use this wonderful shell to mount host folder into my container
[wanghs@db2 machine-diskutil]$ machine-diskutil.sh unmount registry /home/wanghs
############################
# MACHINE DISKUTIL UNMOUNT #
############################
Info: Attempting to stop the docker-machine `registry`.
> docker-machine stop registry
Stopping "registry"...
Machine "registry" was stopped.
[OK]
Info: Attempting to remove the volume `/home/wanghs` as sharedfolder,
from the docker machine `registry`
> VBoxManage sharedfolder remove registry --name /home/wanghs
VBoxManage: error: Could not find a shared folder named '/home/wanghs'
VBoxManage: error: Details: code VBOX_E_OBJECT_NOT_FOUND (0x80bb0001), component SessionMachine, interface IMachine, callee nsISupports
VBoxManage: error: Context: "RemoveSharedFolder(Bstr(name).raw())" at line 1086 of file VBoxManageMisc.cpp
[OK]
Info: Attempting to start the docker-machine `registry`.
> docker-machine start registry
Starting "registry"...
(registry) Check network to re-create if needed...
(registry) Waiting for an IP...
Machine "registry" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.
[OK]
Info: Attempting to remove the mount point `/home/wanghs`
> docker-machine ssh registry sudo rm -rf /home/wanghs
[OK]
Info: Attempting to unmake the volume `/home/wanghs` automountable
Warning: the expected `/var/lib/boot2docker/bootlocal.sh` does not exist,
> no startup entries for automount to remove.
[OK]
[wanghs@db2 machine-diskutil]$ machine-diskutil.sh mount registry /home/wanghs
##########################
# MACHINE DISKUTIL MOUNT #
##########################
Error: The shared folder `/home/wanghs` already exists on the docker machine,
please unmount it first.
[wanghs@db2 machine-diskutil]$ VBoxManage showvminfo registry
Name: registry
Groups: /
Guest OS: Linux 2.6 / 3.x / 4.x (64-bit)
UUID: 53b7ae31-07b1-441f-ac93-b4c8c4fefa9b
Config file: /home/wanghs/.docker/machine/machines/registry/registry/registry.vbox
Snapshot folder: /home/wanghs/.docker/machine/machines/registry/registry/Snapshots
Log folder: /home/wanghs/.docker/machine/machines/registry/registry/Logs
Hardware UUID: 53b7ae31-07b1-441f-ac93-b4c8c4fefa9b
Memory size: 1024MB
Page Fusion: off
VRAM size: 8MB
CPU exec cap: 100%
HPET: on
Chipset: piix3
Firmware: BIOS
Number of CPUs: 1
PAE: on
Long Mode: on
CPUID Portability Level: 0
CPUID overrides: None
Boot menu mode: disabled
Boot Device (1): DVD
Boot Device (2): DVD
Boot Device (3): HardDisk
Boot Device (4): Not Assigned
ACPI: on
IOAPIC: on
Time offset: 0ms
RTC: UTC
Hardw. virt.ext: on
Nested Paging: on
Large Pages: on
VT-x VPID: on
VT-x unr. exec.: on
Paravirt. Provider: Default
State: running (since 2016-04-29T07:59:01.601000000)
Monitor count: 1
3D Acceleration: off
2D Video Acceleration: off
Teleporter Enabled: off
Teleporter Port: 0
Teleporter Address:
Teleporter Password:
Tracing Enabled: off
Allow Tracing to Access VM: off
Tracing Configuration:
Autostart Enabled: off
Autostart Delay: 0
Default Frontend:
Storage Controller Name (0): SATA
Storage Controller Type (0): IntelAhci
Storage Controller Instance Number (0): 0
Storage Controller Max Port Count (0): 30
Storage Controller Port Count (0): 30
Storage Controller Bootable (0): on
SATA (0, 0): /home/wanghs/.docker/machine/machines/registry/boot2docker.iso (UUID: edcbe0d7-8f03-4323-a542-c4272709dfd6)
SATA (1, 0): /home/wanghs/.docker/machine/machines/registry/disk.vmdk (UUID: 370e9110-87ae-412f-94a8-220f4b2882e0)
NIC 1: MAC: 080027CAC041, Attachment: NAT, Cable connected: on, Trace: off (file: none), Type: 82540EM, Reported speed: 0 Mbps, Boot priority: 0, Promisc Policy: deny, Bandwidth group: none
NIC 1 Settings: MTU: 0, Socket (send: 64, receive: 64), TCP Window (send:64, receive: 64)
NIC 1 Rule(0): name = ssh, protocol = tcp, host ip = 127.0.0.1, host port = 40926, guest ip = , guest port = 22
NIC 2: MAC: 080027F57C3D, Attachment: Host-only Interface 'vboxnet0', Cable connected: on, Trace: off (file: none), Type: 82540EM, Reported speed: 0 Mbps, Boot priority: 0, Promisc Policy: deny, Bandwidth group: none
NIC 3: disabled
NIC 4: disabled
NIC 5: disabled
NIC 6: disabled
NIC 7: disabled
NIC 8: disabled
Pointing Device: PS/2 Mouse
Keyboard Device: PS/2 Keyboard
UART 1: disabled
UART 2: disabled
UART 3: disabled
UART 4: disabled
LPT 1: disabled
LPT 2: disabled
Audio: disabled
Clipboard Mode: disabled
Drag and drop Mode: disabled
Session name: headless
Video mode: 720x400x0 at 0,0 enabled
VRDE: disabled
USB: disabled
EHCI: disabled
XHCI: disabled
USB Device Filters:
<none>
Available remote USB devices:
<none>
Currently Attached USB Devices:
<none>
Bandwidth groups: <none>
Shared folders: <none>
VRDE Connection: not active
Clients so far: 0
Video capturing: not active
Capture screens: 0
Capture file: /home/wanghs/.docker/machine/machines/registry/registry/registry.webm
Capture dimensions: 1024x768
Capture rate: 512 kbps
Capture FPS: 25
Guest:
Configured memory balloon size: 0 MB
OS type: Linux26_64
Additions run level: 2
Additions version: 5.0.16 r105871
Guest Facilities:
Facility "VirtualBox Base Driver": active/running (last update: 2016/04/29 07:59:20 UTC)
Facility "VirtualBox System Service": active/running (last update: 2016/04/29 07:59:28 UTC)
Facility "Seamless Mode": not active (last update: 2016/04/29 07:59:20 UTC)
Facility "Graphics Mode": not active (last update: 2016/04/29 07:59:20 UTC)
[wanghs@db2 machine-diskutil]$ docker-machine ssh registry
## .
## ## ## ==
## ## ## ## ## ===
/"""""""""""""""""\___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\_______/
_ _ ____ _ _
| |__ ___ ___ | |_|___ \ __| | ___ ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__| < __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
Boot2Docker version 1.11.0, build HEAD : 32ee7e9 - Wed Apr 13 20:06:49 UTC 2016
Docker version 1.11.0, build 4dc5990
docker@registry:~$ cd /home/
docker@registry:/home$ ls
docker/
docker@registry:/home$
docker@registry:/home$
docker@registry:/home$
docker@registry:/home$ ls -al
total 0
drwxrwxr-x 3 root staff 60 Apr 29 07:59 ./
drwxr-xr-x 16 tc staff 400 Apr 29 07:59 ../
drwxr-sr-x 5 docker staff 160 Apr 29 08:00 docker/
docker@registry:/home$
@wanghaisheng sorry for not seeing this comment until now.
I guess it may have been something todo with your HD.
However at this point i would just recommend to use Docker for Mac where you don't need VirtualBox anymore.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
About
On OS X external disks HD, that are not mounted under the
/Users
path is not available from inside the docker-machine.So when you start up the docker-machine via the
docker run
command or throughdocker-compose
and link an external hd that is not available from under the/Users
path it will just be empty inside the docker-machine (symlinks do not work :/).It is possible to mount disk under the
/Users
folder, but it may depend on the disk how it was formatted and so on. e.g.This script is intended for the case when you can't mount the volume under the
/Users
path or if you want to mount/Volumes/hd-name
as it is onto the docker-machine.This script is based on the solution from this Stackoverflow thread
References:
Installing
This script is intended to mount/unmount external /Volumes on your Mac, so that they are accesible from you docker-machine(s) that are running inside Virtualbox.
Download this script some place on your machine and make sure it's executable e.g.
Mounting
Then you can mount your external volume e.g.:
Where:
machine-name
is the name of the docker-machine you want to mount the volume onto./Volumes/hd-name
is the full path of the external hd you want make available from the docker-machine.This will mount the external hd
/Volumes/hd-name
as a shared folder/Volumes/hd-name
in your Virtualbox docker machine.The external hd will be mounted with the same path it has on your machine. So that you can refer to it with it's canonical path e.g.
/Volumes/hd-name/some/path
using thedocker run
command or viadocker-compose
, this works as you would expect with any other path on your system that is under /User.Unmounting
If you want to unmount the
volume
you mounted run it with same arguments that you sent to the mount command e.g.:Where:
machine-name
is the name of the docker-machine you want to unmount the volume from./Volumes/hd-name
is the full path of external hd that you want remove from the docker-machine.