github.com/circular-dark/docker@v1.7.0/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 Boot2Docker 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 -dD 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 -dD` 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/).