mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
add basic support for unix sockets
This commit is contained in:
parent
069a7c1e99
commit
3adf9ce04e
5 changed files with 110 additions and 46 deletions
19
api.go
19
api.go
|
@ -8,12 +8,16 @@ import (
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const APIVERSION = 1.2
|
const APIVERSION = 1.2
|
||||||
|
const DEFAULTHTTPHOST string = "127.0.0.1"
|
||||||
|
const DEFAULTHTTPPORT int = 4243
|
||||||
|
|
||||||
func hijackServer(w http.ResponseWriter) (io.ReadCloser, io.Writer, error) {
|
func hijackServer(w http.ResponseWriter) (io.ReadCloser, io.Writer, error) {
|
||||||
conn, _, err := w.(http.Hijacker).Hijack()
|
conn, _, err := w.(http.Hijacker).Hijack()
|
||||||
|
@ -848,12 +852,21 @@ func createRouter(srv *Server, logging bool) (*mux.Router, error) {
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListenAndServe(addr string, srv *Server, logging bool) error {
|
func ListenAndServe(proto, addr string, srv *Server, logging bool) error {
|
||||||
log.Printf("Listening for HTTP on %s\n", addr)
|
log.Printf("Listening for HTTP on %s (%s)\n", addr, proto)
|
||||||
|
|
||||||
r, err := createRouter(srv, logging)
|
r, err := createRouter(srv, logging)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return http.ListenAndServe(addr, r)
|
l, e := net.Listen(proto, addr)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
//as the daemon is launched as root, change to permission of the socket to allow non-root to connect
|
||||||
|
if proto == "unix" {
|
||||||
|
os.Chmod(addr, 0777)
|
||||||
|
}
|
||||||
|
httpSrv := http.Server{Addr: addr, Handler: r}
|
||||||
|
return httpSrv.Serve(l)
|
||||||
}
|
}
|
||||||
|
|
|
@ -304,9 +304,9 @@ func (b *builderClient) Build(dockerfile, context io.Reader) (string, error) {
|
||||||
return "", fmt.Errorf("An error occured during the build\n")
|
return "", fmt.Errorf("An error occured during the build\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBuilderClient(addr string, port int) BuildFile {
|
func NewBuilderClient(proto, addr string) BuildFile {
|
||||||
return &builderClient{
|
return &builderClient{
|
||||||
cli: NewDockerCli(addr, port),
|
cli: NewDockerCli(proto, addr),
|
||||||
config: &Config{},
|
config: &Config{},
|
||||||
tmpContainers: make(map[string]struct{}),
|
tmpContainers: make(map[string]struct{}),
|
||||||
tmpImages: make(map[string]struct{}),
|
tmpImages: make(map[string]struct{}),
|
||||||
|
|
47
commands.go
47
commands.go
|
@ -40,8 +40,8 @@ func (cli *DockerCli) getMethod(name string) (reflect.Method, bool) {
|
||||||
return reflect.TypeOf(cli).MethodByName(methodName)
|
return reflect.TypeOf(cli).MethodByName(methodName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseCommands(addr string, port int, args ...string) error {
|
func ParseCommands(proto, addr string, args ...string) error {
|
||||||
cli := NewDockerCli(addr, port)
|
cli := NewDockerCli(proto, addr)
|
||||||
|
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
method, exists := cli.getMethod(args[0])
|
method, exists := cli.getMethod(args[0])
|
||||||
|
@ -74,7 +74,7 @@ func (cli *DockerCli) CmdHelp(args ...string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
help := fmt.Sprintf("Usage: docker [OPTIONS] COMMAND [arg...]\n -H=\"%s:%d\": Host:port to bind/connect to\n\nA self-sufficient runtime for linux containers.\n\nCommands:\n", cli.host, cli.port)
|
help := fmt.Sprintf("Usage: docker [OPTIONS] COMMAND [arg...]\n -H=\"%s:%d\": Host:port to bind/connect to\n\nA self-sufficient runtime for linux containers.\n\nCommands:\n", DEFAULTHTTPHOST, DEFAULTHTTPPORT)
|
||||||
for _, command := range [][2]string{
|
for _, command := range [][2]string{
|
||||||
{"attach", "Attach to a running container"},
|
{"attach", "Attach to a running container"},
|
||||||
{"build", "Build a container from a Dockerfile"},
|
{"build", "Build a container from a Dockerfile"},
|
||||||
|
@ -197,7 +197,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
|
||||||
v := &url.Values{}
|
v := &url.Values{}
|
||||||
v.Set("t", *tag)
|
v.Set("t", *tag)
|
||||||
// Send the multipart request with correct content-type
|
// Send the multipart request with correct content-type
|
||||||
req, err := http.NewRequest("POST", fmt.Sprintf("http://%s:%d%s?%s", cli.host, cli.port, "/build", v.Encode()), multipartBody)
|
req, err := http.NewRequest("POST", fmt.Sprintf("/v%s/build?%s", APIVERSION, v.Encode()), multipartBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -206,8 +206,13 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
|
||||||
req.Header.Set("X-Docker-Context-Compression", compression.Flag())
|
req.Header.Set("X-Docker-Context-Compression", compression.Flag())
|
||||||
fmt.Println("Uploading Context...")
|
fmt.Println("Uploading Context...")
|
||||||
}
|
}
|
||||||
|
dial, err := net.Dial(cli.proto, cli.addr)
|
||||||
resp, err := http.DefaultClient.Do(req)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
clientconn := httputil.NewClientConn(dial, nil)
|
||||||
|
resp, err := clientconn.Do(req)
|
||||||
|
defer clientconn.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1339,7 +1344,7 @@ func (cli *DockerCli) call(method, path string, data interface{}) ([]byte, int,
|
||||||
params = bytes.NewBuffer(buf)
|
params = bytes.NewBuffer(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := http.NewRequest(method, fmt.Sprintf("http://%s:%d/v%g%s", cli.host, cli.port, APIVERSION, path), params)
|
req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", APIVERSION, path), params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, -1, err
|
return nil, -1, err
|
||||||
}
|
}
|
||||||
|
@ -1349,7 +1354,13 @@ func (cli *DockerCli) call(method, path string, data interface{}) ([]byte, int,
|
||||||
} else if method == "POST" {
|
} else if method == "POST" {
|
||||||
req.Header.Set("Content-Type", "plain/text")
|
req.Header.Set("Content-Type", "plain/text")
|
||||||
}
|
}
|
||||||
resp, err := http.DefaultClient.Do(req)
|
dial, err := net.Dial(cli.proto, cli.addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, -1, err
|
||||||
|
}
|
||||||
|
clientconn := httputil.NewClientConn(dial, nil)
|
||||||
|
resp, err := clientconn.Do(req)
|
||||||
|
defer clientconn.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "connection refused") {
|
if strings.Contains(err.Error(), "connection refused") {
|
||||||
return nil, -1, fmt.Errorf("Can't connect to docker daemon. Is 'docker -d' running on this host?")
|
return nil, -1, fmt.Errorf("Can't connect to docker daemon. Is 'docker -d' running on this host?")
|
||||||
|
@ -1374,7 +1385,7 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer) e
|
||||||
if (method == "POST" || method == "PUT") && in == nil {
|
if (method == "POST" || method == "PUT") && in == nil {
|
||||||
in = bytes.NewReader([]byte{})
|
in = bytes.NewReader([]byte{})
|
||||||
}
|
}
|
||||||
req, err := http.NewRequest(method, fmt.Sprintf("http://%s:%d/v%g%s", cli.host, cli.port, APIVERSION, path), in)
|
req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", APIVERSION, path), in)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1382,7 +1393,13 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer) e
|
||||||
if method == "POST" {
|
if method == "POST" {
|
||||||
req.Header.Set("Content-Type", "plain/text")
|
req.Header.Set("Content-Type", "plain/text")
|
||||||
}
|
}
|
||||||
resp, err := http.DefaultClient.Do(req)
|
dial, err := net.Dial(cli.proto, cli.addr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
clientconn := httputil.NewClientConn(dial, nil)
|
||||||
|
resp, err := clientconn.Do(req)
|
||||||
|
defer clientconn.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "connection refused") {
|
if strings.Contains(err.Error(), "connection refused") {
|
||||||
return fmt.Errorf("Can't connect to docker daemon. Is 'docker -d' running on this host?")
|
return fmt.Errorf("Can't connect to docker daemon. Is 'docker -d' running on this host?")
|
||||||
|
@ -1432,7 +1449,7 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in *os.Fi
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
req.Header.Set("Content-Type", "plain/text")
|
req.Header.Set("Content-Type", "plain/text")
|
||||||
dial, err := net.Dial("tcp", fmt.Sprintf("%s:%d", cli.host, cli.port))
|
dial, err := net.Dial(cli.proto, cli.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1515,13 +1532,13 @@ func Subcmd(name, signature, description string) *flag.FlagSet {
|
||||||
return flags
|
return flags
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDockerCli(addr string, port int) *DockerCli {
|
func NewDockerCli(proto, addr string) *DockerCli {
|
||||||
authConfig, _ := auth.LoadConfig(os.Getenv("HOME"))
|
authConfig, _ := auth.LoadConfig(os.Getenv("HOME"))
|
||||||
return &DockerCli{addr, port, authConfig}
|
return &DockerCli{proto, addr, authConfig}
|
||||||
}
|
}
|
||||||
|
|
||||||
type DockerCli struct {
|
type DockerCli struct {
|
||||||
host string
|
proto string
|
||||||
port int
|
addr string
|
||||||
authConfig *auth.AuthConfig
|
authConfig *auth.AuthConfig
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,15 +24,13 @@ func main() {
|
||||||
docker.SysInit()
|
docker.SysInit()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
host := "127.0.0.1"
|
|
||||||
port := 4243
|
|
||||||
// FIXME: Switch d and D ? (to be more sshd like)
|
// FIXME: Switch d and D ? (to be more sshd like)
|
||||||
flDaemon := flag.Bool("d", false, "Daemon mode")
|
flDaemon := flag.Bool("d", false, "Daemon mode")
|
||||||
flDebug := flag.Bool("D", false, "Debug mode")
|
flDebug := flag.Bool("D", false, "Debug mode")
|
||||||
flAutoRestart := flag.Bool("r", false, "Restart previously running containers")
|
flAutoRestart := flag.Bool("r", false, "Restart previously running containers")
|
||||||
bridgeName := flag.String("b", "", "Attach containers to a pre-existing network bridge")
|
bridgeName := flag.String("b", "", "Attach containers to a pre-existing network bridge")
|
||||||
pidfile := flag.String("p", "/var/run/docker.pid", "File containing process PID")
|
pidfile := flag.String("p", "/var/run/docker.pid", "File containing process PID")
|
||||||
flHost := flag.String("H", fmt.Sprintf("%s:%d", host, port), "Host:port to bind/connect to")
|
flHost := flag.String("H", fmt.Sprintf("%s:%d", docker.DEFAULTHTTPHOST, docker.DEFAULTHTTPPORT), "Host:port to bind/connect to")
|
||||||
flEnableCors := flag.Bool("api-enable-cors", false, "Enable CORS requests in the remote api.")
|
flEnableCors := flag.Bool("api-enable-cors", false, "Enable CORS requests in the remote api.")
|
||||||
flDns := flag.String("dns", "", "Set custom dns servers")
|
flDns := flag.String("dns", "", "Set custom dns servers")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
@ -42,21 +40,8 @@ func main() {
|
||||||
docker.NetworkBridgeIface = docker.DefaultNetworkBridge
|
docker.NetworkBridgeIface = docker.DefaultNetworkBridge
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(*flHost, ":") {
|
protoAddr := parseHost(*flHost)
|
||||||
hostParts := strings.Split(*flHost, ":")
|
protoAddrs := []string{protoAddr}
|
||||||
if len(hostParts) != 2 {
|
|
||||||
log.Fatal("Invalid bind address format.")
|
|
||||||
os.Exit(-1)
|
|
||||||
}
|
|
||||||
if hostParts[0] != "" {
|
|
||||||
host = hostParts[0]
|
|
||||||
}
|
|
||||||
if p, err := strconv.Atoi(hostParts[1]); err == nil {
|
|
||||||
port = p
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
host = *flHost
|
|
||||||
}
|
|
||||||
|
|
||||||
if *flDebug {
|
if *flDebug {
|
||||||
os.Setenv("DEBUG", "1")
|
os.Setenv("DEBUG", "1")
|
||||||
|
@ -67,12 +52,13 @@ func main() {
|
||||||
flag.Usage()
|
flag.Usage()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := daemon(*pidfile, host, port, *flAutoRestart, *flEnableCors, *flDns); err != nil {
|
if err := daemon(*pidfile, protoAddrs, *flAutoRestart, *flEnableCors, *flDns); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := docker.ParseCommands(host, port, flag.Args()...); err != nil {
|
protoAddrParts := strings.SplitN(protoAddrs[0], "://", 2)
|
||||||
|
if err := docker.ParseCommands(protoAddrParts[0], protoAddrParts[1], flag.Args()...); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
|
@ -106,10 +92,7 @@ func removePidFile(pidfile string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func daemon(pidfile, addr string, port int, autoRestart, enableCors bool, flDns string) error {
|
func daemon(pidfile string, protoAddrs []string, autoRestart, enableCors bool, flDns string) error {
|
||||||
if addr != "127.0.0.1" {
|
|
||||||
log.Println("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
|
|
||||||
}
|
|
||||||
if err := createPidFile(pidfile); err != nil {
|
if err := createPidFile(pidfile); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -131,6 +114,55 @@ func daemon(pidfile, addr string, port int, autoRestart, enableCors bool, flDns
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
chErrors := make(chan error, len(protoAddrs))
|
||||||
return docker.ListenAndServe(fmt.Sprintf("%s:%d", addr, port), server, true)
|
for _, protoAddr := range protoAddrs {
|
||||||
|
protoAddrParts := strings.SplitN(protoAddr, "://", 2)
|
||||||
|
if protoAddrParts[0] == "unix" {
|
||||||
|
syscall.Unlink(protoAddrParts[1]);
|
||||||
|
} else if protoAddrParts[0] == "tcp" {
|
||||||
|
if !strings.HasPrefix(protoAddrParts[1], "127.0.0.1") {
|
||||||
|
log.Println("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Fatal("Invalid protocol format.")
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
chErrors <- docker.ListenAndServe(protoAddrParts[0], protoAddrParts[1], server, true)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
for i :=0 ; i < len(protoAddrs); i+=1 {
|
||||||
|
err := <-chErrors
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseHost(addr string) string {
|
||||||
|
if strings.HasPrefix(addr, "unix://") {
|
||||||
|
return addr
|
||||||
|
}
|
||||||
|
host := docker.DEFAULTHTTPHOST
|
||||||
|
port := docker.DEFAULTHTTPPORT
|
||||||
|
if strings.HasPrefix(addr, "tcp://") {
|
||||||
|
addr = strings.TrimPrefix(addr, "tcp://")
|
||||||
|
}
|
||||||
|
if strings.Contains(addr, ":") {
|
||||||
|
hostParts := strings.Split(addr, ":")
|
||||||
|
if len(hostParts) != 2 {
|
||||||
|
log.Fatal("Invalid bind address format.")
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
|
if hostParts[0] != "" {
|
||||||
|
host = hostParts[0]
|
||||||
|
}
|
||||||
|
if p, err := strconv.Atoi(hostParts[1]); err == nil {
|
||||||
|
port = p
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
host = addr
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("tcp://%s:%d", host, port)
|
||||||
}
|
}
|
||||||
|
|
|
@ -652,3 +652,5 @@ func CheckLocalDns() bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue