Skip to content
This repository was archived by the owner on Apr 28, 2020. It is now read-only.

Commit 090e180

Browse files
committed
Add fast support for macOS
Updates #52 Still no good support for multi user systems but I think that's fine for now.
1 parent e4aef86 commit 090e180

File tree

4 files changed

+45
-13
lines changed

4 files changed

+45
-13
lines changed

codeserver.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ package main
33
import (
44
"context"
55
"io"
6+
"net"
67
"net/http"
78
"os"
9+
"os/exec"
810
"path/filepath"
11+
"runtime"
912
"strings"
1013
"time"
1114

@@ -82,6 +85,25 @@ func codeServerPort(cntName string) (string, error) {
8285
)
8386

8487
for ctx.Err() == nil {
88+
if runtime.GOOS == "darwin" {
89+
// macOS uses port forwarding instead of host networking so netstat stuff below will not work
90+
// as it will find the port inside the container, which we already know is 8443.
91+
cmd := exec.CommandContext(ctx, "docker", "port", cntName, "8443")
92+
var out []byte
93+
out, err = cmd.CombinedOutput()
94+
if err != nil {
95+
continue
96+
}
97+
98+
addr := strings.TrimSpace(string(out))
99+
_, port, err = net.SplitHostPort(addr)
100+
if err != nil {
101+
return "", xerrors.Errorf("invalid address from docker port: %q", string(out))
102+
}
103+
104+
return port, nil
105+
}
106+
85107
port, err = codeserver.Port(cntName)
86108
if err == nil {
87109
return port, nil

internal/codeserver/proc.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ func parseNetTCPStats(out []byte) ([]*netStat, error) {
130130
for _, line := range lines {
131131
fields := strings.Fields(string(bytes.TrimSpace(line)))
132132
if len(fields) != 3 {
133-
return nil, xerrors.Errorf("line formatted incorrectly: %s", line)
133+
return nil, xerrors.Errorf("line formatted incorrectly: %q", line)
134134
}
135135

136136
var stat netStat

project.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package main
33
import (
44
"context"
55
"fmt"
6-
"net"
76
"os"
87
"path/filepath"
98
"strings"
@@ -247,7 +246,7 @@ func (p *project) open() error {
247246
return err
248247
}
249248

250-
u := "http://localhost:" + port
249+
u := "http://127.0.0.1:" + port
251250

252251
flog.Info("opening %v", u)
253252
return browserapp.Open(u)

runner.go

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import (
44
"context"
55
"fmt"
66
"github.com/docker/go-connections/nat"
7+
"log"
78
"os"
89
"path/filepath"
910
"runtime"
10-
"strconv"
1111
"strings"
1212
"time"
1313

@@ -70,17 +70,26 @@ func (r *runner) runContainer(image string) error {
7070
return err
7171
}
7272

73+
containerAddr := "localhost"
74+
containerPort := r.port
75+
if runtime.GOOS == "darwin" {
76+
// See justification below.
77+
containerPort = "8443"
78+
containerAddr = "0.0.0.0"
79+
}
7380
// We want the code-server logs to be available inside the container for easy
7481
// access during development, but also going to stdout so `docker logs` can be used
7582
// to debug a failed code-server startup.
76-
cmd := "cd " + projectDir +
77-
"; code-server --host 127.0.0.1" +
78-
" --port " + r.port +
79-
" --data-dir ~/.config/Code --extensions-dir ~/.vscode/extensions --allow-http --no-auth 2>&1 | tee " + containerLogPath
83+
cmd := fmt.Sprintf(`set -euxo pipefail || exit 1
84+
cd %v
85+
code-server --host %v --port %v --data-dir ~/.config/Code --extensions-dir ~/.vscode/extensions --allow-http --no-auth 2>&1 | tee %v
86+
`, projectDir, containerAddr, containerPort, containerLogPath)
8087
if r.testCmd != "" {
8188
cmd = r.testCmd + "\n exit 1"
8289
}
8390

91+
log.Printf("%q", cmd)
92+
8493
var envs []string
8594
sshAuthSock, exists := os.LookupEnv("SSH_AUTH_SOCK")
8695
if exists {
@@ -101,10 +110,9 @@ func (r *runner) runContainer(image string) error {
101110
projectLocalDirLabel: r.projectLocalDir,
102111
projectNameLabel: r.projectName,
103112
},
104-
Env: []string{
105-
"EXT_UID=" + strconv.Itoa(os.Getuid()),
106-
},
107-
User: "root",
113+
// The user inside has uid 1000. This works even on macOS where the default user has uid 501.
114+
// See https://stackoverflow.com/questions/43097341/docker-on-macosx-does-not-translate-file-ownership-correctly-in-volumes
115+
User: "",
108116
}
109117

110118
err = r.addImageDefinedLabels(image, containerConfig.Labels)
@@ -129,9 +137,12 @@ func (r *runner) runContainer(image string) error {
129137
},
130138
}
131139

140+
// macOS does not support host networking.
141+
// See https://github.com/docker/for-mac/issues/2716
132142
if runtime.GOOS == "darwin" {
143+
portSpec := fmt.Sprintf("127.0.0.1:%v:%v/tcp", r.port, "8443")
133144
hostConfig.NetworkMode = ""
134-
exposed, bindings, err := nat.ParsePortSpecs([]string{fmt.Sprintf("%v:%v/tcp", r.port, r.port)})
145+
exposed, bindings, err := nat.ParsePortSpecs([]string{portSpec})
135146
if err != nil {
136147
return xerrors.Errorf("failed to parse port spec: %w", err)
137148
}

0 commit comments

Comments
 (0)