Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Windows #4

Open
matthieudelaro opened this issue Apr 18, 2016 · 20 comments
Open

Add support for Windows #4

matthieudelaro opened this issue Apr 18, 2016 · 20 comments

Comments

@matthieudelaro
Copy link
Owner

Their is one short platform dependent file to implement in module github.com/fgrehm/go-dockerpty : term_PLATFORM.go

Probably some other modifications, especially when filepath.Join is called: since it will be compiled for Windows, but targets container path (linux) half the time, errors are to be expected.

@matthieudelaro
Copy link
Owner Author

matthieudelaro commented Apr 28, 2016

I forked and updated github.com/fgrehm/go-dockerpty in github.com/matthieudelaro/go-dockerpty (see PR).
Nut branch supportwindows now uses the fork, so it compiles for Windows properly. Does anyone have a Windows 10 + Docker for Windows running to give it a try?

I also added https transport so that it can be tested against Docker Toolbox on Windows, but I doubt it will work since attach fails with Docker Toolbox on OSX.

@matthieudelaro matthieudelaro mentioned this issue May 4, 2016
@matthieudelaro
Copy link
Owner Author

matthieudelaro commented May 4, 2016

Here is how to test Nut with Docker for Windows, on Windows 10:

Move to branch supportwindows

# Build Nut for Windows, in a container
    docker run -i -t --rm -v $PWD:/go/src/github.com/matthieudelaro/nut -w /go/src/github.com/matthieudelaro/nut golang:1.6 env GOOS=windows GOARCH=amd64 go build -o nut

Expected bugs:

  • Nut uses filepath packages to build paths of volumes to mount in the container, and to set up the working directory. On Windows, those path should look like C:\some\path, whereas those should be given to the container as /some/path.
  • so far, Docker for Windows does not support volumes, so Nut can't mount volumes for the project

Here is how to test Nut with Docker Toolbox, on Windows:

Move to branch supportwindows

# Build Nut for Windows, in a container
    docker run -i -t --rm -v $PWD:/go/src/github.com/matthieudelaro/nut -w /go/src/github.com/matthieudelaro/nut golang:1.6 env GOOS=windows GOARCH=amd64 go build -o nut

