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  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  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  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/).