Browse code

Adding new Dockerfile Best Practices doc, and links thereto.

Docker-DCO-1.1-Signed-off-by: Fred Lifton <fred.lifton@docker.com> (github: fredlf)

Fred Lifton authored on 2014/09/24 06:21:00
Showing 6 changed files
... ...
@@ -84,17 +84,18 @@ pages:
84 84
 - ['articles/networking.md', 'Articles', 'Advanced networking']
85 85
 - ['articles/security.md', 'Articles', 'Security']
86 86
 - ['articles/https.md', 'Articles', 'Running Docker with HTTPS']
87
-- ['articles/host_integration.md', 'Articles', 'Automatically starting Containers']
87
+- ['articles/host_integration.md', 'Articles', 'Automatically starting containers']
88
+- ['articles/baseimages.md', 'Articles', 'Creating a base image']
89
+- ['articles/dockerfile_best-practices.md', 'Articles', 'Best practices for writing Dockerfiles']
88 90
 - ['articles/certificates.md', 'Articles', 'Using certificates for repository client verification']
89 91
 - ['articles/using_supervisord.md', 'Articles', 'Using Supervisor']
90 92
 - ['articles/cfengine_process_management.md', 'Articles', 'Process management with CFEngine']
91 93
 - ['articles/puppet.md', 'Articles', 'Using Puppet']
92 94
 - ['articles/chef.md', 'Articles', 'Using Chef']
93 95
 - ['articles/dsc.md', 'Articles', 'Using PowerShell DSC']
94
-- ['articles/ambassador_pattern_linking.md', 'Articles', 'Cross-Host linking using Ambassador Containers']
96
+- ['articles/ambassador_pattern_linking.md', 'Articles', 'Cross-Host linking using ambassador containers']
95 97
 - ['articles/runmetrics.md', 'Articles', 'Runtime metrics']
96
-- ['articles/baseimages.md', 'Articles', 'Creating a Base Image']
97
-- ['articles/b2d_volume_resize.md', 'Articles', 'Increasing a Boot2Docker Volume']
98
+- ['articles/b2d_volume_resize.md', 'Articles', 'Increasing a Boot2Docker volume']
98 99
 
99 100
 # Reference
100 101
 - ['reference/index.md', '**HIDDEN**']
... ...
@@ -55,5 +55,14 @@ image to base your new minimal containers `FROM`:
55 55
     COPY true-asm /true
56 56
     CMD ["/true"]
57 57
 
