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