Nut should be able to connect to Docker daemon using Docker Machine variables, pull images automatically, and start container. But:
Expected bug:

  • as with Docker for Windows, there should be the bug of filepath
  • as with Docker Toolbox on OSX, there should be a bug to attach to the container (see Add support for Docker Toolbox #5)
  • there should also be the bug of GUI, maybe for the same reason

Fix filepath

I think that a fix is to create some containerFilePath package, which behaves as provides same features as path/filepath package (filepath.Abs(), filepath.Join(), filepath.Base(), filepath.Dir()), but always with proper paths for linux, even when compiled on Windows.

Fix attach

First make sure where the issues comes from. I think it comes from fsouza/go-dockerclient#126 (Nut uses this library to connect to Docker Daemon). If so, then good fix is to help fix go-dockerclient.

@matthieudelaro
Copy link
Owner Author

The source code of path/filepath is available here : https://golang.org/src/path/filepath/
I think we can copy/paste the code dedicated to linux into a subpackage of nut, called nut/filepathLinux. Then, in the source of Nut, use nut/filepathLinux instead of path/filepath when it comes to paths for the container, and keep using path/filepath when it comes to paths for the host.

@matthieudelaro
Copy link
Owner Author

matthieudelaro commented May 14, 2016

Nut compiles and partially runs on Windows! Since Nut supports Docker Toolbox on OSX, it also got closer to supporting Docker Toolbox on Windows.

What works

  • parse configuration
  • init project
  • load configuration from Github
  • pull docker image

What fails

  • start and attach to container fails: “the parameter is incorrect”, even when there isn't any directory to mount in the container, and no working directory is specified.

(tested on Docker Toolbox, Windows 7)

Branch supportwindows has been merged into master, to leverage the support of connection over HTTPS on all platforms. So testing on Windows doesn't require to checkout anymore:

git clone https://github.com/matthieudelaro/nut.git —recursive
cd nut
docker run -i -t --rm -v $PWD:/go/src/github.com/matthieudelaro/nut -w /go/src/github.com/matthieudelaro/nut golang:1.6 env GOOS=windows GOARCH=amd64 go build -o nut
./nut --exec="echo hello world" 

@ctaggart
Copy link

ctaggart commented May 17, 2016

I'm able to compile it on Windows using the master branch. Using PowerShell, I adjusted the above command by using ${PWD} and setting the output to nut.exe.

docker run -i -t --rm -v ${PWD}:/go/src/github.com/matthieudelaro/nut -w /go/src/github.com/matthieudelaro/nut golang:1.6 env GOOS=windows GOARCH=amd64 go build -o nut.exe
PS C:\Users\cameron\go\src\github.com\matthieudelaro\nut> .\nut.exe
NAME:
   nut - the development environment, containerized

USAGE:
   C:\Users\cameron\go\src\github.com\matthieudelaro\nut\nut.exe [global options] command [command options] [arguments...]

VERSION:
   0.1.2 dev

COMMANDS:
   build                macro: build the project
   build-all, ba        macro: build the project for linux, OSX, and for Windows
   build-linux, bl      macro: build the project for Linux
   build-osx, bo        macro: build the project for OSX
   build-windows, bw    macro: build the project for Windows
   code                 macro: open this project in vscode
   run                  macro: run the project in the container
   test                 macro: test the project
   help, h              Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --clean              clean all data stored in .nut
   --init               initialize a nut project
   --github             Use with --init: provide a GitHub repository to initialize Nut.
   --logs               Use with --exec: display log messages. Useful for contributors and to report an issue
   --exec               execute a command in a container.
   --help, -h           show help
   --version, -v        print the version

That looks good. However, trying out this throws an error:

PS C:\Users\cameron\go\src\github.com\matthieudelaro\nut> .\nut.exe --exec="echo hello world"
Could not inspect image golang:1.6 : Get http://unix.sock/images/golang:1.6/json: dial unix /var/run/docker.sock: socket: An a
ddress incompatible with the requested protocol was used.
Pulling image...
time="2016-05-17T11:58:43-07:00" level=error msg="Could not pull image golang:1.6: dial unix /var/run/docker.sock: socket: An
address incompatible with the requested protocol was used."

I have the latest Docker for Windows 1.11.1-beta11 installed.

@matthieudelaro
Copy link
Owner Author

Thanks for the test with Docker for Windows!

I assume that you don't get this issue with Docker Toolbox, right? It looks like it comes from here : https://github.com/matthieudelaro/nut/blob/master/network.go#L44
In case $DOCKER_HOST environment variable is not defined, Nut assumes that you are not using Toolbox/Docker Machine, so it contacts docker host via docker socket. Which seems not to be addressable with unix:///var/run/docker.sock on Windows.

However, according to this post, on Windows we can mount docker socket, just like on linux, with docker run -v /var/run/docker.sock:/var/run/docker.sock, so there must be a way to use this file as host socket.

On OSX, when Docker for Mac is off, I get this error message:

Could not inspect image golang:1.6 : cannot connect to Docker endpoint
# which differs from your error on Windows:
Could not inspect image golang:1.6 : Get http://unix.sock/images/golang:1.6/json: dial unix /var/run/docker.sock: socket: An address incompatible with the requested protocol was used.

"incompatible with the requested protocol"... Maybe removing unix:/// would be worth a try? Also, I don't know what kind of socket is used in Docker for Windows, but probably not a pure unix socket. So maybe there is something to change here...

@RnbWd
Copy link

RnbWd commented May 18, 2016

anyone with windows and node installed willing to try this command to see if it works?

npm install -g nut-bin

haven't tested it on windows yet

it should automatically put a pre-build binary of nut in the path without needing to run docker commands and compile locally. But I'm not sure if I need to modify it by adding .exe - or if that happens automatically. Based on @ctaggart 's fix I might need to include that file extension for windows

@matthieudelaro
Copy link
Owner Author

@RnbWd : I tried npm on Windows 10, which encounters issues in the installation process:
image

I also tried to compile and run nut on Windows 10, with Docker Toolbox:

  • pulled with git on windows
  • build on windows
  • run in Git Bash, and in Command Prompt:
    image

With Git Bash

The first issue in Git Bash on my installation is that docker run yields the following bug: docker-archive/toolbox#136. As a result, I'm not sure I can expect Nut to work either. So I tested in Command Prompt:

With Command Prompt

docker run works properly in this environment. The error message for Nut changes: it is not the handle which is incorrect, but the parameter.
I can't explain why the error log doesn't format \n properly. I know there can be issues with new line characters in files when transferred from Unix world to Windows, but I think Git is has got a feature to do the translation. And anyway it is not really a new line, so... Could this weird behavior also affect the formatting of http request? Because there are only minimal parameters here.

@RnbWd
Copy link

RnbWd commented May 25, 2016

oh, there's ways to normalize the paths between linux / windows, and I always see windows files ending in .exe - right now it's like this:

module.exports = new BinWrapper()
  .src(BASE + 'osx/nut', 'darwin')
  .src(BASE + 'linux/nut',  'linux', 'x64')
  .src(BASE + 'windows/nut', 'win32', 'x64')
  .dest(path.join(__dirname, '../vendor'))
  .use('nut')

It's using the default path module, so that might need be normalized with windows (it's easy just requires a special fs package). And I probably need to add this line at the end:

