{"action":"created","issue":{"url":"https://api.github.com/repos/docker/machine/issues/179","labels_url":"https://api.github.com/repos/docker/machine/issues/179/labels{/name}","comments_url":"https://api.github.com/repos/docker/machine/issues/179/comments","events_url":"https://api.github.com/repos/docker/machine/issues/179/events","html_url":"https://github.com/docker/machine/issues/179","id":53144018,"number":179,"title":"Proposal: machine share","user":{"login":"nathanleclaire","id":1476820,"avatar_url":"https://avatars.githubusercontent.com/u/1476820?v=3","gravatar_id":"","url":"https://api.github.com/users/nathanleclaire","html_url":"https://github.com/nathanleclaire","followers_url":"https://api.github.com/users/nathanleclaire/followers","following_url":"https://api.github.com/users/nathanleclaire/following{/other_user}","gists_url":"https://api.github.com/users/nathanleclaire/gists{/gist_id}","starred_url":"https://api.github.com/users/nathanleclaire/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nathanleclaire/subscriptions","organizations_url":"https://api.github.com/users/nathanleclaire/orgs","repos_url":"https://api.github.com/users/nathanleclaire/repos","events_url":"https://api.github.com/users/nathanleclaire/events{/privacy}","received_events_url":"https://api.github.com/users/nathanleclaire/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":21,"created_at":"2014-12-30T20:22:54Z","updated_at":"2015-02-27T14:43:21Z","closed_at":null,"body":"# `machine share`\r\n\r\n## Abstract\r\n`machine` is shaping up to be an excellent tool for quickly and painlessly creating and managing Docker hosts across a variety of virtualization platforms and hosting providers.  For a variety of reasons, syncing files between the computer where `machine` commands are executed and the machines themselves is desirable.\r\n\r\n## Motivation\r\nContainers are a great tool and unit of deployment and machine makes creating a place to run your containers easier than ever.  There are, however, many reasons why one would want to share files which are not pre-baked into the Docker image from their `machine` client computer to a machine host.  Some examples are:\r\n\r\n1. The `machine` host is VM on the user's laptop and they are developing a web application inside of a container.  They want to develop with the source code bind-mounted inside of a container, but still edit on their computer using Sublime etc.\r\n2. The user wants to spin up 10 hosts in the cloud and do some scientific computing on them using Docker.  They have a container with, say, the Python libraries they need, but they also need to push their `.csv` files up to the hosts from their laptop.  This user does not know about the implementation details of `machine` or how to find the SSH keys for the hosts etc.\r\n3. There is some artifact of a build run on a machine (e.g. one or many compiled binaries) and the user wants to retrieve that artifact from the remote.\r\n\r\nLike the rest of `machine`, it would be preferable to have 80% of use cases where this sort of thing happens integrated seamlessly into the `machine` workflow, while still providing enough flexibility to users who fall into the 20% not covered by the most common use cases.\r\n\r\n## Interface\r\nAfter thinking about the mechanics and UX of this, I think we should favor explicitness over implicitness and err on the side of _not_ creating accidental or implicit shares.\r\n\r\nThere are a few aspects to the story that should be considered.\r\n\r\n### Command Line\r\n\r\nThe syntax would be something like this:\r\n\r\n```console\r\n$ pwd\r\n/Users/nathanleclaire/website\r\n\r\n$ machine ls\r\nNAME           ACTIVE   DRIVER         STATE     URL\r\nshareexample   *        digitalocean   Running   tcp://104.236.115.220:2376\r\n\r\n$ machine ssh -c pwd\r\n/root\r\n\r\n$ machine share --driver rsync . /root/code\r\nSharing /Users/nathanleclaire/website from this computer to /root/code on host \"shareexample\"....\r\n\r\n$ machine share ls\r\nMACHINE      DRIVER SRC                           DEST\r\nshareexample rsync  /Users/nathanleclaire/website /root/code\r\n\r\n$ ls\r\n\r\n$ echo foo >foo.txt\r\n\r\n$ ls \r\nfoo.txt\r\n\r\n$ machine ssh -c \"cat foo.txt\"\r\ncat: foo.txt: No such file or directory\r\nFATA[0001] exit status 1\r\n\r\n$ machine share push\r\n[INFO] Pushing to remote...\r\n\r\n$ machine ssh -c \"cat foo.txt\"\r\nfoo\r\n\r\n$ machine share --driver scp / /root/client_home_dir \r\nERR[0001] Sharing the home directory or folders outside of it is not allowed.  To override use --i-know-what-i-am-doing-i-swear\r\n```\r\n\r\nIMO we should forbid users from creating shares to or from outside of the home directory of the client _or_ the remote host.  There's a strong argument that the home directory itself should be banned from sharing as well, to prevent accidental sharing of files which should be moved around carefully such as `~/.ssh` and, of course, `~/.docker`.  Also, clients could share directories to multiple locations, but any shares which point to the same destination on the remote would be disallowed.\r\n\r\nTotally open to feedback and changes on the UI, this is just what I've come up with so far.\r\n\r\n### Drivers\r\n\r\nThere is a huge variety of ways to get files from point A to point B and back, so I'd propose a standard interface that drivers have to implement to be recognized as an option for sharing (just like we have done with virtualization / cloud platforms).  The default would be something like `scp` (since it is so simple and is pretty ubiquitous) and users would be able to manually specify one as well.  Users could pick the driver that suits their needs.  Additionally it would allow the `machine` team to start with a simpler core and move forward later e.g. just `rsync`, `scp`, and `vboxsf` could be the options in the v1.0 and then later other drivers could be added.\r\n\r\nSome possible drivers: `scp`, `vboxsf`, `fusionsf`, `rsync`, `sshfs`, `nfs`, `samba`\r\n\r\nThis would be useful because different use cases call for different ways of moving files around.  NFS might work well for development in a VM, but you might want `rsync` if you are pushing large files to the server frequently, and so on.\r\n\r\nPart of the interface for a share driver would be some sort of `IsContractFulfilled()` method which returns a boolean that indicates if the \"contract\" necessary for the share to work is fulfilled by both the client and remote host.  This would allow us to, for instance, check if `rsync` is installed on the client machine and the remote host, and refuse to create a share if that is not the case.  Likewise, it would prevent users from trying to do something silly like using the `vboxsf` driver on a non-Virtualbox host.\r\n\r\n## Possible Issues\r\n- If `machine` moves to a client-server model, which seems favored at the moment, it introduces additional complications to the implementation of `machine share`.  Namely, `machine share` would be all client-side logic, and would not be able to make the same assumptions it may make today e.g. that the SSH keys for the hosts are all lying around ready to be used on the client computer.\r\n- `machine share push` and `machine share pull` make a ton of sense for some drivers, such as `rsync`, but not so much sense for `vboxsf` or `nfs` which update automatically.  What happens when a user does `machine share push` on such a driver?  `\"ERR: This driver is bidirectional\"`?\r\n- This is likely to have a pretty big scope, so we might want to consider making it a separate tool or introducing some sort of model for extensions that could keep the core really lean.\r\n- How are symlinks handled?  Permissions?  What happens if you move, rename, or delete the shared directory on the client, or on the remote?\r\n\r\n## Other Notes\r\nI am not attached to the proposal, I am just looking for feedback and to see if anyone else thinks this would be useful.  I have put together some code which defines a tentative `ShareDriver` interface but it is not really to my liking (and no _real_ sync functionality is implemented) so I haven't shared it."},"comment":{"url":"https://api.github.com/repos/docker/machine/issues/comments/76404594","html_url":"https://github.com/docker/machine/issues/179#issuecomment-76404594","issue_url":"https://api.github.com/repos/docker/machine/issues/179","id":76404594,"user":{"login":"ehazlett","id":260642,"avatar_url":"https://avatars.githubusercontent.com/u/260642?v=3","gravatar_id":"","url":"https://api.github.com/users/ehazlett","html_url":"https://github.com/ehazlett","followers_url":"https://api.github.com/users/ehazlett/followers","following_url":"https://api.github.com/users/ehazlett/following{/other_user}","gists_url":"https://api.github.com/users/ehazlett/gists{/gist_id}","starred_url":"https://api.github.com/users/ehazlett/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ehazlett/subscriptions","organizations_url":"https://api.github.com/users/ehazlett/orgs","repos_url":"https://api.github.com/users/ehazlett/repos","events_url":"https://api.github.com/users/ehazlett/events{/privacy}","received_events_url":"https://api.github.com/users/ehazlett/received_events","type":"User","site_admin":false},"created_at":"2015-02-27T14:43:21Z","updated_at":"2015-02-27T14:43:21Z","body":"@jokeyrhyme the issue with fusion is known and is being worked on.  Thanks for the great feedback!"}}