58
-The Dockerfile above is from extremely minimal image - [tianon/true](
58
+The `Dockerfile` above is from an extremely minimal image - [tianon/true](
59 59
 https://github.com/tianon/dockerfiles/tree/master/true).
60
+
61
+## More resources
62
+
63
+There are lots more resources available to help you write your 'Dockerfile`.
64
+
65
+* There's a [complete guide to all the instructions](/reference/builder/) available for use in a `Dockerfile` in the reference section.
66
+* To help you write a clear, readable, maintainable `Dockerfile`, we've also
67
+written a [`Dockerfile` Best Practices guide](/articles/dockerfile_best-practices).
68
+* If you're working on an Official Repo, be sure to check out the [Official Repo Guidelines](/docker-hub/official_repos/).
60 69
new file mode 100644
... ...
@@ -0,0 +1,333 @@
0
+page_title: Best Practices for Writing Dockerfiles
1
+page_description: Hints, tips and guidelines for writing clean, reliable Dockerfiles
2
+page_keywords: Examples, Usage, base image, docker, documentation, dockerfile, best practices, hub, official repo
3
+
4
+
5
+ # Best Practices for Writing `Dockerfile`s
6
+
7
+## Overview
8
+
9
+Docker can build images automatically by reading the instructions from a
10
+`Dockerfile`, a text file that contains all the commands, in order, needed to
11
+build a given image. `Dockerfile`s adhere to a specific format and use a
12
+specific set of instructions. You can learn the basics on the 
13
+[Dockerfile Reference](https://docs.docker.com/reference/builder/) page. If
14
+you’re new to writing `Dockerfile`s, you should start there.
15
+
16
+This document covers the best practices and methods recommended by Docker,
17
+Inc., for creating easy-to-use, effective `Dockerfile`s. We strongly suggest
18
+you follow these recommendations (in fact, if you’re creating an Official
19
+Image, you *must* adhere to these practices).
20
+
21
+You can see many of these practices and recommendations in action in the [buildpack-deps `Dockerfile`](https://github.com/docker-library/buildpack-deps/blob/master/jessie/Dockerfile).
22
+
23
+> Note: for more detailed explanations of any of the Dockerfile commands
24
+>mentioned here, visit the [Dockerfile Reference](https://docs.docker.com/reference/builder/) page.
25
+
26
+## General Guidelines and Recommendations
27
+
28
+### Containers should be ephemeral
29
+
30
+The container produced by the image your `Dockerfile` defines should be as
31
+ephemeral as possible. “Ephemeral” here means that it can be stopped and
32
+destroyed and a new one built and put in place with an absolute minimum of
33
+set-up and configuration.
34
+
35
+### Use a [`.dockerignore` file](https://docs.docker.com/reference/builder/#the-dockerignore-file)
36
+
37
+For faster uploading and efficiency, you should make use of a `.dockerignore`
38
+file to exclude files or directories from the build context. For example, unless
39
+`.git` is needed by your build process or scripts, you should add it to
40
+`.dockerignore`, which can save many megabytes worth of upload time.
41
+
42
+### Avoid installing unnecessary packages
43
+
44
+You should avoid installing extra or unnecessary packages just because they
45
+might be “nice to have.” For example, you don’t need to include a text editor
46
+in a database image.
47
+
48
+### Run only one process per container
49
+
50
+In almost all cases, you should only run a single process in a single
51
+container. Decoupling applications into multiple containers makes it much
52
+easier to scale horizontally and reuse containers. If that service depends on
53
+another service, make use of [container linking](https://docs.docker.com/userguide/dockerlinks/).
54
+
55
+### Minimize the number of layers
56
+
57
+You need to find the balance between readability (and thus long-term
58
+maintainability) of the `Dockerfile` and minimizing the number of layers it
59
+uses. Be strategic and cautious about the number of layers you use.
60
+
61
+### Sort multi-line arguments
62
+
63
+Whenever possible, ease later changes by sorting multi-line arguments
64
+alphanumerically. This will help you avoid duplication of packages and make the
65
+list much easier to update. This also makes PRs a lot easier to read and
66
+review. Adding a space before a backslash (`\`) helps as well. 
67
+
68
+Here’s an example from the [`buildpack-deps` image](https://github.com/docker-library/buildpack-deps):
69
+
70
+ RUN apt-get update && apt-get install -y \
71
+    bzr \
72
+    cvs \
73
+    git \
74
+    mercurial \
75
+    subversion
76
+
77
+## The `Dockerfile` instructions
78
+
79
+This section contains specific recommendations for the correct usage of the
80
+various instructions contained in a `Dockerfile`.
81
+
82
+### [`FROM`](https://docs.docker.com/reference/builder/#from)
83
+
84
+Whenever possible, use Official Repositories as the basis for your image. We
85
+recommend the [Debian image](https://registry.hub.docker.com/_/debian/) since
86
+it’s very tightly controlled and kept extremely minimal (currently under 100
87
+mb), while still being a full distribution.
88
+
89
+### [`RUN`](https://docs.docker.com/reference/builder/#run)
90
+
91
+As always, to make your `Dockerfile` more readable, understandable, and
92
+maintainable, put long or complex statements on multiple lines separated with
93
+backslashes.
94
+
95
+Probably the most common use-case for `RUN` is an application of `apt-get`.
96
+When using `apt-get`, here a few things to keep in mind:
97
+
98
+* Don’t do simply `RUN apt-get update` on a single line. This will cause
99
+caching issues if the referenced archive gets updated, which will make your
100
+subsequent `apt-get install` fail without comment.
101
+
102
+* For the most part, to keep your code more readable and maintainable, avoid
103
+`RUN apt-get install -y package-foo && apt-get install -y package-bar`.
104
+
105
+* Avoid `RUN apt-get upgrade` or `dist-upgrade` since many of the “essential” packages from the base images will fail to upgrade inside an unprivileged container. If a base package is out of date, you should contact its maintainers. If you know there’s a particular package, `foo`, that needs to be updated, use `apt-get install -y foo` and it will update automatically.
106
+
107
+* Do use `RUN apt-get update && apt-get install -y package-bar package-foo
108
+package-baz`. Writing the instruction this way not only makes it easier to read
109
+and maintain, but also, by including `apt-get update`, ensures that the cache
110
+will naturally be busted and the latest versions will be installed with no
111
+further coding or manual intervention required.
112
+
113
+* Further natural cache-busting can be realized by version-pinning packages
114
+(e.g., `package-foo=1.3*`) since it will force retrieval of that version
115
+regardless of what’s in the cache.
116
+
117
+Forming your `apt-get` code this way will greatly ease maintenance and reduce
118
+failures due to unanticipated changes in required packages.
119
+
120
+#### Example
121
+
122
+Below is a well-formed `RUN` instruction that demonstrates the above
123
+recommendations. Note that the last package, `s3cmd`, specifies a version
124
+`1.1.0*`, which will bust the `apt-get` cache and force the installation of
125
+that version (which in this case had a new, required feature). 
126
+
127
+    RUN apt-get update && apt-get install -y \
128
+        aufs-tools \
129
+        automake \
130
+        btrfs-tools \
131
+        build-essential \
132
+        curl \
133
+        dpkg-sig \
134
+        git \
135
+        iptables \
136
+        libapparmor-dev \
137
+        libcap-dev \
138
+        libsqlite3-dev \
139
+        lxc=1.0* \
140
+        mercurial \
141
+        parallel \
142
+        reprepro \
143
+        ruby1.9.1 \
144
+        ruby1.9.1-dev \
145
+        s3cmd=1.1.0*
146
+
147
+### [`CMD`](https://docs.docker.com/reference/builder/#cmd)
148
+
149
+The `CMD` instruction should be used to run the software contained by your
150
+image, along with any arguments.  `CMD` should almost always be used in the
151
+form of `CMD [“executable”, “param1”, “param2”…]`. Thus, if the image is for a
152
+service (Apache, Rails, etc.), you would run something like `CMD ["apache2",
153
+"-DFOREGROUND"]`. Indeed, this form of the instruction is recommended for any
154
+service-based image.
155
+
156
+In most other cases, `CMD` should be given an interactive shell (bash, python,
157
+perl, etc). For example, `CMD ["perl", "-de0"]`, `CMD ["python"]`, or `CMD
158
+[“php”, “-a”]`. Using this form means that when you execute something like
159
+`docker run -it python`, you’ll get dropped into a usable shell, ready to go.
160
+`CMD` should rarely be used in the manner of `CMD [“param”, “param”]` in
161
+conjunction with [`ENTRYPOINT`](https://docs.docker.com/reference/builder/#entrypoint), unless
162
+you and your expected users are already quite familiar with how `ENTRYPOINT`
163
+works. 
164
+
165
+### [`EXPOSE`](https://docs.docker.com/reference/builder/#expose)
166
+
167
+The `EXPOSE` instruction is the way you tell the users of your image where to
168
+connect. Consequently, you should use the common, traditional port for your
169
+application. For example, an image containing the Apache web server would use
170
+`EXPOSE 80` while an image containing MongoDB would use `EXPOSE 27017` and so
171
+on.
172
+
173
+For external access, your users can execute `docker run` with a flag indicating
174
+how to map the specified port to the port of their choice.
175
+For container linking, Docker provides environment variables for the path from
176
+the recipient container back to the source (ie, `MYSQL_PORT_3306_TCP`).
177
+
178
+### [`ENV`](https://docs.docker.com/reference/builder/#env)
179
+
180
+In order to make new software easier to run, you can use `ENV` to update the
181
+`PATH` environment variable for the software your container installs. For
182
+example, `ENV PATH /usr/local/nginx/bin:$PATH` will ensure that `CMD [“nginx”]`
183
+just works.
184
+
185
+The `ENV` instruction is also useful for providing required environment
186
+variables specific to services you wish to containerize, such as Postgres’s
187
+`PGDATA`.
188
+
189
+Lastly, `ENV` can also be used to set commonly used version numbers so that
190
+version bumps are easier to maintain, as seen in the following example:
191
+
192
+    ENV PG_MAJOR 9.3
193
+    ENV PG_VERSION 9.3.4
194
+    RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && …
195
+    ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
196
+
197
+Similar to having constant variables in a program (as opposed to hard-coding
198
+values), this approach lets you change a single `ENV` instruction to
199
+auto-magically bump the version of the software in your container.
200
+
201
+### [`ADD`](https://docs.docker.com/reference/builder/#add) or
202
+[`COPY`](https://docs.docker.com/reference/builder/#copy)
203
+
204
+Although `ADD` and `COPY` are functionally similar, generally speaking, `COPY`
205
+is preferred. That’s because it’s more transparent than `ADD`. `COPY` only
206
+supports the basic copying of local files into the container, while `ADD` has
207
+some features (like local-only tar extraction and remote URL support) that are
208
+not immediately obvious.
209
+
210
+Consequently, the best use for `ADD` is local tar file auto-extraction into the
211
+image, as in `ADD rootfs.tar.xz /`.
212
+Because image size matters, using `ADD` to fetch packages from remote URLs is
213
+strongly discouraged; you should use `curl` or `wget` instead. That way you can, where possible, delete the files you no longer need after they’ve been
214
+extracted without having to add another layer in your image. For example, you
215
+should avoid doing things like:
216
+
217
+    ADD http://example.com/big.tar.xz /usr/src/things/
218
+    RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
219
+    RUN make -C /usr/src/things all
220
+
221
+And instead, do something like:
222
+    RUN mdkir -p /usr/src/things \
223
+    && curl -SL http://example.com/big.tar.gz \
224
+    | tar -xJC /usr/src/things \
225
+    && make -C /usr/src/things all
226
+
227
+For other items (files, directories) that do not require `ADD`’s tar
228
+auto-extraction capability, you should always use `COPY`. 
229
+
230
+### [`ENTRYPOINT`](https://docs.docker.com/reference/builder/#entrypoint)
231
+
232
+The best use for `ENTRYPOINT` is as a helper script. Using `ENTRYPOINT` for
233
+other tasks can make your code harder to understand. For example, `docker run
234
+-it official-image bash` is much easier to understand than `docker run -it
235
+--entrypoint bash official-image -i`, especially for Docker beginners.
236
+
237
+In order to avoid a situation where commands are run without clear visibility
238
+to the user, make sure your script ends with something like `exec "$@"`. After
239
+the entrypoint completes, the script will transparently bootstrap the command
240
+invoked by the user, making what has been run clear to the user (for example,
241
+`docker run -it mysql mysqld --some --flags` will transparently run `mysqld
242
+--some --flags` after `ENTRYPOINT` runs `initdb`).
243
+
244
+For example, let’s look at the `Dockerfile` for the
245
+[Postgres Official Image](https://github.com/docker-library/postgres).
246
+It refers to the following script: 
247
+
248
+```bash
249
+#!/bin/bash
250
+set -e
251
+
252
+if [ "$1" = 'postgres' ]; then
253
+    chown -R postgres "$PGDATA"
254
+
255
+    if [ -z "$(ls -A "$PGDATA")" ]; then
256
+        gosu postgres initdb
257
+    fi
258
+
259
+    exec gosu postgres "$@"
260
+fi
261
+
262
+exec "$@"
263
+```
264
+
265
+That script then gets copied into the container and the run via `ENTRYPOINT` on
266
+container startup: 
267
+
268
+    COPY ./docker-entrypoint.sh /
269
+    ENTRYPOINT ["/docker-entrypoint.sh"]
270
+
271
+### [`VOLUME`](https://docs.docker.com/reference/builder/#volume)
272
+
273
+`VOLUME` should be used to expose any database storage area, configuration
274
+storage, or files/folders created by your docker container. You are strongly
275
+encouraged to use `VOLUME` for any mutable and/or user-serviceable parts of
276
+your image.
277
+
278
+### [`USER`](https://docs.docker.com/reference/builder/#user)
279
+
280
+If a service can run without privileges, use `USER` to change to a non-root
281
+user. Start by creating the user and group in the `Dockerfile` with something
282
+like `RUN groupadd -r postgres && useradd -r -g postgres postgres`.
283
+
284
+>**Note** that users/groups in an image get assigned nondeterministic UID/GID in
285
+>that the “next” UID/GID will be assigned regardless of image rebuilds. So, if
286
+>it’s critical, you should assign an explicit UID/GID.
287
+
288
+You should avoid installing or using `sudo` since it has unpredictable TTY and
289
+signal-forwarding behavior that can cause more more problems than it solves. If
290
+you absolutely need functionality similar to `sudo` (e.g., initializing the
291
+daemon as root but running it as non-root), you may be able to use
292
+[“gosu”](https://github.com/tianon/gosu). 
293
+
294
+Lastly, to reduce layers and complexity, try to minimize switching `USER` back
295
+and forth frequently.
296
+
297
+### [`WORKDIR`](https://docs.docker.com/reference/builder/#workdir)
298
+
299
+For clarity and reliability, you should always use absolute paths for your
300
+`WORKDIR`. Also, you should use `WORKDIR` instead of  proliferating
301
+instructions like `RUN cd … && do-something`, which are hard to read,
302
+troubleshoot, and maintain.
303
+
304
+### [`ONBUILD`](https://docs.docker.com/reference/builder/#onbuild)
305
+
306
+`ONBUILD` is only useful for images that are going to be built `FROM` a given
307
+image. For example, you would use `ONBUILD` for a language stack image that
308
+builds arbitrary user software written in that language within the
309
+`Dockerfile`, as you can see in [Ruby’s `ONBUILD` variants](https://github.com/docker-library/ruby/blob/master/2.1/onbuild/Dockerfile). 
310
+
311
+Images built from `ONBUILD` should get a separate tag, for example:
312
+`ruby:1.9-onbuild` or `ruby:2.0-onbuild`.
313
+
314
+Be careful when putting `ADD` or `COPY` in `ONBUILD`. The “onbuild” image will
315
+fail catastrophically if it is missing the the resource being added. Adding a
316
+separate tag, as recommended above, will help mitigate this by allowing the
317
+`Dockerfile` author to make a choice.
318
+
319
+## Examples For Official Repositories
320
+
321
+These Official Repos have exemplary `Dockerfile`s:
322
+* [Go](https://registry.hub.docker.com/_/golang/)
323
+* [Perl](https://registry.hub.docker.com/_/perl/)
324
+* [Hy](https://registry.hub.docker.com/_/hylang/)
325
+* [Rails](https://registry.hub.docker.com/_/rails)
326
+
327
+## Additional Resources:
328
+
329
+* [Dockerfile Reference](https://docs.docker.com/reference/builder/#onbuild)
330
+* [More about Base Images](https://docs.docker.com/articles/baseimages/)
331
+* [More about Automated Builds](https://docs.docker.com/docker-hub/builds/)
332
+* [Guidelines for Creating Official Repositories](https://docs.docker.com/docker-hub/official_repos/)
0 333
\ No newline at end of file
... ...
@@ -6,10 +6,11 @@ page_keywords: Docker, docker, registry, accounts, plans, Dockerfile, Docker Hub
6 6
 
7 7
 ## Introduction
8 8
 
9
-You’ve been given the job of creating an image for an Official Repository hosted on
10
-[Docker Hub Registry](https://registry.hub.docker.com/). These are Docker, Inc.’s
11
-guidelines for getting that task done. Even if you’re not planning to create an Official
12
-Repo, you can think of these guidelines as best practices for image creation generally.
9
+You’ve been given the job of creating an image for an Official Repository
10
+hosted on[Docker Hub Registry](https://registry.hub.docker.com/). These are
11
+Docker, Inc.’s guidelines for getting that task done. Even if you’re not
12
+planning to create an Official Repo, you can think of these guidelines as best
13
+practices for image creation generally.
13 14
 
14 15
 This document consists of three major sections:
15 16
 
... ...
@@ -21,38 +22,41 @@ This document consists of three major sections:
21 21
 
22 22
 ### A Git repository
23 23
 
24
-Your image needs to live in a Git repository, preferably on GitHub. (If you’d like to use
25
-a different provider, please [contact us](TODO: link) directly.) Docker **strongly**
26
-recommends that this repo be publicly accessible.
24
+Your image needs to live in a Git repository, preferably on GitHub. (If you’d
25
+like to use a different provider, please [contact us](mailto:feedback@docker.com)
26
+directly.) Docker **strongly** recommends that this repo be publicly
27
+accessible.
27 28
 
28
-If the repo is private or has otherwise limited access, you must provide a means of at
29
-least “read-only” access for both general users and for the docker-library maintainers,
30
-who need access for review and building purposes.
29
+If the repo is private or has otherwise limited access, you must provide a
30
+means of at least “read-only” access for both general users and for the docker-
31
+library maintainers, who need access for review and building purposes.
31 32
 
32 33
 ### A `Dockerfile`
33 34
 
34 35
 Complete information on `Dockerfile`s can be found in the [Reference section](https://docs.docker.com/reference/builder/).
35
-We also have a page discussing best practices for writing `Dockerfile`s (TODO: link).
36
+We also have a page discussing [best practices for writing `Dockerfile`s](/articles/dockerfile_best-practices).
36 37
 Your `Dockerfile` should adhere to the following:
37 38
 
38
-* It must be written either by using `FROM scratch` or be based on another, established
39
-Official Image.
40
-* It must follow `Dockerfile` best practices. These are discussed in the [Best Practices
41
-document](TODO: link). In addition, Docker, Inc. engineer Michael Crosby has a good
42
-discussion of Dockerfiles in this [blog post](http://crosbymichael.com/dockerfile-best-practices-take-2.html).
39
+* It must be written either by using `FROM scratch` or be based on another,
40
+established Official Image.
41
+* It must follow `Dockerfile` best practices. These are discussed in the
42
+[Best Practices document](/articles/dockerfile_best-practices). In addition,
43
+Docker, Inc. engineer Michael Crosby has a good discussion of Dockerfiles in
44
+this [blog post](http://crosbymichael.com/dockerfile-best-practices-take-2.html).
43 45
 
44
-While [`ONBUILD` triggers](https://docs.docker.com/reference/builder/#onbuild) are not
45
-required, if you choose to use them you should:
46
+While [`ONBUILD` triggers](https://docs.docker.com/reference/builder/#onbuild)
47
+are not required, if you choose to use them you should:
46 48
 
47
-* Build both `ONBUILD` and non-`ONBUILD` images, with the `ONBUILD` image built `FROM`
48
-the non-`ONBUILD` image.
49
-* The `ONBUILD` image should be specifically tagged, for example, `ruby:latest` and
50
-`ruby:onbuild`, or `ruby:2` and  `ruby:2-onbuild`.
49
+* Build both `ONBUILD` and non-`ONBUILD` images, with the `ONBUILD` image
50
+built `FROM` the non-`ONBUILD` image.
51
+* The `ONBUILD` image should be specifically tagged, for example, `ruby:
52
+latest`and `ruby:onbuild`, or `ruby:2` and  `ruby:2-onbuild`.
51 53
 
52 54
 ### A short description
53 55
 
54
-Include a brief description of your image (in plaintext). Only one description is
55
-required; you don’t need additional descriptions for each tag. The file should also: 
56
+Include a brief description of your image (in plaintext). Only one description
57
+is required; you don’t need additional descriptions for each tag. The file
58
+should also: 
56 59
 
57 60
 * Be named `README-short.txt`
58 61
 * Reside in the repo for the “latest” tag
... ...
@@ -60,26 +64,26 @@ required; you don’t need additional descriptions for each tag. The file should
60 60
 
61 61
 ### A logo
62 62
 
63
-Include a logo of your company or the product (png format preferred). Only one logo is
64
-required; you don’t need additional logo files for each tag. The logo file should have
65
-the following characteristics: 
63
+Include a logo of your company or the product (png format preferred). Only one
64
+logo is required; you don’t need additional logo files for each tag. The logo
65
+file should have the following characteristics: 
66 66
 
67 67
 * Be named `logo.png`
68 68
 * Should reside in the repo for the “latest” tag
69 69
 * Should be 200px min. in one dimension, 200px max. in the other.
70
-* Square or wide (landscape) is preferred over tall (portrait), but exceptions can be
71
-made based on the logo needed.
70
+* Square or wide (landscape) is preferred over tall (portrait), but exceptions
71
+can be made based on the logo needed.
72 72
 
73 73
 ### A long description
74 74
 
75
-Include a comprehensive description of your image (in markdown format). Only one
76
-description is required; you don’t need additional descriptions for each tag. The file
77
-should also: 
75
+Include a comprehensive description of your image (in markdown format). Only
76
+one description is required; you don’t need additional descriptions for each
77
+tag. The file should also: 
78 78
 
79 79
 * Be named `README.md`
80 80
 * Reside in the repo for the “latest” tag
81
-* Be no longer than absolutely necessary, while still addressing all the content
82
-requirements.
81
+* Be no longer than absolutely necessary, while still addressing all the
82
+content requirements.
83 83
 
84 84
 In terms of content, the long description must include the following sections:
85 85
 
... ...
@@ -89,42 +93,43 @@ In terms of content, the long description must include the following sections:
89 89
 
90 90
 #### Overview & links
91 91
 
92
-A section providing (a) an overview of the software contained in the image, similar to
93
-the introduction in a Wikipedia entry and (b) a selection of links to outside resources
94
-that help to describe the software.
92
+A section providing (a) an overview of the software contained in the image,
93
+similar to the introduction in a Wikipedia entry and (b) a selection of links
94
+to outside resources that help to describe the software.
95 95
 
96 96
 This section *must* also include a link to the `Dockerfile`.
97 97
 
98 98
 #### How-to/usage
99 99
 
100
-A section that describes how to run and use the image, including common use cases and
101
-example `Dockerfile`s (if applicable). Try to provide clear, step-by-step instructions
102
-wherever possible.
100
+A section that describes how to run and use the image, including common use
101
+cases and example `Dockerfile`s (if applicable). Try to provide clear,step-by-
102
+step instructions wherever possible.
103 103
 
104 104
 ##### Contributing
105 105
 
106
-In this part, point users to any resources that can help them contribute to the project.
107
-Include contribution guidelines and any specific instructions related to your development
108
-practices. Include a link to [Docker’s resources for contributors](https://docs.docker.com/contributing/contributing/).
106
+In this part, point users to any resources that can help them contribute to the
107
+project. Include contribution guidelines and any specific instructions related
108
+to your development practices. Include a link to
109
+[Docker’s resources for contributors](https://docs.docker.com/contributing/contributing/).
109 110
 Be sure to include contact info, handles, etc. for official maintainers.
110 111
 
111 112
 ##### Issues
112 113
 
113
-Include a brief section letting users know where they can go for help and how they can
114
-file issues with the repo. Point them to any specific IRC channels, issue trackers,
115
-contacts, additional “how-to” information or other resources.
114
+Include a brief section letting users know where they can go for help and how
115
+they can file issues with the repo. Point them to any specific IRC channels,
116
+issue trackers, contacts, additional “how-to” information or other resources.
116 117
 
117 118
 ### License
118 119
 
119
-Include a file, `LICENSE`, of any applicable license.  Docker recommends using the
120
-license of the software contained in the image, provided it allows Docker, Inc. to
121
-legally build and distribute the image.  Otherwise Docker recommends adopting the
122
-[Expat license](http://directory.fsf.org/wiki/License:Expat).
120
+Include a file, `LICENSE`, of any applicable license.  Docker recommends using
121
+the license of the software contained in the image, provided it allows Docker,
122
+Inc. to legally build and distribute the image.  Otherwise Docker recommends
123
+adopting the [Expat license](http://directory.fsf.org/wiki/License:Expat).
123 124
 
124 125
 ## Examples
125 126
 
126
-Below are sample short and long description files for an imaginary image containing
127
-Ruby on Rails.
127
+Below are sample short and long description files for an imaginary image
128
+containing Ruby on Rails.
128 129
 
129 130
 ### Short description
130 131
 
... ...
@@ -165,4 +170,10 @@ Test it by visiting `http://container-ip:3000` in a browser. On the other hand,
165 165
 Then hit `http://localhost:8080` or `http://host-ip:8080` in a browser.
166 166
 ```
167 167
 
168
-For more examples, take a look at these repos: <TODO links>
168
+For more examples, take a look at these repos: 
169
+
170
+* [Go](https://github.com/docker-library/golang)
171
+* [PostgreSQL](https://github.com/docker-library/postgres)
172
+* [Buildpack-deps](https://github.com/docker-library/buildpack-deps)
173
+* ["Hello World" minimal container](https://github.com/docker-library/hello-world)
174
+* [Node](https://github.com/docker-library/node)
... ...
@@ -11,6 +11,11 @@ Docker image. By calling `docker build` from your terminal, you can have
11 11
 Docker build your image step by step, executing the instructions
12 12
 successively.
13 13
 
14
+This page discusses the specifics of all the instructions you can use in your
15
+`Dockerfile`. To further help you write a clear, readable, maintainable
16
+`Dockerfile`, we've also written a [`Dockerfile` Best Practices guide](/articles/dockerfile_best-practices).
17
+
18
+
14 19
 ## Usage
15 20
 
16 21
 To [*build*](../commandline/cli/#cli-build) an image from a source repository,
... ...
@@ -468,11 +468,13 @@ We can then create a container from our new image.
468 468
     root@8196968dac35:/#
469 469
 
470 470
 > **Note:** 
471
-> This is just the briefest introduction to creating images. We've
471
+> This is just a brief introduction to creating images. We've
472 472
 > skipped a whole bunch of other instructions that you can use. We'll see more of
473 473
 > those instructions in later sections of the Guide or you can refer to the
474 474
 > [`Dockerfile`](/reference/builder/) reference for a
475 475
 > detailed description and examples of every instruction.
476
+> To help you write a clear, readable, maintainable `Dockerfile`, we've also
477
+> written a [`Dockerfile` Best Practices guide](/articles/dockerfile_best-practices).
476 478
 
477 479
 ## Setting tags on an image
478 480