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