github.com/grubernaut/docker@v1.6.0-rc2/docs/sources/project/set-up-dev-env.md (about)

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