mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge branch 'master' into tty_resize
Conflicts: commands.go
This commit is contained in:
commit
ffd9e06deb
8 changed files with 125 additions and 53 deletions
9
api.go
9
api.go
|
@ -60,7 +60,7 @@ func getBoolParam(value string) (bool, error) {
|
|||
}
|
||||
|
||||
func getAuth(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
b, err := json.Marshal(srv.registry.GetAuthConfig())
|
||||
b, err := json.Marshal(srv.registry.GetAuthConfig(false))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -73,9 +73,9 @@ func postAuth(srv *Server, version float64, w http.ResponseWriter, r *http.Reque
|
|||
if err := json.NewDecoder(r.Body).Decode(config); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if config.Username == srv.registry.GetAuthConfig().Username {
|
||||
config.Password = srv.registry.GetAuthConfig().Password
|
||||
authConfig := srv.registry.GetAuthConfig(true)
|
||||
if config.Username == authConfig.Username {
|
||||
config.Password = authConfig.Password
|
||||
}
|
||||
|
||||
newAuthConfig := auth.NewAuthConfig(config.Username, config.Password, config.Email, srv.runtime.root)
|
||||
|
@ -686,6 +686,5 @@ func ListenAndServe(addr string, srv *Server, logging bool) error {
|
|||
r.Path(localRoute).Methods(localMethod).HandlerFunc(f)
|
||||
}
|
||||
}
|
||||
|
||||
return http.ListenAndServe(addr, r)
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ func TestGetAuth(t *testing.T) {
|
|||
t.Fatalf("%d OK or 0 expected, received %d\n", http.StatusOK, r.Code)
|
||||
}
|
||||
|
||||
newAuthConfig := srv.registry.GetAuthConfig()
|
||||
newAuthConfig := srv.registry.GetAuthConfig(false)
|
||||
if newAuthConfig.Username != authConfig.Username ||
|
||||
newAuthConfig.Email != authConfig.Email {
|
||||
t.Fatalf("The auth configuration hasn't been set correctly")
|
||||
|
|
110
commands.go
110
commands.go
|
@ -32,15 +32,19 @@ var (
|
|||
GIT_COMMIT string
|
||||
)
|
||||
|
||||
func ParseCommands(args ...string) error {
|
||||
cli := NewDockerCli("0.0.0.0", 4243)
|
||||
func (cli *DockerCli) getMethod(name string) (reflect.Method, bool) {
|
||||
methodName := "Cmd" + strings.ToUpper(name[:1]) + strings.ToLower(name[1:])
|
||||
return reflect.TypeOf(cli).MethodByName(methodName)
|
||||
}
|
||||
|
||||
func ParseCommands(addr string, port int, args ...string) error {
|
||||
cli := NewDockerCli(addr, port)
|
||||
|
||||
if len(args) > 0 {
|
||||
methodName := "Cmd" + strings.ToUpper(args[0][:1]) + strings.ToLower(args[0][1:])
|
||||
method, exists := reflect.TypeOf(cli).MethodByName(methodName)
|
||||
method, exists := cli.getMethod(args[0])
|
||||
if !exists {
|
||||
fmt.Println("Error: Command not found:", args[0])
|
||||
return cli.CmdHelp(args...)
|
||||
return cli.CmdHelp(args[1:]...)
|
||||
}
|
||||
ret := method.Func.CallSlice([]reflect.Value{
|
||||
reflect.ValueOf(cli),
|
||||
|
@ -55,7 +59,19 @@ func ParseCommands(args ...string) error {
|
|||
}
|
||||
|
||||
func (cli *DockerCli) CmdHelp(args ...string) error {
|
||||
help := "Usage: docker COMMAND [arg...]\n\nA self-sufficient runtime for linux containers.\n\nCommands:\n"
|
||||
if len(args) > 0 {
|
||||
method, exists := cli.getMethod(args[0])
|
||||
if !exists {
|
||||
fmt.Println("Error: Command not found:", args[0])
|
||||
} else {
|
||||
method.Func.CallSlice([]reflect.Value{
|
||||
reflect.ValueOf(cli),
|
||||
reflect.ValueOf([]string{"--help"}),
|
||||
})[0].Interface()
|
||||
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.addr, cli.port)
|
||||
for cmd, description := range map[string]string{
|
||||
"attach": "Attach to a running container",
|
||||
"build": "Build a container from Dockerfile or via stdin",
|
||||
|
@ -609,39 +625,13 @@ func (cli *DockerCli) CmdPush(args ...string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
body, _, err := cli.call("GET", "/auth", nil)
|
||||
username, err := cli.checkIfLogged(*registry == "", "push")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var out auth.AuthConfig
|
||||
err = json.Unmarshal(body, &out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If the login failed AND we're using the index, abort
|
||||
if *registry == "" && out.Username == "" {
|
||||
if err := cli.CmdLogin(args...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
body, _, err = cli.call("GET", "/auth", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = json.Unmarshal(body, &out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if out.Username == "" {
|
||||
return fmt.Errorf("Please login prior to push. ('docker login')")
|
||||
}
|
||||
}
|
||||
|
||||
if len(strings.SplitN(name, "/", 2)) == 1 {
|
||||
return fmt.Errorf("Impossible to push a \"root\" repository. Please rename your repository in <user>/<repo> (ex: %s/%s)", out.Username, name)
|
||||
return fmt.Errorf("Impossible to push a \"root\" repository. Please rename your repository in <user>/<repo> (ex: %s/%s)", username, name)
|
||||
}
|
||||
|
||||
v := url.Values{}
|
||||
|
@ -672,6 +662,12 @@ func (cli *DockerCli) CmdPull(args ...string) error {
|
|||
remote = remoteParts[0]
|
||||
}
|
||||
|
||||
if strings.Contains(remote, "/") {
|
||||
if _, err := cli.checkIfLogged(true, "pull"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
v := url.Values{}
|
||||
v.Set("fromImage", remote)
|
||||
v.Set("tag", *tag)
|
||||
|
@ -1161,6 +1157,40 @@ func (cli *DockerCli) CmdRun(args ...string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (cli *DockerCli) checkIfLogged(condition bool, action string) (string, error) {
|
||||
body, _, err := cli.call("GET", "/auth", nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var out auth.AuthConfig
|
||||
err = json.Unmarshal(body, &out)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// If condition AND the login failed
|
||||
if condition && out.Username == "" {
|
||||
if err := cli.CmdLogin(""); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
body, _, err = cli.call("GET", "/auth", nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
err = json.Unmarshal(body, &out)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if out.Username == "" {
|
||||
return "", fmt.Errorf("Please login prior to %s. ('docker login')", action)
|
||||
}
|
||||
}
|
||||
return out.Username, nil
|
||||
}
|
||||
|
||||
func (cli *DockerCli) call(method, path string, data interface{}) ([]byte, int, error) {
|
||||
var params io.Reader
|
||||
if data != nil {
|
||||
|
@ -1171,7 +1201,7 @@ func (cli *DockerCli) call(method, path string, data interface{}) ([]byte, int,
|
|||
params = bytes.NewBuffer(buf)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(method, fmt.Sprintf("http://%s:%d/v%f", cli.host, cli.port, API_VERSION)+path, params)
|
||||
req, err := http.NewRequest(method, fmt.Sprintf("http://%s:%d/v%g%s", cli.addr, cli.port, API_VERSION, path), params)
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
|
@ -1203,7 +1233,7 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer) e
|
|||
if (method == "POST" || method == "PUT") && in == nil {
|
||||
in = bytes.NewReader([]byte{})
|
||||
}
|
||||
req, err := http.NewRequest(method, fmt.Sprintf("http://%s:%d/v%f%s", cli.host, cli.port, API_VERSION, path), in)
|
||||
req, err := http.NewRequest(method, fmt.Sprintf("http://%s:%d/v%g%s", cli.addr, cli.port, API_VERSION, path), in)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1234,12 +1264,12 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer) e
|
|||
}
|
||||
|
||||
func (cli *DockerCli) hijack(method, path string, setRawTerminal bool) error {
|
||||
req, err := http.NewRequest(method, fmt.Sprintf("/v%f%s", API_VERSION, path), nil)
|
||||
req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", API_VERSION, path), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Set("Content-Type", "plain/text")
|
||||
dial, err := net.Dial("tcp", fmt.Sprintf("%s:%d", cli.host, cli.port))
|
||||
dial, err := net.Dial("tcp", fmt.Sprintf("%s:%d", cli.addr, cli.port))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1320,8 +1350,8 @@ func Subcmd(name, signature, description string) *flag.FlagSet {
|
|||
return flags
|
||||
}
|
||||
|
||||
func NewDockerCli(host string, port int) *DockerCli {
|
||||
return &DockerCli{host, port}
|
||||
func NewDockerCli(addr string, port int) *DockerCli {
|
||||
return &DockerCli{addr, port}
|
||||
}
|
||||
|
||||
type DockerCli struct {
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
|
@ -23,18 +24,38 @@ func main() {
|
|||
docker.SysInit()
|
||||
return
|
||||
}
|
||||
host := "127.0.0.1"
|
||||
port := 4243
|
||||
// FIXME: Switch d and D ? (to be more sshd like)
|
||||
flDaemon := flag.Bool("d", false, "Daemon mode")
|
||||
flDebug := flag.Bool("D", false, "Debug mode")
|
||||
flAutoRestart := flag.Bool("r", false, "Restart previously running containers")
|
||||
bridgeName := flag.String("b", "", "Attach containers to a pre-existing network bridge")
|
||||
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")
|
||||
flag.Parse()
|
||||
if *bridgeName != "" {
|
||||
docker.NetworkBridgeIface = *bridgeName
|
||||
} else {
|
||||
docker.NetworkBridgeIface = docker.DefaultNetworkBridge
|
||||
}
|
||||
|
||||
if strings.Contains(*flHost, ":") {
|
||||
hostParts := strings.Split(*flHost, ":")
|
||||
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 {
|
||||
os.Setenv("DEBUG", "1")
|
||||
}
|
||||
|
@ -44,12 +65,12 @@ func main() {
|
|||
flag.Usage()
|
||||
return
|
||||
}
|
||||
if err := daemon(*pidfile, *flAutoRestart); err != nil {
|
||||
if err := daemon(*pidfile, host, port, *flAutoRestart); err != nil {
|
||||
log.Fatal(err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
} else {
|
||||
if err := docker.ParseCommands(flag.Args()...); err != nil {
|
||||
if err := docker.ParseCommands(host, port, flag.Args()...); err != nil {
|
||||
log.Fatal(err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
@ -83,7 +104,10 @@ func removePidFile(pidfile string) {
|
|||
}
|
||||
}
|
||||
|
||||
func daemon(pidfile string, autoRestart bool) error {
|
||||
func daemon(pidfile, addr string, port int, autoRestart bool) 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 {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -103,5 +127,5 @@ func daemon(pidfile string, autoRestart bool) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return docker.ListenAndServe("0.0.0.0:4243", server, true)
|
||||
return docker.ListenAndServe(fmt.Sprintf("%s:%d", addr, port), server, true)
|
||||
}
|
||||
|
|
|
@ -14,7 +14,8 @@ To list available commands, either run ``docker`` with no parameters or execute
|
|||
``docker help``::
|
||||
|
||||
$ docker
|
||||
Usage: docker COMMAND [arg...]
|
||||
Usage: docker [OPTIONS] COMMAND [arg...]
|
||||
-H="127.0.0.1:4243": Host:port to bind/connect to
|
||||
|
||||
A self-sufficient runtime for linux containers.
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ Due to a bug in LXC docker works best on the 3.8 kernel. Precise comes with a 3.
|
|||
.. code-block:: bash
|
||||
|
||||
# install the backported kernel
|
||||
sudo apt-get update && sudo apt-get install linux-image-3.8.0-19-generic
|
||||
sudo apt-get update && sudo apt-get install linux-image-generic-lts-raring
|
||||
|
||||
# reboot
|
||||
sudo reboot
|
||||
|
|
|
@ -33,6 +33,19 @@ Running an interactive shell
|
|||
# allocate a tty, attach stdin and stdout
|
||||
docker run -i -t base /bin/bash
|
||||
|
||||
Bind Docker to another host/port
|
||||
--------------------------------
|
||||
|
||||
If you want Docker to listen to another port and bind to another ip
|
||||
use -host and -port on both deamon and client
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# Run docker in daemon mode
|
||||
sudo <path to>/docker -H 0.0.0.0:5555 &
|
||||
# Download a base image
|
||||
docker -H :5555 pull base
|
||||
|
||||
|
||||
Starting a long-running worker process
|
||||
--------------------------------------
|
||||
|
|
|
@ -428,9 +428,14 @@ func (r *Registry) ResetClient(authConfig *auth.AuthConfig) {
|
|||
r.client.Jar = cookiejar.NewCookieJar()
|
||||
}
|
||||
|
||||
func (r *Registry) GetAuthConfig() *auth.AuthConfig {
|
||||
func (r *Registry) GetAuthConfig(withPasswd bool) *auth.AuthConfig {
|
||||
password := ""
|
||||
if withPasswd {
|
||||
password = r.authConfig.Password
|
||||
}
|
||||
return &auth.AuthConfig{
|
||||
Username: r.authConfig.Username,
|
||||
Password: password,
|
||||
Email: r.authConfig.Email,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue