Home PC Games Linux Windows Database Network Programming Server Mobile  
  Home \ Linux \ 5 steps to help you become a good Docker contributors     - wget command usage Explanation (Linux)

- How to defragment the hard disk in Linux (Linux)

- How to manage start-up applications in Ubuntu (Linux)

- Grep, Ack, Ag searches Efficiency Comparison (Linux)

- Php and MySQL command add to the environment variable method in Linux system (Linux)

- MySQL 5.7 can not log in problem (Database)

- floating IP in OpenStack neutron (Server)

- How to download GOG games in Linux command line (Linux)

- Getting Started with Linux system to learn: how to check the version of SSH on Linux (Linux)

- C ++ thread creates transmission parameters are changed (Programming)

- Questions about Linux compiler u-boot (Programming)

- Linux System Getting Started Learning: compile and install ixgbe driver in Ubuntu or Debian (Linux)

- To install Samba server on CentOS 6.6 (Server)

- How to use the Linux terminal Git commands (Linux)

- CentOS6 5 source compiler installation Hadoop2.5.1 (Server)

- Setting the RedHat9 Intrusion Detection System (Linux)

- To access an Oracle database using Instant Client (Database)

- Sublime Text 3 practical functions and shortcut keys used to collect (Linux)

- installation of Vim plugin YouCompleteMe under Ubuntu 15.04 (Linux)

- Linux System Administrator Network Security Experience (Linux)

  5 steps to help you become a good Docker contributors
  Add Date : 2018-11-21      
  Open source become mainstream, more and more developers who want to participate in the open source community. And nowadays the most fiery Docker is perhaps the best choice for developers to start an open source project, it is not only one of the most popular open source projects, but also in terms of the documentation submitted Issue and processes are currently open source projects I've seen the most Ok. This article describes how to start an open source project, some small experience and gadgets, learning together.

It became a popular open source projects (such as the Docker) contributor has the following advantages:

You can participate in the project to improve the lot of people are used, in order to obtain a sense of identity;
You can work together with the open source community that highly intelligent people;
You can participate in this project to improve understanding and to become a better programmer.
However, a new code number (codebase) start is definitely a scary thing. Currently, Docker has been quite a bit of code, even if it is to fix a small problem, you need to read a lot of code, and understand how the parts fit together.

However, they are not as difficult as you might think. You can Docker contributors guide to complete the configuration environment. Then follows five simple steps, with the relevant code snippets depth code base. You experience these skills, all will come in handy in every new project in your programming career. Well so what, we'll get working.


Step 1: From the 'func main ()' start

As the old saying, you know from the start. If you and most of the Docker user, you probably use mainly Docker CLI. So, let's start from the entrance application: 'main' function.

Here tips in this article, we'll use a site called Sourcegraph's, Docker team use it to complete the online search and browse the code, and you use a smart IDE do the same. Recommend reading this article, open Sourcegraph aside to better keep up with the progress of the article.

In Sourcegraph site, let us search Docker warehouse 'func main ()'.

We are looking for the corresponding 'docker' command 'main' function, which is 'docker / docker / docker.go' a file. Click on the search results, we will jump to its definition (see below). Take a moment to look at this function:

