github.com/rentongzhang/docker@v1.8.2-rc1/docs/project/set-up-dev-env.md (about)

     1  <!--[metadata]>
     2  +++
     3  title = "Work with a development container"
     4  description = "How to use Docker's development environment"
     5  keywords = ["development, inception, container, image Dockerfile, dependencies, Go,  artifacts"]
     6  [menu.main]
     7  parent = "smn_develop"
     8  weight=5
     9  +++
    10  <![end-metadata]-->
    11  
    12  # Work with a development container
    13  
    14  In this section, you learn to develop like a member of Docker's core team.
    15  The `docker` repository includes a `Dockerfile` at its root. This file defines
    16  Docker's development environment.  The `Dockerfile` lists the environment's
    17  dependencies: system libraries and binaries, Go environment, Go dependencies,
    18  etc. 
    19  
    20  Docker's development environment is itself, ultimately a Docker container.
    21  You use the `docker` repository and its `Dockerfile` to create a Docker image, 
    22  run a Docker container, and develop code in the container. Docker itself builds,
    23  tests, and releases new Docker versions using this container.
    24  
    25  If you followed the procedures that <a href="/project/set-up-git" target="_blank">
    26  set up Git for contributing</a>, you should have a fork of the `docker/docker`
    27  repository. You also created a branch called `dry-run-test`. In this section,
    28  you continue working with your fork on this branch.
    29  
    30  ##  Clean your host of Docker artifacts
    31  
    32  Docker developers run the latest stable release of the Docker software (with Docker Machine if their machine is Mac OS X). They clean their local
    33  hosts of unnecessary Docker artifacts such as stopped containers or unused
    34  images. Cleaning unnecessary artifacts isn't strictly necessary, but it is
    35  good practice, so it is included here.
    36  
    37  To remove unnecessary artifacts,
    38  
    39  1. Verify that you have no unnecessary containers running on your host.
    40  
    41          $ docker ps
    42  
    43      You should see something similar to the following:
    44  
    45      <table class="code">
    46        <tr>
    47          <th>CONTAINER ID</th>
    48          <th>IMAGE</th>
    49          <th>COMMAND</th>
    50          <th>CREATED</th>
    51          <th>STATUS</th>
    52          <th>PORTS</th>
    53          <th>NAMES</th>
    54        </tr>
    55      </table>
    56  
    57      There are no running containers on this host. If you have running but unused
    58      containers, stop and then remove them with the `docker stop` and `docker rm`
    59      commands.
    60  
    61  2. Verify that your host has no dangling images.
    62  
    63          $ docker images
    64  
    65      You should see something similar to the following:
    66  
    67      <table class="code">
    68        <tr>
    69          <th>REPOSITORY</th>
    70          <th>TAG</th>
    71          <th>IMAGE ID</th>
    72          <th>CREATED</th>
    73          <th>VIRTUAL SIZE</th>
    74        </tr>
    75      </table>
    76  
    77      This host has no images. You may have one or more _dangling_ images. A
    78      dangling image is not used by a running container and is not an ancestor of
    79      another image on your system. A fast way to remove dangling containers is
    80      the following:
    81  
    82          $ docker rmi -f $(docker images -q -a -f dangling=true)
    83  
    84      This command uses `docker images` to list all images (`-a` flag) by numeric
    85      IDs (`-q` flag) and filter them to find dangling images (`-f dangling=true`).
    86      Then, the `docker rmi` command forcibly (`-f` flag) removes
    87      the resulting list. To remove just one image, use the `docker rmi ID`
    88      command.
    89  
    90  	
    91  ## Build an image
    92  
    93  If you followed the last procedure, your host is clean of unnecessary images 
    94  and containers. In this section, you build an image from the Docker development
    95  environment.
    96  
    97  1. Open a terminal.
    98  
    99      Mac users, use `boot2docker status` to make sure Boot2Docker is running. You
   100      may need to run `eval "$(boot2docker shellinit)"` to initialize your shell
   101      environment.
   102  
   103  3. Change into the root of your forked repository.
   104  
   105          $ cd ~/repos/docker-fork 
   106          
   107  	If you are following along with this guide, you created a `dry-run-test`
   108  	branch when you <a href="/project/set-up-git" target="_blank"> set up Git for
   109  	contributing</a>.
   110  
   111  4. Ensure you are on your `dry-run-test` branch.
   112  
   113          $ git checkout dry-run-test
   114          
   115      If you get a message that the branch doesn't exist, add the `-b` flag (git checkout -b dry-run-test) so the
   116      command both creates the branch and checks it out.
   117  
   118  5. Compile your development environment container into an image.
   119  
   120          $ docker build -t dry-run-test .
   121  
   122      The `docker build` command returns informational message as it runs. The
   123      first build may take a few minutes to create an image. Using the
   124      instructions in the `Dockerfile`, the build may need to download source and
   125      other images. A successful build returns a final status message similar to
   126      the following:
   127  
   128          Successfully built 676815d59283
   129  
   130  6. List your Docker images again.
   131  
   132          $ docker images
   133  
   134      You should see something similar to this:
   135  
   136      <table class="code">
   137        <tr>
   138          <th>REPOSTITORY</th>
   139          <th>TAG</th>
   140          <th>IMAGE ID</th>
   141          <th>CREATED</th>
   142          <th>VIRTUAL SIZE</th>
   143        </tr>
   144        <tr>
   145          <td>dry-run-test</td>
   146          <td>latest</td>
   147          <td>663fbee70028</td>
   148          <td>About a minute ago</td>
   149          <td></td>
   150        </tr>
   151        <tr>
   152          <td>ubuntu</td>
   153          <td>trusty</td>
   154          <td>2d24f826cb16</td>
   155          <td>2 days ago</td>
   156          <td>188.3 MB</td>
   157        </tr>
   158        <tr>
   159          <td>ubuntu</td>
   160          <td>trusty-20150218.1</td>
   161          <td>2d24f826cb16</td>
   162          <td>2 days ago</td>
   163          <td>188.3 MB</td>
   164        </tr>
   165        <tr>
   166          <td>ubuntu</td>
   167          <td>14.04</td>
   168          <td>2d24f826cb16</td>
   169          <td>2 days ago</td>
   170          <td>188.3 MB</td>
   171        </tr>
   172        <tr>
   173          <td>ubuntu</td>
   174          <td>14.04.2</td>
   175          <td>2d24f826cb16</td>
   176          <td>2 days ago</td>
   177          <td>188.3 MB</td>
   178        </tr>
   179        <tr>
   180          <td>ubuntu</td>
   181          <td>latest</td>
   182          <td>2d24f826cb16</td>
   183          <td>2 days ago</td>
   184          <td>188.3 MB</td>
   185        </tr>
   186      </table>
   187  
   188      Locate your new `dry-run-test` image in the list. You should also see a
   189      number of `ubuntu` images. The build process creates these. They are the
   190      ancestors of your new Docker development image. When you next rebuild your
   191      image, the build process reuses these ancestors images if they exist. 
   192  
   193      Keeping the ancestor images improves the build performance. When you rebuild
   194      the child image, the build process uses the local ancestors rather than
   195      retrieving them from the Hub. The build process gets new ancestors only if
   196      DockerHub has updated versions.
   197  
   198  ## Start a container and run a test
   199  
   200  At this point, you have created a new Docker development environment image. Now,
   201  you'll use this image to create a Docker container to develop in. Then, you'll
   202  build and run a `docker` binary in your container.
   203  
   204  1. Open two additional terminals on your host.
   205  
   206      At this point, you'll have about three terminals open.
   207  
   208      ![Multiple terminals](/project/images/three_terms.png)
   209  
   210      Mac OS X users, make sure you run `eval "$(boot2docker shellinit)"` in any new
   211      terminals.
   212  
   213  2. In a terminal, create a new container from your `dry-run-test` image.
   214  
   215          $ docker run --privileged --rm -ti dry-run-test /bin/bash
   216          root@5f8630b873fe:/go/src/github.com/docker/docker# 
   217  
   218      The command creates a container from your `dry-run-test` image. It opens an
   219      interactive terminal (`-ti`) running a `/bin/bash` shell.  The
   220      `--privileged` flag gives the container access to kernel features and device
   221      access. This flag allows you to run a container in a container.
   222      Finally, the `-rm` flag instructs Docker to remove the container when you
   223      exit the `/bin/bash` shell.
   224  
   225      The container includes the source of your image repository in the
   226      `/go/src/github.com/docker/docker` directory. Try listing the contents to
   227      verify they are the same as that of your `docker-fork` repo.
   228  
   229      ![List example](/project/images/list_example.png)
   230  
   231  
   232  3. Investigate your container bit. 
   233  
   234      If you do a `go version` you'll find the `go` language is part of the
   235      container. 
   236  
   237          root@31ed86e9ddcf:/go/src/github.com/docker/docker# go version
   238          go version go1.4.2 linux/amd64
   239  
   240      Similarly, if you do a `docker version` you find the container
   241      has no `docker` binary. 
   242  
   243          root@31ed86e9ddcf:/go/src/github.com/docker/docker# docker version
   244          bash: docker: command not found
   245  
   246      You will create one in the next steps.
   247  
   248  4. From the `/go/src/github.com/docker/docker` directory make a `docker` binary
   249  with the `make.sh` script.
   250  
   251          root@5f8630b873fe:/go/src/github.com/docker/docker# hack/make.sh binary
   252  
   253      You only call `hack/make.sh` to build a binary _inside_ a Docker
   254      development container as you are now. On your host, you'll use `make`
   255      commands (more about this later). 
   256  
   257      As it makes the binary, the `make.sh` script reports the build's progress.
   258      When the command completes successfully, you should see the following
   259      output:
   260  
   261  	---> Making bundle: binary (in bundles/1.5.0-dev/binary)
   262  	Created binary: /go/src/github.com/docker/docker/bundles/1.5.0-dev/binary/docker-1.5.0-dev
   263  	
   264  5. List all the contents of the `binary` directory.
   265  
   266          root@5f8630b873fe:/go/src/github.com/docker/docker#  ls bundles/1.5.0-dev/binary/
   267          docker  docker-1.5.0-dev  docker-1.5.0-dev.md5  docker-1.5.0-dev.sha256
   268  
   269      You should see that `binary` directory, just as it sounds, contains the
   270      made binaries.
   271  
   272  
   273  6. Copy the `docker` binary to the `/usr/bin` of your container.
   274  
   275          root@5f8630b873fe:/go/src/github.com/docker/docker#  cp bundles/1.5.0-dev/binary/docker /usr/bin
   276  
   277  7. Inside your container, check your Docker version.
   278  
   279          root@5f8630b873fe:/go/src/github.com/docker/docker# docker --version
   280          Docker version 1.5.0-dev, build 6e728fb
   281  
   282      Inside the container you are running a development version. This is the version
   283      on the current branch. It reflects the value of the `VERSION` file at the
   284      root of your `docker-fork` repository.
   285  
   286  8. Start a `docker` daemon running inside your container.
   287  
   288          root@5f8630b873fe:/go/src/github.com/docker/docker#  docker daemon -D
   289  
   290      The `-dD` flag starts the daemon in debug mode. You'll find this useful
   291      when debugging your code.
   292  
   293  9. Bring up one of the terminals on your local host.
   294  
   295  
   296  10. List your containers and look for the container running the `dry-run-test` image.
   297  
   298          $ docker ps
   299  
   300      <table class="code">
   301        <tr>
   302          <th>CONTAINER ID</th>
   303          <th>IMAGE</th>
   304          <th>COMMAND</th>
   305          <th>CREATED</th>
   306          <th>STATUS</th>
   307          <th>PORTS</th>
   308          <th>NAMES</th>
   309        </tr>
   310        <tr>
   311          <td>474f07652525</td>
   312          <td>dry-run-test:latest</td>
   313          <td>"hack/dind /bin/bash</td>
   314          <td>14 minutes ago</td>
   315          <td>Up 14 minutes</td>
   316          <td></td>
   317          <td>tender_shockley</td>
   318        </tr>
   319      </table>
   320  
   321      In this example, the container's name is `tender_shockley`; yours will be
   322      different.
   323  
   324  11. From the terminal, start another shell on your Docker development container.
   325  
   326          $ docker exec -it tender_shockley bash
   327  
   328      At this point, you have two terminals both with a shell open into your
   329      development container. One terminal is running a debug session. The other
   330      terminal is displaying a `bash` prompt.
   331  
   332  12. At the prompt, test the Docker client by running the `hello-world` container.	
   333  
   334          root@9337c96e017a:/go/src/github.com/docker/docker#  docker run hello-world
   335  
   336      You should see the image load and return. Meanwhile, you
   337      can see the calls made via the debug session in your other terminal.
   338  
   339      ![List example](/project/images/three_running.png)
   340  
   341  
   342  ## Restart a container with your source
   343  
   344  At this point, you have experienced the "Docker inception" technique. That is,
   345  you have:
   346  
   347  * built a Docker image from the Docker repository
   348  * created and started a Docker development container from that image
   349  * built a Docker binary inside of your Docker development container
   350  * launched a `docker` daemon using your newly compiled binary
   351  * called the `docker` client to run a `hello-world` container inside
   352    your development container
   353  
   354  When you really get to developing code though, you'll want to iterate code
   355  changes and builds inside the container. For that you need to mount your local
   356  Docker repository source into your Docker container. Try that now.
   357  
   358  1. If you haven't already, exit out of BASH shells in your running Docker
   359  container.
   360  
   361      If you have followed this guide exactly, exiting out your BASH shells stops
   362      the running container. You can use the `docker ps` command to verify the
   363      development container is stopped. All of your terminals should be at the
   364      local host prompt.
   365  
   366  2. Choose a terminal and make sure you are in your `docker-fork` repository.
   367  
   368          $ pwd
   369          /Users/mary/go/src/github.com/moxiegirl/docker-fork
   370  
   371      Your location will be different because it reflects your environment. 
   372  
   373  3. Create a container using `dry-run-test`, but this time, mount your repository
   374  onto the `/go` directory inside the container.
   375  
   376          $  docker run --privileged --rm -ti -v `pwd`:/go/src/github.com/docker/docker dry-run-test /bin/bash
   377  
   378      When you pass `pwd`, `docker` resolves it to your current directory.
   379  
   380  4. From inside the container, list your `binary` directory.
   381  
   382          root@074626fc4b43:/go/src/github.com/docker/docker# ls bundles/1.5.0-dev/binary
   383          ls: cannot access binary: No such file or directory
   384  
   385      Your `dry-run-test` image does not retain any of the changes you made inside
   386      the container.  This is the expected behavior for a container. 
   387  
   388  5. In a fresh terminal on your local host, change to the `docker-fork` root.
   389  
   390          $ cd ~/repos/docker-fork/
   391  
   392  6. Create a fresh binary, but this time, use the `make` command.
   393  
   394          $ make BINDDIR=. binary
   395  
   396      The `BINDDIR` flag is only necessary on Mac OS X but it won't hurt to pass
   397      it on Linux command line. The `make` command, like the `make.sh` script
   398      inside the container, reports its progress. When the make succeeds, it
   399      returns the location of the new binary.
   400  
   401  
   402  7. Back in the terminal running the container, list your `binary` directory.
   403  
   404          root@074626fc4b43:/go/src/github.com/docker/docker# ls bundles/1.5.0-dev/binary
   405          docker	docker-1.5.0-dev  docker-1.5.0-dev.md5	docker-1.5.0-dev.sha256 
   406  
   407      The compiled binaries created from your repository on your local host are
   408      now available inside your running Docker development container.
   409  
   410  8. Repeat the steps you ran in the previous procedure.
   411  
   412      * copy the binary inside the development container using
   413        `cp bundles/1.5.0-dev/binary/docker /usr/bin`
   414      * start `docker daemon -D` to launch the Docker daemon inside the container
   415      * run `docker ps` on local host to get the development container's name
   416      * connect to your running container `docker exec -it container_name bash`
   417      * use the `docker run hello-world` command to create and run a container 
   418        inside your development container
   419  
   420  ## Where to go next
   421  
   422  Congratulations, you have successfully achieved Docker inception. At this point,
   423  you've set up your development environment and verified almost all the essential
   424  processes you need to contribute. Of course, before you start contributing, 
   425  [you'll need to learn one more piece of the development environment, the test
   426  framework](/project/test-and-docs/).