diff --git a/engine/getstarted/step_four.md b/engine/getstarted/step_four.md
index 3261376b21..c1cb13e72b 100644
--- a/engine/getstarted/step_four.md
+++ b/engine/getstarted/step_four.md
@@ -9,131 +9,183 @@ title: Build your own image
---
The `whalesay` image could be improved. It would be nice if you didn't have to
-think of something to say. And you type a lot to get `whalesay` to talk.
+think of something to say and you didn't need to type as much to get `whalesay`
+to talk.
- docker run docker/whalesay cowsay boo-boo
+```bash
+docker run docker/whalesay cowsay boo-boo
+```
-In this next section, you will improve the `whalesay` image by building a new version that "talks on its own" and requires fewer words to run.
+In this next section, you will improve the `whalesay` image by building a new
+version that "talks on its own" and requires fewer words to run.
## Step 1: Write a Dockerfile
-In this step, you use your favorite text editor to write a short Dockerfile. A
-Dockerfile describes the software that is "baked" into an image. It isn't just
-ingredients though, it can tell the software what environment to use or what
-commands to run. Your recipe is going to be very short.
+In this step, you use a text editor to write a short Dockerfile. A Dockerfile
+is a recipe which describes the files, environment, and commands that make up an
+image. Your recipe is going to be very short.
-1. Go back to your command terminal window.
+You run these steps in a terminal window on Linux or macOS, or a command prompt
+on Windows. Remember that if you are using macOS or Windows, you are still
+creating an image which runs on Linux.
-2. Make a new directory by typing `mkdir mydockerbuild` and pressing RETURN.
+1. Make a new directory. If you're on Windows, use `md` instead of `mkdir`.
- $ mkdir mydockerbuild
+ ```bash
+ $ mkdir mydockerbuild
+ ```
- This directory serves as the "context" for your build. The context just means it contains all the things you need to build your image.
+ This directory will contain all the things you need to build your image.
+ Right now, it's empty.
-3. Change to your new directory.
+2. Change to your new directory. Whether you're on Linux, macOS, or Windows,
+ the `cd` command is the same.
- $ cd mydockerbuild
+ ```bash
+ $ cd mydockerbuild
+ ```
- Right now the directory is empty.
+3. Edit a new text file named `Dockerfile` in the current directory, using a
+ text editor such as `nano` or `vi` on Linux or Mac, or `notepad` on Windows.
-4. Create a Dockerfile in the directory by typing `touch Dockerfile` and pressing RETURN.
+ **Linux or Mac**:
- $ touch Dockerfile
+ ```bash
+ $ nano Dockerfile
+ ```
- The command appears to do nothing but it actually creates the Dockerfile in the current directory. Just type `ls` to see it.
+ **Windows**:
- $ ls
- Dockerfile
+ ```none
+ C:\> notepad Dockerfile
+ ```
-5. Open the `Dockerfile` in a visual text editor like Atom or Sublime, or a text based editor like vi, or nano.
+4. Add a `FROM` statement by copying the following line into the file:
-6. Add a line to the file like this:
+ ```Dockerfile
+ FROM docker/whalesay:latest
+ ```
- FROM docker/whalesay:latest
+ The `FROM` keyword tells Docker which image your image is based on.
+ Whalesay is cute and has the `cowsay` program already, so we'll start
+ there.
- The `FROM` keyword tells Docker which image your image is based on. Whalesay is cute and has the `cowsay` program already, so we'll start there.
+5. Add a `RUN` statement which will install the `fortunes` program into the
+ image.
-7. Now, add the `fortunes` program to the image.
+ ```Dockerfile
+ RUN apt-get -y update && apt-get install -y fortunes
+ ```
- RUN apt-get -y update && apt-get install -y fortunes
+ The `whalesay` image is based on Ubuntu, which uses `apt-get` to install
+ packages. These two commands refresh the list of packages available to the
+ image and install the `fortunes` program into it. The `fortunes` program has
+ prints out wise sayings for our whale to say.
- The `fortunes` program has a command that prints out wise sayings for our whale to say. So, the first step is to install it. This line installs the software into the image.
+6. Add a `CMD` statement, which tells the image the final command to run after
+ its environment is set up. This command runs `fortune -a` and sends its
+ output to the `cowsay` command.
-8. Once the image has the software it needs, you instruct the software to run
- when the image is loaded.
+ ```Dockerfile
+ CMD /usr/games/fortune -a | cowsay
+ ```
- CMD /usr/games/fortune -a | cowsay
+7. Check your work. Your file should look just like this:
- This line tells the `fortune` program to pass a nifty quote to the `cowsay` program.
+ ```Dockerfile
+ FROM docker/whalesay:latest
+ RUN apt-get -y update && apt-get install -y fortunes
+ CMD /usr/games/fortune -a | cowsay
+ ```
-9. Check your work, your file should look like this:
-
- FROM docker/whalesay:latest
- RUN apt-get -y update && apt-get install -y fortunes
- CMD /usr/games/fortune -a | cowsay
-
-10. Save and close your Dockerfile.
-
- At this point, you have all your software ingredients and behaviors described in a Dockerfile. You are ready to build a new image.
+8. Save the file and close the text editor. At this point, your software recipe
+ is described in the `Dockerfile` file. You are ready to build a new image.
## Step 2: Build an image from your Dockerfile
-1. At the command line, make sure the Dockerfile is in the current directory by typing `cat Dockerfile`
+While you are in the `mydockerbuild` directory, build the image using the
+`docker build` image. The `-t` parameter gives your image a tag, so you can
+run it more easily later. Don't forget the `.` command, which tells the
+`docker build` command to look in the current directory for a file called
+`Dockerfile`. This command works the same in Linux, macOS, or Windows.
- $ cat Dockerfile
- FROM docker/whalesay:latest
+```bash
+$ docker build -t docker-whale .
- RUN apt-get -y update && apt-get install -y fortunes
+Sending build context to Docker daemon 2.048 kB
+...snip...
+Removing intermediate container cb53c9d09f3b
+Successfully built c2c3152907b5
+```
- CMD /usr/games/fortune -a | cowsay
-
-2. Now, build your new image by typing the `docker build -t docker-whale .` command in your terminal (don't forget the . period).
-
- $ docker build -t docker-whale .
- Sending build context to Docker daemon 2.048 kB
- ...snip...
- Removing intermediate container a8e6faa88df3
- Successfully built 7d9495d03763
-
- The command takes several seconds to run and reports its outcome. Before
- you do anything with the new image, take a minute to learn about the
- Dockerfile build process.
+The command takes several seconds to run and reports its outcome. Keep reading
+to learn a little more about what the output means and what happens when you
+build an image.
## Step 3: Learn about the build process
-The `docker build -t docker-whale .` command takes the `Dockerfile` in the
-current directory, and builds an image called `docker-whale` on your local
-machine. The command takes about a minute and its output looks really long and
-complex. In this section, you learn what each message means.
+The `docker build -t docker-whale .` command reads the `Dockerfile` in the
+current directory and processes its instructions one by one to build an image
+called `docker-whale` on your local machine. The command takes about a minute
+and its output looks really long and complex. In this section, you learn what
+each message means.
-First Docker checks to make sure it has everything it needs to build.
+1. Docker checks to make sure it has everything it needs to build. This
+ generates this message:
+ ```none
Sending build context to Docker daemon 2.048 kB
+ ```
-Then, Docker loads with the `whalesay` image. It already has this image
-locally as you might recall from the last page. So, Docker doesn't need to
-download it.
+2. Docker checks to see whether it already has the `whalesay` image locally and
+ pulls it from Docker hub if not. In this case, the image already exists
+ locally because you pulled it in a previous task. This corresponds to `FROM`
+ statement in the Dockerfile, and generates this message:
+ ```none
Step 1 : FROM docker/whalesay:latest
- ---> fb434121fc77
+ ---> 6b362a9f73eb
+ ```
-Docker moves onto the next step which is to update the `apt-get` package
-manager. This takes a lot of lines, no need to list them all again here.
+ At the end of each step, an ID is printed. This is the ID of the layer that
+ was created by this step. Each line in a Dockerfile corresponds to a layer
+ in the image. Your ID will be different.
+3. Docker starts up temporary container running the `whalesay` image (the
+ `Running in` line below). In the temporary container, Docker runs the next
+ command in the Dockerfile, which is the `RUN` command, which installs the
+ `fortune` command. This generates a lot of lines of output, just like you
+ would see if you were manually running the `apt-get` commands on an Ubuntu
+ host.
+
+ ```none
Step 2 : RUN apt-get -y update && apt-get install -y fortunes
- ---> Running in 27d224dfa5b2
+ ---> Running in 05d4eda04526
Ign http://archive.ubuntu.com trusty InRelease
- Ign http://archive.ubuntu.com trusty-updates InRelease
- Ign http://archive.ubuntu.com trusty-security InRelease
+ Get:1 http://archive.ubuntu.com trusty-updates InRelease [65.9 kB]
+ Get:2 http://archive.ubuntu.com trusty-security InRelease [65.9 kB]
Hit http://archive.ubuntu.com trusty Release.gpg
- ....snip...
- Get:15 http://archive.ubuntu.com trusty-security/restricted amd64 Packages [14.8 kB]
- Get:16 http://archive.ubuntu.com trusty-security/universe amd64 Packages [134 kB]
+ Hit http://archive.ubuntu.com trusty Release
+ Get:3 http://archive.ubuntu.com trusty-updates/main Sources [480 kB]
+ Get:4 http://archive.ubuntu.com trusty-updates/restricted Sources [5921 B]
+ Get:5 http://archive.ubuntu.com trusty-updates/universe Sources [214 kB]
+ Get:6 http://archive.ubuntu.com trusty-updates/main amd64 Packages [1160 kB]
+ Get:7 http://archive.ubuntu.com trusty-updates/restricted amd64 Packages [20.4 kB]
+ Get:8 http://archive.ubuntu.com trusty-updates/universe amd64 Packages [505 kB]
+ Get:9 http://archive.ubuntu.com trusty-security/main Sources [157 kB]
+ Get:10 http://archive.ubuntu.com trusty-security/restricted Sources [4621 B]
+ Get:11 http://archive.ubuntu.com trusty-security/universe Sources [54.5 kB]
+ Get:12 http://archive.ubuntu.com trusty-security/main amd64 Packages [700 kB]
+ Get:13 http://archive.ubuntu.com trusty-security/restricted amd64 Packages [17.0 kB]
+ Get:14 http://archive.ubuntu.com trusty-security/universe amd64 Packages [191 kB]
+ Hit http://archive.ubuntu.com trusty/main Sources
+ Hit http://archive.ubuntu.com trusty/restricted Sources
+ Hit http://archive.ubuntu.com trusty/universe Sources
+ Hit http://archive.ubuntu.com trusty/main amd64 Packages
+ Hit http://archive.ubuntu.com trusty/restricted amd64 Packages
+ Hit http://archive.ubuntu.com trusty/universe amd64 Packages
+ Fetched 3640 kB in 11s (329 kB/s)
Reading package lists...
- ---> eb06e47a01d2
-
-Then, Docker installs the new `fortunes` software.
-
Reading package lists...
Building dependency tree...
Reading state information...
@@ -143,69 +195,129 @@ Then, Docker installs the new `fortunes` software.
x11-utils bsdmainutils
The following NEW packages will be installed:
fortune-mod fortunes fortunes-min librecode0
- 0 upgraded, 4 newly installed, 0 to remove and 3 not upgraded.
+ 0 upgraded, 4 newly installed, 0 to remove and 92 not upgraded.
Need to get 1961 kB of archives.
After this operation, 4817 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu/ trusty/main librecode0 amd64 3.6-21 [771 kB]
- ...snip......
+ Get:2 http://archive.ubuntu.com/ubuntu/ trusty/universe fortune-mod amd64 1:1.99.1-7 [39.5 kB]
+ Get:3 http://archive.ubuntu.com/ubuntu/ trusty/universe fortunes-min all 1:1.99.1-7 [61.8 kB]
+ Get:4 http://archive.ubuntu.com/ubuntu/ trusty/universe fortunes all 1:1.99.1-7 [1089 kB]
+ debconf: unable to initialize frontend: Dialog
+ debconf: (TERM is not set, so the dialog frontend is not usable.)
+ debconf: falling back to frontend: Readline
+ debconf: unable to initialize frontend: Readline
+ debconf: (This frontend requires a controlling tty.)
+ debconf: falling back to frontend: Teletype
+ dpkg-preconfigure: unable to re-open stdin:
+ Fetched 1961 kB in 19s (101 kB/s)
+ Selecting previously unselected package librecode0:amd64.
+ (Reading database ... 13116 files and directories currently installed.)
+ Preparing to unpack .../librecode0_3.6-21_amd64.deb ...
+ Unpacking librecode0:amd64 (3.6-21) ...
+ Selecting previously unselected package fortune-mod.
+ Preparing to unpack .../fortune-mod_1%3a1.99.1-7_amd64.deb ...
+ Unpacking fortune-mod (1:1.99.1-7) ...
+ Selecting previously unselected package fortunes-min.
+ Preparing to unpack .../fortunes-min_1%3a1.99.1-7_all.deb ...
+ Unpacking fortunes-min (1:1.99.1-7) ...
+ Selecting previously unselected package fortunes.
+ Preparing to unpack .../fortunes_1%3a1.99.1-7_all.deb ...
+ Unpacking fortunes (1:1.99.1-7) ...
+ Setting up librecode0:amd64 (3.6-21) ...
+ Setting up fortune-mod (1:1.99.1-7) ...
+ Setting up fortunes-min (1:1.99.1-7) ...
Setting up fortunes (1:1.99.1-7) ...
Processing triggers for libc-bin (2.19-0ubuntu6.6) ...
- ---> c81071adeeb5
- Removing intermediate container 23aa52c1897c
+ ---> dfaf993d4a2e
+ Removing intermediate container 05d4eda04526
+ ```
-Finally, Docker finishes the build and reports its outcome.
+ When the `RUN` command finishes, a new layer is created and the imtermediate
+ container is removed.
+4. A new intermediate container is created, and Docker adds a layer for the
+ `CMD` line in the Dockerfile, and removes the intermediate container.
+
+ ```none
Step 3 : CMD /usr/games/fortune -a | cowsay
---> Running in a8e6faa88df3
---> 7d9495d03763
Removing intermediate container a8e6faa88df3
Successfully built 7d9495d03763
+ ```
+
+You have now built an image called `docker-whale`.
## Step 4: Run your new docker-whale
-In this step, you verify the new images is on your computer and then you run your new image.
+Now you can verify that the new image is on your computer and you can run it.
-1. Open a command line terminal.
+1. In a terminal window or command prompt, type `docker images`, which lists
+ the images you have locally.
-2. Type `docker images` and press RETURN.
+ ```bash
+ $ docker images
- This command, you might remember, lists the images you have locally.
+ REPOSITORY TAG IMAGE ID CREATED SIZE
+ docker-whale latest c2c3152907b5 4 minutes ago 275.1 MB
+ docker/whalesay latest fb434121fc77 4 hours ago 247 MB
+ hello-world latest 91c95931e552 5 weeks ago 910 B
+ ```
- $ docker images
- REPOSITORY TAG IMAGE ID CREATED SIZE
- docker-whale latest 7d9495d03763 4 minutes ago 273.7 MB
- docker/whalesay latest fb434121fc77 4 hours ago 247 MB
- hello-world latest 91c95931e552 5 weeks ago 910 B
+2. Run your new image by typing `docker run docker-whale`.
-3. Run your new image by typing `docker run docker-whale` and pressing RETURN.
+ ```bash
- $ docker run docker-whale
- _________________________________________
- / "He was a modest, good-humored boy. It \
- \ was Oxford that made him insufferable." /
- -----------------------------------------
- \
- \
- \
- ## .
- ## ## ## ==
- ## ## ## ## ===
- /""""""""""""""""___/ ===
- ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
- \______ o __/
- \ \ __/
- \____\______/
+ $ docker run docker-whale
+
+ ______________________________________
+ < You will be successful in your work. >
+ --------------------------------------
+ \
+ \
+ \
+ ## .
+ ## ## ## ==
+ ## ## ## ## ===
+ /""""""""""""""""___/ ===
+ ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
+ \______ o __/
+ \ \ __/
+ \____\______/
+ ```
+
+ The whale is now a lot smarter. It comes up with its own thoughts and it takes
+ less typing to run. You may also notice that Docker didn't have to download
+ anything, because you built the image locally.
+
+3. Just for fun, run it again.
+
+ ```bash
+ _______________________________________
+ / If everything seems to be going well, \
+ | you have obviously overlooked |
+ \ something. /
+ ---------------------------------------
+ \
+ \
+ \
+ ## .
+ ## ## ## ==
+ ## ## ## ## ===
+ /""""""""""""""""___/ ===
+ ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
+ \______ o __/
+ \ \ __/
+ \____\______/
+
+ ```
+
+Your whale now has a mind of its own, but if you don't like what it says,
+just run it again!
-As you can see, you've made the whale a lot smarter. It finds its own
-things to say and the command line is a lot shorter! You may also notice
-that Docker didn't have to download anything. That is because the image was
-built locally and is already available.
## Where to go next
-On this page, you learned to build an image by writing your own Dockerfile.
-You ran your image in a container. You also just used Linux from your Mac yet
-again. In the next section, you take the first step in sharing your image by
-[creating a Docker Hub account](step_five.md).
-
+Now that you have learned to build an image and run it, you can learn to share
+the image by [creating a Docker Hub account](step_five.md).