func main () {
if reexec.Init () {
// Set terminal emulation based on platform as required.
stdin, stdout, stderr: = term.StdStreams ()
initLogging (stderr)
flag.Parse ()
// FIXME: validate daemon flags here
if * flVersion {
showVersion ()
if * flLogLevel! = "" {
lvl, err: = logrus.ParseLevel (* flLogLevel)
if err! = nil {
logrus.Fatalf ( "Unable to parse logging level:% s", * flLogLevel)
setLogLevel (lvl)
} Else {
setLogLevel (logrus.InfoLevel)
// -D, --debug, -l / - Log-level = debug processing
// When / if -D is removed this block can be deleted
if * flDebug {
os.Setenv ( "DEBUG", "1")
setLogLevel (logrus.DebugLevel)
if len (flHosts) == 0 {
defaultHost: = os.Getenv ( "DOCKER_HOST")
if defaultHost == "" || * flDaemon {
// If we do not have a host, default to unix socket
defaultHost = fmt.Sprintf ( "unix: //% s", api.DEFAULTUNIXSOCKET)
defaultHost, err: = api.ValidateHost (defaultHost)
if err! = nil {
logrus.Fatal (err)
flHosts = append (flHosts, defaultHost)
setDefaultConfFlag (flTrustKey, defaultTrustKeyFile)
if * flDaemon {
if * flHelp {
flag.Usage ()
mainDaemon ()
if len (flHosts)> 1 {
logrus.Fatal ( "Please specify only one -H")
protoAddrParts: = strings.SplitN (flHosts [0], ": //", 2)
var (
cli * client.DockerCli
tlsConfig tls.Config
tlsConfig.InsecureSkipVerify = true
// Regardless of whether the user sets it to true or false, if they
// Specify --tlsverify at all then we need to turn on tls
if flag.IsSet ( "- tlsverify") {
* FlTls = true
// If we should verify the server, we need to load a trusted ca
if * flTlsVerify {
certPool: = x509.NewCertPool ()
file, err: = ioutil.ReadFile (* flCa)
if err! = nil {
logrus.Fatalf ( "Could not read ca cert% s:% s", * flCa, err)
certPool.AppendCertsFromPEM (file)
tlsConfig.RootCAs = certPool
tlsConfig.InsecureSkipVerify = false
// If tls is enabled, try to load and send client certificates
if * flTls || * flTlsVerify {
_, ErrCert: = os.Stat (* flCert)
_, ErrKey: = os.Stat (* flKey)
if errCert == nil && errKey == nil {
* FlTls = true
cert, err: = tls.LoadX509KeyPair (* flCert, * flKey)
if err! = nil {
logrus.Fatalf ( "Could not load X509 key pair:% q Make sure the key is encrypted.", err)
tlsConfig.Certificates = [] tls.Certificate {cert}
// Avoid fallback to SSL protocols tlsConfig.MinVersion = tls.VersionTLS10
if * flTls || * flTlsVerify {
cli = client.NewDockerCli (stdin, stdout, stderr, * flTrustKey, protoAddrParts [0], protoAddrParts [1], & tlsConfig)
} Else {
cli = client.NewDockerCli (stdin, stdout, stderr, * flTrustKey, protoAddrParts [0], protoAddrParts [1], nil)
if err: = cli.Cmd (flag.Args () ...); err = nil {!
if sterr, ok: = err (* utils.StatusError); ok {.
if sterr.Status! = "" {
logrus.Println (sterr.Status)
os.Exit (sterr.StatusCode)
logrus.Fatal (err)
In the top of the 'main' function, we saw many of the log configuration command to read the signs and associated default initialization code. At the bottom, we find on "client.NewDockerCli" call, it seems to be responsible for creating the structure, and this structure function will do all the real work. Let's search for "NewDockerCli."


Step 2: Find the core part

In many applications and libraries, there are 1-2 key interface, which expresses the essence or core functions. Let's try to reach this critical section.

Click 'NewDockerCli' search results, we will reach the defined function. Since we are only interested in the structure returned by this function - "DockerCli", so let's click on the return type to jump to its definition.

func NewDockerCli (in io.ReadCloser, out, err io.Writer, keyFile string, proto, addr string, tlsConfig * tls.Config) * DockerCli {
var (
inFd uintptr
outFd uintptr
isTerminalIn = false
isTerminalOut = false
scheme = "http"
if tlsConfig! = nil {
scheme = "https"
ifin! = nil {
inFd, isTerminalIn = term.GetFdInfo (in)
ifout! = nil {
outFd, isTerminalOut = term.GetFdInfo (out)
if err == nil {
err = out
// The transport is created here for reuse during the client session
tr: = & http.Transport {
TLSClientConfig: tlsConfig,
// Why 32? See issue 8035
timeout: = 32 * time.Second
if proto == "unix" {
// No need in compressing for local communications
tr.DisableCompression = true
tr.Dial = func (_, _ string) (net.Conn, error) {
return net.DialTimeout (proto, addr, timeout)
} Else {
tr.Proxy = http.ProxyFromEnvironment
tr.Dial = (& net.Dialer {Timeout: timeout}). Dial
return & DockerCli {
proto: proto,
addr: addr,
in: in,
out: out,
err: err,
keyFile: keyFile,
inFd: inFd,
outFd: outFd,
isTerminalIn: isTerminalIn,
isTerminalOut: isTerminalOut,
tlsConfig: tlsConfig,
scheme: scheme,
transport: tr,
Click "DockerCli" takes us into its definition. Scroll down this document, we can see its methods, 'getMethod', 'Cmd', 'Subcmd' and 'LoadConfigFile'. Wherein, 'Cmd' worth noting. It is the only way to contain a docstring, and docstring is that it is a method of execution cores each Docker command.


Step 3: further

Now that we have found the 'DockerCli', the Docker core client 'controller', let us continue in-depth understanding of a specific command Docker is how it works. Let's zoom 'docker build' section of the code.

type DockerClistruct {
proto string
addr string
configFile * registry.ConfigFile
in io.ReadCloser
out io.Writer
err io.Writer
keyFile string
tlsConfig * tls.Config
scheme string
// InFd holds file descriptor of the client's STDIN, if it's a valid file
inFd uintptr
// OutFd holds file descriptor of the client's STDOUT, if it's a valid file
outFd uintptr
// IsTerminalIn describes if client's STDIN is a TTY
isTerminalIn bool
// IsTerminalOut describes if client's STDOUT is a TTY
isTerminalOut bool
transport * http.Transport
Read 'DockerCli.Cmd' implementation can be found, it calls the 'DockerCli.getMethod' method to execute each command Docker corresponding functions.

func (cli * DockerCli) Cmd (args ... string) error {
if len (args)> 1 {
method, exists: = cli.getMethod (args [: 2] ...)
if exists {
return method (args [2:] ...)
if len (args)> 0 {
method, exists: = cli.getMethod (args [0])
if! exists {
fmt.Fprintf (cli.err, "docker: '% s' is not a docker command See 'docker --help' \ n..", args [0])
os.Exit (1)
return method (args [1:] ...)
return cli.CmdHelp ()
In the 'DockerCli.getMethod', we can see that it is through the dynamic invocation of a function implemented, in which the form of the function name is preset before Docker command "Cmd" string. So in 'docker build' this situation, we are looking for 'DockerCli.CmdBuild'. But in this file and no corresponding method, so let's need to search for 'CmdBuild'.

func (cli * DockerCli) getMethod (args ... string) (func (... string) error, bool) {
camelArgs: = make ([] string, len (args))
for i, s: = range args {
if len (s) == 0 {
returnnil, false
camelArgs [i] = strings.ToUpper (s [: 1]) + strings.ToLower (s [1:])
methodName: = "Cmd" + strings.Join (camelArgs, "")
method: = reflect.ValueOf (cli) .MethodByName (methodName)
if! method.IsValid () {
returnnil, false
return method.Interface (). (func (... string) error), true
Search results show 'DockerCli' does have a 'CmdBuild' methods, so jump to its definition section. Since 'DockerCli.CmdBuild' method body for too long, it is not embedded in the paper, but there is a link to it.

There are a lot of content. In the top of the method, we can see the code will handle a variety of input methods for the Dockerfile and configuration. In general, reading a long way when read upside down is a very good strategy. Starting from the bottom, to observe what has been done at the end of the function. In many cases, they are functions of nature, whereas the previous content is nothing more than just to complement the core behavior.

At the bottom of 'CmdBuild', we can see through 'cli.stream' structure 'POST' request. Jump through some additional definitions, we arrived at the 'DockerCli.clientRequest', it constructs an HTTP request, the request contains you through 'docker build' information passed to the Docker. So here, 'docker build does is send out a vision of' POST 'request to Docker daemon. If you prefer, you can also use 'curl' to accomplish this behavior.

So far, we have a thorough understanding of a separate Docker client command, you may still want to go further, to find the daemon accepts requests section, and track all the way to its core and LXC and interactive part. This is certainly a reasonable path, but we will leave it as an exercise for our readers. Next, let us key components of the client to have a more comprehensive understanding.


Step 4: See the example

To better understand a piece of code is to use an example to show how the code view is applied. Let's go back 'DockerCli.clientRequest' method. Sourcegraph the right hand side panel, we can view examples of the use of this method. The results show that this method is used in many places, because most Docker client commands will have reached the daemon HTTP request.

To fully understand a snippet, you need to know how it works and how to use. By defining part of reading the code allows us to understand the former, and usage example is covered by the latter.

Please on more functions and methods to try to understand their internal links.

Step 5: Select a problem and start coding

Now that you have a general understanding of the Docker's code base, you can consult about the issue tracking system, what kind of problems to be solved, and in the face of your own when you can not answer the question, to the members of the community of Docker Shen aid. Since you've spent the time to explore and understand the code, then you should already have the conditions to make "smart" questions and know that the problem probably lies.

If you feel the need, the way you can take notes, record your experiences, and like the same article as a blog post. Docker team will be happy to see that you study their code experience.


Effective contribution

A huge and strange fear reference code, seems to have become a people involved in the project to prevent misunderstanding. We often assume, for programmers and difficult work is to write code, but the code reading and understanding of others is often the most critical step. Recognizing all this, and firmly to meet the task, combined with excellent tool will help you overcome the psychological barrier to better put into the code.
- Linux firewall settings instance (Linux)
- Oracle data row split multiple lines (Database)
- View and modify Linux machine name (Linux)
- Terminal multiplexing tool tmux use (Linux)
- GitLab issued Merge Request return error 500 when the two solutions log (Linux)
- Android Action Compendium (Programming)
- Install Java JDK 8 in CentOS 7 / 6.5 / 6.4 (Linux)
- Preview function to confirm the stop resource Oracle 12c new feature crsctl (Database)
- Ubuntu 14.04 Install WordPress on Nginx (Server)
- Linux script commands - terminal recorder (Linux)
- Linux server network penetration testing (Linux)
- Apache site default home page settings (Server)
- LVM Disk Manager Application (Linux)
- shell-like program (Programming)
- Linux Getting Started tutorial: Experience KVM Virtual Machine chapter (Linux)
- Upgrading KDE Plasma 5.3 in Ubuntu 15.04 (Linux)
- socket busy poll of Linux kernel 3.11 to avoid sleep switch (Linux)
- To execute the cp command prompt type skip folder under CentOS (Linux)
- Upgrade to Node V4 seven reasons (Programming)
- IPTABLES configuration steps under Linux (Linux)
  CopyRight 2002-2022 newfreesoft.com, All Rights Reserved.