├── README.md ├── bin └── d4m-nfs-start.sh ├── d4m-apk-cache └── .gitignore ├── d4m-nfs.sh ├── etc └── .gitignore ├── examples ├── d4m-nfs-mounts.txt ├── d4m-traditional.sh ├── d4m-with-nfs.sh ├── docker-compose-traditional.yml ├── docker-compose-with-nfs.yml └── img │ ├── d4m-default-file-sharing.png │ └── d4m-min-file-sharing.png └── install.sh /README.md: -------------------------------------------------------------------------------- 1 | # UPDATE: 2018-11-13 The Moby VM no longer allows NFS volumes but Docker for Mac now supports them. We are not longer using this project internally. If you are still using d4m-nfs, we suggest you migrate to this new method. We will leave this repository available in order for people to [get help with that](https://github.com/IFSight/d4m-nfs/issues/55#issuecomment-377884136). 2 | 3 | ## WARNING: Latest Docker for Mac 17.12.0-ce-mac46 seems to [break d4m-nfs](https://github.com/IFSight/d4m-nfs/issues/55). 4 | ## At this time, don't update if you rely on d4m-nfs. 5 | 6 | Downgrade at https://docs.docker.com/docker-for-mac/release-notes/#docker-community-edition-17120-ce-mac46-2018-01-09-stable - 17.09.1-ce-mac42 is the last known good version. 7 | 8 | See https://github.com/IFSight/d4m-nfs/issues/55 for the issues related to upgrading. 9 | 10 | ## d4m-nfs 11 | 12 | With the Docker for Mac's (D4M) current implementation of osxfs, depending on how read and write heavy containers are on mounted volumes, performance can be abismal. 13 | 14 | d4m-nfs blantently steals from the way that DockerRoot/xhyve used NFS mounts to get around i/o performance issues. With this implementation D4M appears to even outperform DockerRoot/xhyve under a full Drupal stack (mariadb/redis/php-fpm/nginx/varnish/haproxy), including persistent MySQL databases. 15 | 16 | The advantage of this over a file sync strategy is simpler, less overhead and not having to duplicate files. 17 | 18 | In order to make use of NFS, you will want to run ./d4m-nfs.sh before bringing up your containers, **please note this must be run via the bash shell and not the sh shell**. You will either need to change your volume paths to use /mnt, or configure the mounts in etc/d4m-nfs-mounts.txt. Look at the example directory for docker or docker-compose simple examples and an example d4m-nfs-mounts.txt. Please keep in mind that since NFS is the underlying glue that is this project, that all rules of NFS must be followed. Unlike Docker which creates the directory for you, if it doesn't exist, NFS needs it to exist. Since NFS and Docker have no idea of the other, it is up to you to create the skeleton directory structure for bootstrap. The way in which I often bootstrap is start up a stack normally without using NFS, use docker cp to get what the containers of docker had made, and then use that copied directory to map it via a Docker volume. 19 | 20 | By default, if the script doesn't find any other volumes bound to /mnt in your etc/d4m-nfs-mounts.txt, it will mount your home directory (eg. /Users/username) on /mnt to be exposed for the container. If you'd like to disable this, you may set the environment variable AUTO_MOUNT_HOME to false. 21 | 22 | Alpine Linux NFS packages are now cached so that d4m-nfs can be used when not online. In order for this to work, you must of run it once before while online. 23 | 24 | You can now specify what mounts you want in the d4m-nfs-mounts.txt file. Note that if you do this, you need to make sure that it does not conflict with D4M settings, in other words if you want to have /Users be served by NFS instead of osxfs you will need to remove it from the D4M Preferences -> File Sharing. The /tmp share must stay since that is how d4m-nfs exchanges information with the D4M Moby VM. 25 | 26 | This is the default file sharing: 27 | ![D4M Default File Sharing](/examples/img/d4m-default-file-sharing.png?raw=true "D4M Default File Sharing") 28 | 29 | Please make sure that /tmp is still shared: 30 | ![D4M Minimal File Sharing](/examples/img/d4m-min-file-sharing.png?raw=true "D4M Minimal File Sharing") 31 | 32 | Please note: 33 | * To connect to the D4M moby linux VM use: screen -r d4m 34 | * To disconnect from the D4M moby linux VM tty screen session use Ctrl-a d. 35 | * To run d4m-nfs faster and/or offline, leave the files in d4m-apk-cache and the hello-world image. 36 | * If you switch between D4M stable and beta, you might need to remove files in d4m-apk-cache and the hello-world image. 37 | 38 | # Opening Github Issues 39 | **Please keep in mind that everyone's environment is quite unique and this make helping people much harder. In that spirit when opening an issue, please provide the following:** 40 | 41 | 1. Comment out mounts from compose file and add them one at a time. Due to NFS, d4m-nfs cannot make the empty directory structure and will error. Read paragraphs above for more. 42 | 2. Please ensure you have looked at the "examples" directory in the root of this site. 43 | 3. include the text of the any approriate error message 44 | 4. screenshot of Docker for Mac's Preferences -> File Sharing 45 | 5. attachment of d4m-nfs/etc/d4m-nfs-mounts.txt 46 | 6. attachment of /tmp/d4m-mount-nfs.sh 47 | 7. attachment of /tmp/d4m-nfs-mounts.txt 48 | 8. attachment of /etc/exports 49 | 50 | ## Common Problem 51 | It appears as though a number of people are blindly copying the mounts from the preference in Docker for Mac to d4m-nfs/etc/d4m-nfs-mounts.txt. In doing this they end up having a /Volumes, /private and /Users mounts. If you are getting an error similar to the following, you might of done this: 52 | 53 | ``` 54 | ERROR: for applications Cannot start service applications: Mounts denied: r more info. 55 | ``` 56 | 57 | In all likelihood this is not what you want. The location /Volumes on a Mac is actually just a symlink to /, and it is never good to export a symlink. On top of that, with NFS, you can not export child directories which are on the same file system, and since both /Users and /private this could cause problems. You probably will need have to clean up your /etc/exports to remove all the lines from # d4m-nfs exports down. 58 | 59 | Please keep in mind that since NFS is the underlying glue that is this project, that all rules of NFS must be followed. Unlike Docker which creates the directory for you, if it doesn't exist, NFS needs it to exist. Since NFS and Docker have no idea of the other, it is up to you to create the skeleton directory structure for bootstrap. The way in which I often bootstrap is start up a stack normally without using NFS, use docker cp to get what the containers of docker had made, and then use that copied directory to map it via a Docker volume. 60 | 61 | You may also want to check on the latest file system changes that the Docker team is working on: https://blog.docker.com/2017/05/user-guided-caching-in-docker-for-mac/ 62 | 63 | 64 | # Use Stable Docker for Mac channel 65 | Currently d4m-nfs is known to work on the stable channel of 'Docker for Mac' both versions 1.12 and 1.13, we cannot guarantee how it will work on the beta channel of 'Docker for Mac'. Please use the stable channel of Docker for Mac https://docs.docker.com/docker-for-mac/ 66 | 67 | # Integration with text editors 68 | 69 | ## Sublime Text 70 | 71 | If you use Sublime, please checkout the plugin by Yves to help with auto reloads on file changes - https://github.com/yvess/sublime_d4m 72 | 73 | ## Atom 74 | 75 | The easiest way to enable auto reloading is to install [on-save](https://atom.io/packages/on-save) package and set it up with this config: 76 | 77 | ```json 78 | [ 79 | { 80 | "srcDir": ".", 81 | "files": "**/**", 82 | "command": "screen -S d4m -p 0 -X stuff \"touch \\\"`pwd`/${srcFile}\\\"\"\r" 83 | } 84 | ] 85 | ``` 86 | 87 | 88 | ## VS Code 89 | 90 | One of the possible solutions is to use [Save and Run](https://github.com/wk-j/vscode-save-and-run) extension with the following config: 91 | 92 | ```json 93 | "saveAndRun": { 94 | "commands": [ 95 | { 96 | "match": ".*", 97 | "cmd": "screen -S d4m -p 0 -X stuff \"touch \\\"${file}\\\"\n\r\"", 98 | "useShortcut": false, 99 | "silent": true 100 | } 101 | ] 102 | } 103 | ``` 104 | -------------------------------------------------------------------------------- /bin/d4m-nfs-start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | LIBDIR=$(cd "$(dirname "$0")" ; pwd -P) 4 | 5 | echo "[`date`][d4m-nfs] Waiting 30 seconds for the Docker VM to become ready" 6 | sleep 25 7 | echo "[`date`][d4m-nfs] Starting VM setup" 8 | 9 | echo "[`date`][d4m-nfs] Setup for Moby VM APK Cache." 10 | mkdir ${LIBDIR}/d4m-apk-cache 11 | 12 | # check that screen has not already been setup 13 | if ! $(screen -ls |grep d4m > /dev/null 2>&1); then 14 | 15 | until $(screen -ls |grep d4m > /dev/null 2>&1); do 16 | echo "[`date`][d4m-nfs] Setup 'screen' to work properly with the D4M tty, while at it name it 'd4m'." 17 | screen -AmdS d4m ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty 18 | sleep 5 19 | done 20 | 21 | rm -f ${LIBDIR}/d4m-done 22 | 23 | echo "[`date`][d4m-nfs] Runing Moby VM d4m-nfs setup script." 24 | screen -S d4m -p 0 -X stuff "sh ${LIBDIR}/d4m-mount-nfs.sh 25 | " 26 | echo -n "[`date`][d4m-nfs] Waiting until d4m-nfs setup is done." 27 | while [ ! -e ${LIBDIR}/d4m-done ]; do 28 | echo -n "." 29 | sleep .25 30 | done 31 | echo "" 32 | 33 | rm -f ${LIBDIR}/d4m-done 34 | fi 35 | 36 | echo "[`date`][d4m-nfs] Done." -------------------------------------------------------------------------------- /d4m-apk-cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /d4m-nfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | README=true 4 | 5 | while getopts ":q" opt; do 6 | case $opt in 7 | q) 8 | README=false 9 | ;; 10 | \?) 11 | echo "[d4m-nfs] Invalid option: -$OPTARG" >&2 12 | ;; 13 | esac 14 | done 15 | 16 | # check if this script is running under tmux, and if so, exit 17 | # tmux sets $TERM=screen or user sets $TERM=screen-256color 18 | # (under tmux, we are unable to attach to the d4m tty via screen) 19 | if { [[ "$TERM" =~ screen* ]] && [ -n "$TMUX" ]; } then 20 | echo "[d4m-nfs] This script cannot be run under tmux. Exiting." 21 | exit 1 22 | fi 23 | 24 | # env var to specify whether we want our home bound to /mnt 25 | AUTO_MOUNT_HOME=${AUTO_MOUNT_HOME:-true} 26 | 27 | # see if sudo is needed 28 | if ! $(sudo -n cat /dev/null > /dev/null 2>&1); then 29 | # get sudo first so the focus for the password is kept in the term, instead of Docker.app 30 | echo -e "[d4m-nfs] You will need to provide your Mac password in order to setup NFS." 31 | sudo cat /dev/null 32 | fi 33 | 34 | # check to see if Docker is already running 35 | if ! $(docker info > /dev/null 2>&1); then 36 | echo "[d4m-nfs] Opening Docker for Mac (D4M)." 37 | open -a /Applications/Docker.app 38 | fi 39 | 40 | # check if nfs conf line needs to be added 41 | NFSCNF="nfs.server.mount.require_resv_port = 0" 42 | if ! $(grep "$NFSCNF" /etc/nfs.conf > /dev/null 2>&1); then 43 | echo "[d4m-nfs] Set the NFS nfs.server.mount.require_resv_port value." 44 | echo -e "\nnfs.server.mount.require_resv_port = 0\n" | sudo tee -a /etc/nfs.conf 45 | fi 46 | 47 | SDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"&&pwd)" 48 | EXPORTS="# d4m-nfs exports\n" 49 | NFSUID=$(id -u) 50 | NFSGID=$(id -g) 51 | 52 | # iterate through the mounts in etc/d4m-nfs-mounts.txt to add exports 53 | if [ -e "${SDIR}/etc/d4m-nfs-mounts.txt" ]; then 54 | while read MOUNT; do 55 | if ! [[ "$MOUNT" = "#"* || "$MOUNT" =~ ^$ ]]; then 56 | if [[ "$(echo "$MOUNT" | cut -d: -f3)" != "" ]]; then 57 | NFSUID=$(echo "$MOUNT" | cut -d: -f3) 58 | fi 59 | 60 | if [[ "$(echo "$MOUNT" | cut -d: -f4)" != "" ]]; then 61 | NFSGID=$(echo "$MOUNT" | cut -d: -f4) 62 | fi 63 | 64 | NFSEXP="\"$(echo "$MOUNT" | cut -d: -f1)\" -alldirs -mapall=${NFSUID}:${NFSGID} localhost" 65 | 66 | if ! $(grep "$NFSEXP" /etc/exports > /dev/null 2>&1); then 67 | EXPORTS="$EXPORTS\n$NFSEXP" 68 | fi 69 | fi 70 | done < "${SDIR}/etc/d4m-nfs-mounts.txt" 71 | 72 | egrep -v '^#|^$' "${SDIR}/etc/d4m-nfs-mounts.txt" > /tmp/d4m-nfs-mounts.txt 73 | fi 74 | 75 | # if /Users is not in etc/d4m-nfs-mounts.txt then add /Users/$USER 76 | if [[ ! "$EXPORTS" == *'"/Users"'* && ! "$EXPORTS" == *"\"/Users/$USER"* ]]; then 77 | # make sure /Users is not in /etc/exports 78 | if ! $(egrep '^"/Users"' /etc/exports > /dev/null 2>&1); then 79 | NFSEXP="\"/Users/$USER\" -alldirs -mapall=$(id -u):$(id -g) localhost" 80 | 81 | if ! $(grep "/Users/$USER" /etc/exports > /dev/null 2>&1); then 82 | EXPORTS="$EXPORTS\n$NFSEXP" 83 | fi 84 | fi 85 | fi 86 | 87 | # only add if we have something to do 88 | if [ "$EXPORTS" != "# d4m-nfs exports\n" ]; then 89 | echo -e "$EXPORTS\n" | sudo tee -a /etc/exports 90 | fi 91 | 92 | # copy anything from the apk-cache into 93 | echo "[d4m-nfs] Copy the Moby VM APK Cache back." 94 | rm -rf /tmp/d4m-apk-cache 95 | cp -fr ${SDIR}/d4m-apk-cache/ /tmp/d4m-apk-cache 96 | 97 | # make sure /etc/exports is ok 98 | if ! $(nfsd checkexports); then 99 | echo "[d4m-nfs] Something is wrong with your /etc/exports file, please check it." >&2 100 | exit 1 101 | else 102 | echo "[d4m-nfs] Create the script for Moby VM." 103 | # make the script for the d4m side 104 | echo "ln -nsf /tmp/d4m-apk-cache /etc/apk/cache 105 | apk update 106 | apk add nfs-utils sntpc 107 | rpcbind -s > /dev/null 2>&1 108 | 109 | DEFGW=\$(ip route|awk '/default/{print \$3}') 110 | FSTAB=\"\\n\\n# d4m-nfs mounts\n\" 111 | 112 | if $AUTO_MOUNT_HOME && ! \$(grep ':/mnt' /tmp/d4m-nfs-mounts.txt > /dev/null 2>&1); then 113 | mkdir -p /mnt 114 | 115 | FSTAB=\"\${FSTAB}\${DEFGW}:/Users/${USER} /mnt nfs nolock,local_lock=all 0 0\" 116 | fi 117 | 118 | if [ -e /tmp/d4m-nfs-mounts.txt ]; then 119 | while read MOUNT; do 120 | DSTDIR=\$(echo \"\$MOUNT\" | cut -d: -f2) 121 | mkdir -p \${DSTDIR} 122 | FSTAB=\"\${FSTAB}\\n\${DEFGW}:\$(echo \"\$MOUNT\" | cut -d: -f1) \${DSTDIR} nfs nolock,local_lock=all 0 0\" 123 | done < /tmp/d4m-nfs-mounts.txt 124 | fi 125 | 126 | if ! \$(grep \"d4m-nfs mounts\" /etc/fstab > /dev/null 2>&1); then 127 | echo "adding d4m nfs config to /etc/fstab:" 128 | echo -e \$FSTAB | tee /etc/fstab 129 | else 130 | echo "d4m nfs mounts already exist in /etc/fstab" 131 | fi 132 | 133 | sntpc -i 10 \${DEFGW} & 134 | 135 | sleep .5 136 | mount -a 137 | touch /tmp/d4m-done 138 | " > /tmp/d4m-mount-nfs.sh 139 | 140 | echo -e "[d4m-nfs] Start and restop nfsd, for some reason restart is not as kind." 141 | sudo killall -9 nfsd ; sudo nfsd start 142 | 143 | echo -n "[d4m-nfs] Wait until NFS is setup." 144 | while ! rpcinfo -u localhost nfs > /dev/null 2>&1; do 145 | echo -n "." 146 | sleep .25 147 | done 148 | 149 | echo -ne "\n[d4m-nfs] Wait until D4M is running." 150 | # while ! $(ps auxwww|grep docker|grep vmstateevent |grep '"vmstate":"running"' > /dev/null 2>&1); do 151 | while ! $(docker run --rm hello-world > /dev/null 2>&1); do 152 | echo -n "." 153 | sleep .25 154 | done 155 | echo "" 156 | 157 | # check that screen has not already been setup 158 | if ! $(screen -ls |grep d4m > /dev/null 2>&1); then 159 | echo "[d4m-nfs] Setup 'screen' to work properly with the D4M tty, while at it name it 'd4m'." 160 | screen -AmdS d4m ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty 161 | 162 | echo "[d4m-nfs] Run Moby VM d4m-nfs setup script." 163 | screen -S d4m -p 0 -X stuff "sh /tmp/d4m-mount-nfs.sh 164 | " 165 | 166 | echo -n "[d4m-nfs] Waiting until d4m-nfs setup is done." 167 | while [ ! -e /tmp/d4m-done ]; do 168 | echo -n "." 169 | sleep .25 170 | done 171 | echo "" 172 | 173 | rm /tmp/d4m-done 174 | fi 175 | 176 | echo -e "[d4m-nfs] Copy back the APK cache.\n" 177 | cp -f /tmp/d4m-apk-cache/* ${SDIR}/d4m-apk-cache/ 178 | 179 | echo "" 180 | 181 | if [ $README = true ]; then 182 | cat ${SDIR}/README.md 183 | fi 184 | fi 185 | -------------------------------------------------------------------------------- /etc/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /examples/d4m-nfs-mounts.txt: -------------------------------------------------------------------------------- 1 | # Be sure that any mounts that have been added here 2 | # have been removed from Docker for Mac -> Preferences -> File Sharing 3 | # 4 | # You must supply the Mac source directory and Moby VM destination directory, 5 | # and optionally add on user/group mapping: 6 | # 7 | # https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man5/exports.5.html 8 | # 9 | # :[:MAC_UID_MAP][:MAC_GID_MAP] 10 | # 11 | #/Users/MYUSERNAME:/mnt:0:0 12 | -------------------------------------------------------------------------------- /examples/d4m-traditional.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | 5 | docker run \ 6 | --name d4m-tradtional \ 7 | --detach=true \ 8 | --volume=/Users/$USER/www:/usr/share/nginx/html \ 9 | nginx:mainline-alpine 10 | -------------------------------------------------------------------------------- /examples/d4m-with-nfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ../d4m-nfs.sh 4 | 5 | docker run \ 6 | --name d4m-with-nfs \ 7 | --detach=true \ 8 | --volume=/mnt/www:/usr/share/nginx/html \ 9 | nginx:mainline-alpine 10 | -------------------------------------------------------------------------------- /examples/docker-compose-traditional.yml: -------------------------------------------------------------------------------- 1 | # 2 | 3 | d4m-tradtional: 4 | container_name: d4m-tradtional 5 | image: nginx:mainline-alpine 6 | volumes: 7 | - /Users/$USER/www:/usr/share/nginx/html 8 | -------------------------------------------------------------------------------- /examples/docker-compose-with-nfs.yml: -------------------------------------------------------------------------------- 1 | # ../d4m-nfs.sh && docker-compose --file docker-compose-with-nfs.yml 2 | 3 | d4m-tradtional: 4 | container_name: d4m-with-nfs 5 | image: nginx:mainline-alpine 6 | volumes: 7 | - /mnt/www:/usr/share/nginx/html 8 | -------------------------------------------------------------------------------- /examples/img/d4m-default-file-sharing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mineshaftgap/d4m-nfs/a188ea08de63b12fb84fcd67ca9641c0f6f57724/examples/img/d4m-default-file-sharing.png -------------------------------------------------------------------------------- /examples/img/d4m-min-file-sharing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mineshaftgap/d4m-nfs/a188ea08de63b12fb84fcd67ca9641c0f6f57724/examples/img/d4m-min-file-sharing.png -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # env var to specify whether we want our home bound to /mnt 4 | AUTO_MOUNT_HOME=${AUTO_MOUNT_HOME:-true} 5 | 6 | # see if sudo is needed 7 | if ! $(sudo -n cat /dev/null > /dev/null 2>&1); then 8 | # get sudo first so the focus for the password is kept in the term, instead of Docker.app 9 | echo -e "[d4m-nfs] You will need to provide your Mac password in order to setup NFS." 10 | sudo cat /dev/null 11 | fi 12 | 13 | # check if nfs conf line needs to be added 14 | NFSCNF="nfs.server.mount.require_resv_port = 0" 15 | if ! $(grep "$NFSCNF" /etc/nfs.conf > /dev/null 2>&1); then 16 | echo "[d4m-nfs] Set the NFS nfs.server.mount.require_resv_port value." 17 | echo -e "\nnfs.server.mount.require_resv_port = 0\n" | sudo tee -a /etc/nfs.conf 18 | fi 19 | 20 | SDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"&&pwd)" 21 | EXPORTS="# d4m-nfs exports\n" 22 | NFSUID=$(id -u) 23 | NFSGID=$(id -g) 24 | 25 | LIBDIR=/opt/d4m-nfs 26 | sudo mkdir -p $LIBDIR 27 | sudo chown $USER $LIBDIR 28 | chmod 755 $LIBDIR 29 | 30 | # iterate through the mounts in etc/d4m-nfs-mounts.txt to add exports 31 | if [ -e "${SDIR}/etc/d4m-nfs-mounts.txt" ]; then 32 | while read MOUNT; do 33 | if ! [[ "$MOUNT" = "#"* ]]; then 34 | if [[ "$(echo "$MOUNT" | cut -d: -f3)" != "" ]]; then 35 | NFSUID=$(echo "$MOUNT" | cut -d: -f3) 36 | fi 37 | 38 | if [[ "$(echo "$MOUNT" | cut -d: -f4)" != "" ]]; then 39 | NFSGID=$(echo "$MOUNT" | cut -d: -f4) 40 | fi 41 | 42 | NFSEXP="\"$(echo "$MOUNT" | cut -d: -f1)\" -alldirs -mapall=${NFSUID}:${NFSGID} localhost" 43 | 44 | if ! $(grep "$NFSEXP" /etc/exports > /dev/null 2>&1); then 45 | EXPORTS="$EXPORTS\n$NFSEXP" 46 | fi 47 | fi 48 | done < "${SDIR}/etc/d4m-nfs-mounts.txt" 49 | 50 | egrep -v '^#' "${SDIR}/etc/d4m-nfs-mounts.txt" > ${LIBDIR}/d4m-nfs-mounts.txt 51 | fi 52 | 53 | # if /Users is not in etc/d4m-nfs-mounts.txt then add /Users/$USER 54 | if [[ ! "$EXPORTS" == *'"/Users"'* && ! "$EXPORTS" == *"\"/Users/$USER"* ]]; then 55 | # make sure /Users is not in /etc/exports 56 | if ! $(egrep '^"/Users"' /etc/exports > /dev/null 2>&1); then 57 | NFSEXP="\"/Users/$USER\" -alldirs -mapall=$(id -u):$(id -g) localhost" 58 | 59 | if ! $(grep "/Users/$USER" /etc/exports > /dev/null 2>&1); then 60 | EXPORTS="$EXPORTS\n$NFSEXP" 61 | fi 62 | fi 63 | fi 64 | 65 | # only add if we have something to do 66 | if [ "$EXPORTS" != "# d4m-nfs exports\n" ]; then 67 | echo -e "$EXPORTS\n" | sudo tee -a /etc/exports 68 | fi 69 | 70 | # make sure /etc/exports is ok 71 | if ! $(nfsd checkexports); then 72 | echo "[d4m-nfs] Something is wrong with your /etc/exports file, please check it." >&2 73 | exit 1 74 | else 75 | echo "[d4m-nfs] Create the script for Moby VM." 76 | # make the script for the d4m side 77 | echo "#!/bin/sh 78 | ln -nsf ${LIBDIR}/d4m-apk-cache /etc/apk/cache 79 | apk update 80 | apk add nfs-utils sntpc 81 | rpcbind -s > /dev/null 2>&1 82 | 83 | DEFGW=\$(ip route|awk '/default/{print \$3}') 84 | FSTAB=\"\\n\\n# d4m-nfs mounts\n\" 85 | 86 | if $AUTO_MOUNT_HOME && ! \$(grep ':/mnt' ${LIBDIR}/d4m-nfs-mounts.txt > /dev/null 2>&1); then 87 | mkdir -p /mnt 88 | 89 | FSTAB=\"\${FSTAB}\${DEFGW}:/Users/${USER} /mnt nfs nolock,local_lock=all 0 0\" 90 | fi 91 | 92 | if [ -e ${LIBDIR}/d4m-nfs-mounts.txt ]; then 93 | while read MOUNT; do 94 | DSTDIR=\$(echo \"\$MOUNT\" | cut -d: -f2) 95 | mkdir -p \${DSTDIR} 96 | FSTAB=\"\${FSTAB}\\n\${DEFGW}:\$(echo \"\$MOUNT\" | cut -d: -f1) \${DSTDIR} nfs nolock,local_lock=all 0 0\" 97 | done < ${LIBDIR}/d4m-nfs-mounts.txt 98 | fi 99 | 100 | if ! \$(grep \"d4m-nfs mounts\" /etc/fstab > /dev/null 2>&1); then 101 | echo "adding d4m nfs config to /etc/fstab:" 102 | echo -e \$FSTAB | tee /etc/fstab 103 | else 104 | echo "d4m nfs mounts already exist in /etc/fstab" 105 | fi 106 | 107 | sntpc -i 10 \${DEFGW} & 108 | 109 | sleep .5 110 | mount -a 111 | touch ${LIBDIR}/d4m-done 112 | " > ${LIBDIR}/d4m-mount-nfs.sh 113 | chmod +x ${LIBDIR}/d4m-mount-nfs.sh 114 | 115 | echo -e "[d4m-nfs] Start and restop nfsd, for some reason restart is not as kind." 116 | sudo killall -9 nfsd ; sudo nfsd start 117 | 118 | echo -n "[d4m-nfs] Wait until NFS is setup." 119 | while ! rpcinfo -u localhost nfs > /dev/null 2>&1; do 120 | echo -n "." 121 | sleep .25 122 | done 123 | fi 124 | 125 | cp ${SDIR}/bin/d4m-nfs-start.sh ${LIBDIR}/ 126 | 127 | cat > ~/Library/LaunchAgents/com.ifsight.d4m-nfs.plist < 129 | 130 | 131 | 132 | Label 133 | com.ifsight.d4m-nfs 134 | RunAtLoad 135 | 136 | WatchPaths 137 | 138 | ${HOME}/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty 139 | 140 | StandardOutPath 141 | ${LIBDIR}/launchd.log 142 | Program 143 | ${LIBDIR}/d4m-nfs-start.sh 144 | EnvironmentVariables 145 | 146 | PATH 147 | /bin:/usr/bin:/usr/local/bin 148 | 149 | 150 | 151 | EOF 152 | 153 | launchctl load -w ~/Library/LaunchAgents/com.ifsight.d4m-nfs.plist 154 | --------------------------------------------------------------------------------