.use(process.platform === 'win32' ? 'vault.exe' : 'vault');

so I can rename the file? or maybe it's a global npm permission thing? I assume it needs .exe, but I don't know windows that well.

@matthieudelaro
Copy link
Owner Author

I don't know either :(

@RnbWd
Copy link

RnbWd commented May 26, 2016

I'll assume yes... - but i'll start up a windows vm (or maybe window IOT for raspi) - or just try building it instead of linking a binary. I'm certain this is possible

@matthieudelaro
Copy link
Owner Author

Ok. It's not trivial to get a VM which can do emulation, so I created a Windows 10 VM in Virtual Box, which connects to the docker VM (both VM are running on the same host). Here is the recipe to connect them:

prepare VMs

  • go to VM of docker (default) -> Settings -> Network -> Adapter 2 -> Promiscuous Mode : set to Allow VMs
  • go to Windows VM -> Settings -> Network. Set Attached to = Host-Only Adapter, Name = vboxnet0, promiscuous mode: Allow All
  • verify that Windows VM can ping docker VM

copy-paste certificates from osx to windows

  • from /Users/matthieudelaro/.docker/machine/machines/default
    • you may have to add read permissions to the files
    • don't copy neither id_rsa nor id_rsa.pub
  • to C:\Users\matthieudelaro.docker\machine\machines\vbox

set docker machine environment variables

# open cmd (not git terminal. See Note)
# for CMD
set DOCKER_HOST=tcp://192.168.99.100:2376
set DOCKER_TLS_VERIFY=1
set DOCKER_TOOLBOX_INSTALL_PATH=C:\Program Files\Docker Toolbox
set DOCKER_CERT_PATH=C:\Users\matthieudelaro\.docker\machine\machines\vbox

# for Git Bash
export DOCKER_HOST=tcp://192.168.99.100:2376
export DOCKER_TLS_VERIFY=1
export DOCKER_TOOLBOX_INSTALL_PATH="/C/Program Files/Docker Toolbox"
export DOCKER_CERT_PATH=/C/Users/matthieudelaro/.docker/machine/machines/vbox

test docker

docker run -it --rm golang /bin/bash  # you are in !

Note

In case of error "cannot enable tty mode on non tty input", see docker-archive/toolbox#136

