這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
Docker 1.12整合了docker swarm功能,其client的相關代碼位於api/client/swarm檔案夾下。以docker swarm init命令的代碼(api/client/swarm/init.go)為例:
const ( generatedSecretEntropyBytes = 16 generatedSecretBase = 36 // floor(log(2^128-1, 36)) + 1 maxGeneratedSecretLength = 25)type initOptions struct { swarmOptions listenAddr NodeAddrOption // Not a NodeAddrOption because it has no default port. advertiseAddr string forceNewCluster bool}func newInitCommand(dockerCli *client.DockerCli) *cobra.Command { opts := initOptions{ listenAddr: NewListenAddrOption(), } cmd := &cobra.Command{ Use: "init [OPTIONS]", Short: "Initialize a swarm", Args: cli.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { return runInit(dockerCli, cmd.Flags(), opts) }, } flags := cmd.Flags() flags.Var(&opts.listenAddr, flagListenAddr, "Listen address (format: <ip|interface>[:port])") flags.StringVar(&opts.advertiseAddr, flagAdvertiseAddr, "", "Advertised address (format: <ip|interface>[:port])") flags.BoolVar(&opts.forceNewCluster, "force-new-cluster", false, "Force create a new cluster from current state.") addSwarmFlags(flags, &opts.swarmOptions) return cmd}func runInit(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts initOptions) error { client := dockerCli.Client() ctx := context.Background() req := swarm.InitRequest{ ListenAddr: opts.listenAddr.String(), AdvertiseAddr: opts.advertiseAddr, ForceNewCluster: opts.forceNewCluster, Spec: opts.swarmOptions.ToSpec(), } nodeID, err := client.SwarmInit(ctx, req) if err != nil { if strings.Contains(err.Error(), "could not choose an IP address to advertise") || strings.Contains(err.Error(), "could not find the system's IP address") { return errors.New(err.Error() + " - specify one with --advertise-addr") } return err } fmt.Fprintf(dockerCli.Out(), "Swarm initialized: current node (%s) is now a manager.\n\n", nodeID) if err := printJoinCommand(ctx, dockerCli, nodeID, true, false); err != nil { return err } fmt.Fprint(dockerCli.Out(), "To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.\n\n") return nil}
其中client.DockerCli代表docker command line client:
// DockerCli represents the docker command line client.// Instances of the client can be returned from NewDockerCli.type DockerCli struct { // initializing closure init func() error // configFile has the client configuration file configFile *configfile.ConfigFile // in holds the input stream and closer (io.ReadCloser) for the client. in io.ReadCloser // out holds the output stream (io.Writer) for the client. out io.Writer // err holds the error stream (io.Writer) for the client. err io.Writer // keyFile holds the key file as a string. keyFile string // inFd holds the file descriptor of the client's STDIN (if valid). inFd uintptr // outFd holds file descriptor of the client's STDOUT (if valid). outFd uintptr // isTerminalIn indicates whether the client's STDIN is a TTY isTerminalIn bool // isTerminalOut indicates whether the client's STDOUT is a TTY isTerminalOut bool // client is the http client that performs all API operations client client.APIClient // state holds the terminal input state inState *term.State // outState holds the terminal output state outState *term.State}
其中的client成員便是engine-api/client,所以上述client.SwarmInit的代碼位於engine-api/client/swarm_init.go:
// SwarmInit initializes the Swarm.func (cli *Client) SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error) { serverResp, err := cli.post(ctx, "/swarm/init", nil, req, nil) if err != nil { return "", err } var response string err = json.NewDecoder(serverResp.body).Decode(&response) ensureReaderClosed(serverResp) return response, err}