If you need to troubleshoot the connection: Windows 10 VM won't answer ping from Docker VM, but Docker VM answers ping from Windows 10 VM.

If this works properly for you as well, I may write a blog post for this, or add it to the wiki for contributors.

@RnbWd
Copy link

RnbWd commented May 27, 2016

Okay I'll try this out - and my roommate has a windows machine too.. not sure if I can use the same code to get docker native but if virtual machine doesn't work I'll try his computer. (at my last job, we had to use windows for a printer driver, and our VM's were faster than the 'cheap windows laptop' we tried using initially. - the bindings for docker could be weird? But I know that the npm binary installation works (I relied on that heavily in the past)

edit: formatted with .exe - not the exact code up right now but one line different.

@matthieudelaro
Copy link
Owner Author

not sure if I can use the same code to get docker native

Not sure it answers your question, but my recipe doesn't make use of Docker for Windows. It uses Docker Toolbox.

matthieudelaro added a commit that referenced this issue May 28, 2016
#4)

On unix, nut uses docker api to connect to docker host. But one can ask nut to call docker cli by using the flag --dockercli.

On Windows, docker cli is used by default. But one can revert to docker api using flag --dockerapi
@matthieudelaro
Copy link
Owner Author

TL;DR: Nut v0.1.3 supports Windows 🎉

Here is a call to top with Nut:
screen shot 2016-05-29 at 02 53 51

Details

So far Nut used to call docker api directly, without using docker cli at all. Now there is a flag --dockercli to force Nut to use docker cli instead of using docker api itself. On Windows, this flag is ON by default.

I tested this in CMD on Windows 10, in a VM reaching another VM running boot2docker. I had issues in Git Bash (due to an issue of docker toolbox in this environment, under some circumstances: docker-archive/toolbox#136)

@RnbWd : I updated the manual build. For Windows, there are both nut and nut.exe, in case it's useful for npm.

@RnbWd
Copy link

RnbWd commented Jun 2, 2016

sorry i was out of town I'll update it and test it on my roommates windows machine as well

@masaeedu
Copy link

Are GUI applications not supported on Windows yet? There's a workflow for running containerized GUI apps on Windows 10 that goes like this:

  • Start X Server (XMingW or Cygwin/X), with access control disabled and TCP transport. E.g. for Cygwin/X, you'd use:

    XWin :0 -multiwindow -clipboard -wgl -ac -listen tcp
    
  • Start some container with the DISPLAY env var set to <docker NAT IP address>:0. E.g. if you're in PowerShell, you can add the following to your docker run invocation:

    -e DISPLAY=$(Get-NetIPAddress | ? { $_.InterfaceAlias -like '*docker*' -and $_.AddressFamily -eq 'IPv4' } | % { $_.IPAddress }):0
    

I have a bunch of scripts for this in my profile, but I was hoping there's some nice tool that encapsulates this stuff.

@matthieudelaro
Copy link
Owner Author

Hello @masaeedu ,

You're right, it's not implemented yet. This feature is implemented for OSX and for other unix systems in platform depend files.

The OSX version implements a workflow similar to the one you describe, in just a few lines. As for windows version, I never had the chance to dev Nut on a proper Windows installation, but I'm pretty sure that you could implement it quickly, using the other versions as an example. I think that this section of the wiki will help you. Hoping to see your PR soon :)

@masaeedu
Copy link

masaeedu commented Nov 21, 2016

@matthieudelaro Alright then. What should be the strategy for installing X? Do you just expect it to be on the machine or install it yourself?

@matthieudelaro
Copy link
Owner Author

Great :)

For OSX, I assumed that it was already installed. But I didn't make any assumption about the configuration of X, so that it should work with any install.

So you could do the same, and simply provide instructions to install X on Windows. I don't feel confortable about forcing users to use a specific implementation of X. (However it may be required for you method, and in this case it should be explained in the instructions to use the feature on Windows.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants