From d9fd5f6199aebb9ea784f5b23ec97b960f89f3d4 Mon Sep 17 00:00:00 2001 From: Fred Lifton Date: Tue, 23 Sep 2014 14:21:00 -0700 Subject: [PATCH] Adding new Dockerfile Best Practices doc, and links thereto. Docker-DCO-1.1-Signed-off-by: Fred Lifton (github: fredlf) --- docs/mkdocs.yml | 9 +- docs/sources/articles/baseimages.md | 11 +- .../articles/dockerfile_best-practices.md | 333 ++++++++++++++++++ docs/sources/docker-hub/official_repos.md | 117 +++--- docs/sources/reference/builder.md | 5 + docs/sources/userguide/dockerimages.md | 4 +- 6 files changed, 420 insertions(+), 59 deletions(-) create mode 100644 docs/sources/articles/dockerfile_best-practices.md diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index f620030713..9428b85e3e 100755 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -84,17 +84,18 @@ pages: - ['articles/networking.md', 'Articles', 'Advanced networking'] - ['articles/security.md', 'Articles', 'Security'] - ['articles/https.md', 'Articles', 'Running Docker with HTTPS'] -- ['articles/host_integration.md', 'Articles', 'Automatically starting Containers'] +- ['articles/host_integration.md', 'Articles', 'Automatically starting containers'] +- ['articles/baseimages.md', 'Articles', 'Creating a base image'] +- ['articles/dockerfile_best-practices.md', 'Articles', 'Best practices for writing Dockerfiles'] - ['articles/certificates.md', 'Articles', 'Using certificates for repository client verification'] - ['articles/using_supervisord.md', 'Articles', 'Using Supervisor'] - ['articles/cfengine_process_management.md', 'Articles', 'Process management with CFEngine'] - ['articles/puppet.md', 'Articles', 'Using Puppet'] - ['articles/chef.md', 'Articles', 'Using Chef'] - ['articles/dsc.md', 'Articles', 'Using PowerShell DSC'] -- ['articles/ambassador_pattern_linking.md', 'Articles', 'Cross-Host linking using Ambassador Containers'] +- ['articles/ambassador_pattern_linking.md', 'Articles', 'Cross-Host linking using ambassador containers'] - ['articles/runmetrics.md', 'Articles', 'Runtime metrics'] -- ['articles/baseimages.md', 'Articles', 'Creating a Base Image'] -- ['articles/b2d_volume_resize.md', 'Articles', 'Increasing a Boot2Docker Volume'] +- ['articles/b2d_volume_resize.md', 'Articles', 'Increasing a Boot2Docker volume'] # Reference - ['reference/index.md', '**HIDDEN**'] diff --git a/docs/sources/articles/baseimages.md b/docs/sources/articles/baseimages.md index bc677eb8a3..3f53c8a84b 100644 --- a/docs/sources/articles/baseimages.md +++ b/docs/sources/articles/baseimages.md @@ -55,5 +55,14 @@ image to base your new minimal containers `FROM`: COPY true-asm /true CMD ["/true"] -The Dockerfile above is from extremely minimal image - [tianon/true]( +The `Dockerfile` above is from an extremely minimal image - [tianon/true]( https://github.com/tianon/dockerfiles/tree/master/true). + +## More resources + +There are lots more resources available to help you write your 'Dockerfile`. + +* There's a [complete guide to all the instructions](/reference/builder/) available for use in a `Dockerfile` in the reference section. +* To help you write a clear, readable, maintainable `Dockerfile`, we've also +written a [`Dockerfile` Best Practices guide](/articles/dockerfile_best-practices). +* If you're working on an Official Repo, be sure to check out the [Official Repo Guidelines](/docker-hub/official_repos/). diff --git a/docs/sources/articles/dockerfile_best-practices.md b/docs/sources/articles/dockerfile_best-practices.md new file mode 100644 index 0000000000..f73c72c4ad --- /dev/null +++ b/docs/sources/articles/dockerfile_best-practices.md @@ -0,0 +1,333 @@ +page_title: Best Practices for Writing Dockerfiles +page_description: Hints, tips and guidelines for writing clean, reliable Dockerfiles +page_keywords: Examples, Usage, base image, docker, documentation, dockerfile, best practices, hub, official repo + + + # Best Practices for Writing `Dockerfile`s + +## Overview + +Docker can build images automatically by reading the instructions from a +`Dockerfile`, a text file that contains all the commands, in order, needed to +build a given image. `Dockerfile`s adhere to a specific format and use a +specific set of instructions. You can learn the basics on the +[Dockerfile Reference](https://docs.docker.com/reference/builder/) page. If +you’re new to writing `Dockerfile`s, you should start there. + +This document covers the best practices and methods recommended by Docker, +Inc., for creating easy-to-use, effective `Dockerfile`s. We strongly suggest +you follow these recommendations (in fact, if you’re creating an Official +Image, you *must* adhere to these practices). + +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). + +> Note: for more detailed explanations of any of the Dockerfile commands +>mentioned here, visit the [Dockerfile Reference](https://docs.docker.com/reference/builder/) page. + +## General Guidelines and Recommendations + +### Containers should be ephemeral + +The container produced by the image your `Dockerfile` defines should be as +ephemeral as possible. “Ephemeral” here means that it can be stopped and +destroyed and a new one built and put in place with an absolute minimum of +set-up and configuration. + +### Use a [`.dockerignore` file](https://docs.docker.com/reference/builder/#the-dockerignore-file) + +For faster uploading and efficiency, you should make use of a `.dockerignore` +file to exclude files or directories from the build context. For example, unless +`.git` is needed by your build process or scripts, you should add it to +`.dockerignore`, which can save many megabytes worth of upload time. + +### Avoid installing unnecessary packages + +You should avoid installing extra or unnecessary packages just because they +might be “nice to have.” For example, you don’t need to include a text editor +in a database image. + +### Run only one process per container + +In almost all cases, you should only run a single process in a single +container. Decoupling applications into multiple containers makes it much +easier to scale horizontally and reuse containers. If that service depends on +another service, make use of [container linking](https://docs.docker.com/userguide/dockerlinks/). + +### Minimize the number of layers + +You need to find the balance between readability (and thus long-term +maintainability) of the `Dockerfile` and minimizing the number of layers it +uses. Be strategic and cautious about the number of layers you use. + +### Sort multi-line arguments + +Whenever possible, ease later changes by sorting multi-line arguments +alphanumerically. This will help you avoid duplication of packages and make the +list much easier to update. This also makes PRs a lot easier to read and +review. Adding a space before a backslash (`\`) helps as well. + +Here’s an example from the [`buildpack-deps` image](https://github.com/docker-library/buildpack-deps): + + RUN apt-get update && apt-get install -y \ + bzr \ + cvs \ + git \ + mercurial \ + subversion + +## The `Dockerfile` instructions + +This section contains specific recommendations for the correct usage of the +various instructions contained in a `Dockerfile`. + +### [`FROM`](https://docs.docker.com/reference/builder/#from) + +Whenever possible, use Official Repositories as the basis for your image. We +recommend the [Debian image](https://registry.hub.docker.com/_/debian/) since +it’s very tightly controlled and kept extremely minimal (currently under 100 +mb), while still being a full distribution. + +### [`RUN`](https://docs.docker.com/reference/builder/#run) + +As always, to make your `Dockerfile` more readable, understandable, and +maintainable, put long or complex statements on multiple lines separated with +backslashes. + +Probably the most common use-case for `RUN` is an application of `apt-get`. +When using `apt-get`, here a few things to keep in mind: + +* Don’t do simply `RUN apt-get update` on a single line. This will cause +caching issues if the referenced archive gets updated, which will make your +subsequent `apt-get install` fail without comment. + +* For the most part, to keep your code more readable and maintainable, avoid +`RUN apt-get install -y package-foo && apt-get install -y package-bar`. + +* 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. + +* Do use `RUN apt-get update && apt-get install -y package-bar package-foo +package-baz`. Writing the instruction this way not only makes it easier to read +and maintain, but also, by including `apt-get update`, ensures that the cache +will naturally be busted and the latest versions will be installed with no +further coding or manual intervention required. + +* Further natural cache-busting can be realized by version-pinning packages +(e.g., `package-foo=1.3*`) since it will force retrieval of that version +regardless of what’s in the cache. + +Forming your `apt-get` code this way will greatly ease maintenance and reduce +failures due to unanticipated changes in required packages. + +#### Example + +Below is a well-formed `RUN` instruction that demonstrates the above +recommendations. Note that the last package, `s3cmd`, specifies a version +`1.1.0*`, which will bust the `apt-get` cache and force the installation of +that version (which in this case had a new, required feature). + + RUN apt-get update && apt-get install -y \ + aufs-tools \ + automake \ + btrfs-tools \ + build-essential \ + curl \ + dpkg-sig \ + git \ + iptables \ + libapparmor-dev \ + libcap-dev \ + libsqlite3-dev \ + lxc=1.0* \ + mercurial \ + parallel \ + reprepro \ + ruby1.9.1 \ + ruby1.9.1-dev \ + s3cmd=1.1.0* + +### [`CMD`](https://docs.docker.com/reference/builder/#cmd) + +The `CMD` instruction should be used to run the software contained by your +image, along with any arguments. `CMD` should almost always be used in the +form of `CMD [“executable”, “param1”, “param2”…]`. Thus, if the image is for a +service (Apache, Rails, etc.), you would run something like `CMD ["apache2", +"-DFOREGROUND"]`. Indeed, this form of the instruction is recommended for any +service-based image. + +In most other cases, `CMD` should be given an interactive shell (bash, python, +perl, etc). For example, `CMD ["perl", "-de0"]`, `CMD ["python"]`, or `CMD +[“php”, “-a”]`. Using this form means that when you execute something like +`docker run -it python`, you’ll get dropped into a usable shell, ready to go. +`CMD` should rarely be used in the manner of `CMD [“param”, “param”]` in +conjunction with [`ENTRYPOINT`](https://docs.docker.com/reference/builder/#entrypoint), unless +you and your expected users are already quite familiar with how `ENTRYPOINT` +works. + +### [`EXPOSE`](https://docs.docker.com/reference/builder/#expose) + +The `EXPOSE` instruction is the way you tell the users of your image where to +connect. Consequently, you should use the common, traditional port for your +application. For example, an image containing the Apache web server would use +`EXPOSE 80` while an image containing MongoDB would use `EXPOSE 27017` and so +on. + +For external access, your users can execute `docker run` with a flag indicating +how to map the specified port to the port of their choice. +For container linking, Docker provides environment variables for the path from +the recipient container back to the source (ie, `MYSQL_PORT_3306_TCP`). + +### [`ENV`](https://docs.docker.com/reference/builder/#env) + +In order to make new software easier to run, you can use `ENV` to update the +`PATH` environment variable for the software your container installs. For +example, `ENV PATH /usr/local/nginx/bin:$PATH` will ensure that `CMD [“nginx”]` +just works. + +The `ENV` instruction is also useful for providing required environment +variables specific to services you wish to containerize, such as Postgres’s +`PGDATA`. + +Lastly, `ENV` can also be used to set commonly used version numbers so that +version bumps are easier to maintain, as seen in the following example: + + ENV PG_MAJOR 9.3 + ENV PG_VERSION 9.3.4 + RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && … + ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH + +Similar to having constant variables in a program (as opposed to hard-coding +values), this approach lets you change a single `ENV` instruction to +auto-magically bump the version of the software in your container. + +### [`ADD`](https://docs.docker.com/reference/builder/#add) or +[`COPY`](https://docs.docker.com/reference/builder/#copy) + +Although `ADD` and `COPY` are functionally similar, generally speaking, `COPY` +is preferred. That’s because it’s more transparent than `ADD`. `COPY` only +supports the basic copying of local files into the container, while `ADD` has +some features (like local-only tar extraction and remote URL support) that are +not immediately obvious. + +Consequently, the best use for `ADD` is local tar file auto-extraction into the +image, as in `ADD rootfs.tar.xz /`. +Because image size matters, using `ADD` to fetch packages from remote URLs is +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 +extracted without having to add another layer in your image. For example, you +should avoid doing things like: + + ADD http://example.com/big.tar.xz /usr/src/things/ + RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things + RUN make -C /usr/src/things all + +And instead, do something like: + RUN mdkir -p /usr/src/things \ + && curl -SL http://example.com/big.tar.gz \ + | tar -xJC /usr/src/things \ + && make -C /usr/src/things all + +For other items (files, directories) that do not require `ADD`’s tar +auto-extraction capability, you should always use `COPY`. + +### [`ENTRYPOINT`](https://docs.docker.com/reference/builder/#entrypoint) + +The best use for `ENTRYPOINT` is as a helper script. Using `ENTRYPOINT` for +other tasks can make your code harder to understand. For example, `docker run +-it official-image bash` is much easier to understand than `docker run -it +--entrypoint bash official-image -i`, especially for Docker beginners. + +In order to avoid a situation where commands are run without clear visibility +to the user, make sure your script ends with something like `exec "$@"`. After +the entrypoint completes, the script will transparently bootstrap the command +invoked by the user, making what has been run clear to the user (for example, +`docker run -it mysql mysqld --some --flags` will transparently run `mysqld +--some --flags` after `ENTRYPOINT` runs `initdb`). + +For example, let’s look at the `Dockerfile` for the +[Postgres Official Image](https://github.com/docker-library/postgres). +It refers to the following script: + +```bash +#!/bin/bash +set -e + +if [ "$1" = 'postgres' ]; then + chown -R postgres "$PGDATA" + + if [ -z "$(ls -A "$PGDATA")" ]; then + gosu postgres initdb + fi + + exec gosu postgres "$@" +fi + +exec "$@" +``` + +That script then gets copied into the container and the run via `ENTRYPOINT` on +container startup: + + COPY ./docker-entrypoint.sh / + ENTRYPOINT ["/docker-entrypoint.sh"] + +### [`VOLUME`](https://docs.docker.com/reference/builder/#volume) + +`VOLUME` should be used to expose any database storage area, configuration +storage, or files/folders created by your docker container. You are strongly +encouraged to use `VOLUME` for any mutable and/or user-serviceable parts of +your image. + +### [`USER`](https://docs.docker.com/reference/builder/#user) + +If a service can run without privileges, use `USER` to change to a non-root +user. Start by creating the user and group in the `Dockerfile` with something +like `RUN groupadd -r postgres && useradd -r -g postgres postgres`. + +>**Note** that users/groups in an image get assigned nondeterministic UID/GID in +>that the “next” UID/GID will be assigned regardless of image rebuilds. So, if +>it’s critical, you should assign an explicit UID/GID. + +You should avoid installing or using `sudo` since it has unpredictable TTY and +signal-forwarding behavior that can cause more more problems than it solves. If +you absolutely need functionality similar to `sudo` (e.g., initializing the +daemon as root but running it as non-root), you may be able to use +[“gosu”](https://github.com/tianon/gosu). + +Lastly, to reduce layers and complexity, try to minimize switching `USER` back +and forth frequently. + +### [`WORKDIR`](https://docs.docker.com/reference/builder/#workdir) + +For clarity and reliability, you should always use absolute paths for your +`WORKDIR`. Also, you should use `WORKDIR` instead of proliferating +instructions like `RUN cd … && do-something`, which are hard to read, +troubleshoot, and maintain. + +### [`ONBUILD`](https://docs.docker.com/reference/builder/#onbuild) + +`ONBUILD` is only useful for images that are going to be built `FROM` a given +image. For example, you would use `ONBUILD` for a language stack image that +builds arbitrary user software written in that language within the +`Dockerfile`, as you can see in [Ruby’s `ONBUILD` variants](https://github.com/docker-library/ruby/blob/master/2.1/onbuild/Dockerfile). + +Images built from `ONBUILD` should get a separate tag, for example: +`ruby:1.9-onbuild` or `ruby:2.0-onbuild`. + +Be careful when putting `ADD` or `COPY` in `ONBUILD`. The “onbuild” image will +fail catastrophically if it is missing the the resource being added. Adding a +separate tag, as recommended above, will help mitigate this by allowing the +`Dockerfile` author to make a choice. + +## Examples For Official Repositories + +These Official Repos have exemplary `Dockerfile`s: +* [Go](https://registry.hub.docker.com/_/golang/) +* [Perl](https://registry.hub.docker.com/_/perl/) +* [Hy](https://registry.hub.docker.com/_/hylang/) +* [Rails](https://registry.hub.docker.com/_/rails) + +## Additional Resources: + +* [Dockerfile Reference](https://docs.docker.com/reference/builder/#onbuild) +* [More about Base Images](https://docs.docker.com/articles/baseimages/) +* [More about Automated Builds](https://docs.docker.com/docker-hub/builds/) +* [Guidelines for Creating Official Repositories](https://docs.docker.com/docker-hub/official_repos/) \ No newline at end of file diff --git a/docs/sources/docker-hub/official_repos.md b/docs/sources/docker-hub/official_repos.md index e7cb86a369..be73c94524 100644 --- a/docs/sources/docker-hub/official_repos.md +++ b/docs/sources/docker-hub/official_repos.md @@ -6,10 +6,11 @@ page_keywords: Docker, docker, registry, accounts, plans, Dockerfile, Docker Hub ## Introduction -You’ve been given the job of creating an image for an Official Repository hosted on -[Docker Hub Registry](https://registry.hub.docker.com/). These are Docker, Inc.’s -guidelines for getting that task done. Even if you’re not planning to create an Official -Repo, you can think of these guidelines as best practices for image creation generally. +You’ve been given the job of creating an image for an Official Repository +hosted on[Docker Hub Registry](https://registry.hub.docker.com/). These are +Docker, Inc.’s guidelines for getting that task done. Even if you’re not +planning to create an Official Repo, you can think of these guidelines as best +practices for image creation generally. This document consists of three major sections: @@ -21,38 +22,41 @@ This document consists of three major sections: ### A Git repository -Your image needs to live in a Git repository, preferably on GitHub. (If you’d like to use -a different provider, please [contact us](TODO: link) directly.) Docker **strongly** -recommends that this repo be publicly accessible. +Your image needs to live in a Git repository, preferably on GitHub. (If you’d +like to use a different provider, please [contact us](mailto:feedback@docker.com) +directly.) Docker **strongly** recommends that this repo be publicly +accessible. -If the repo is private or has otherwise limited access, you must provide a means of at -least “read-only” access for both general users and for the docker-library maintainers, -who need access for review and building purposes. +If the repo is private or has otherwise limited access, you must provide a +means of at least “read-only” access for both general users and for the docker- +library maintainers, who need access for review and building purposes. ### A `Dockerfile` Complete information on `Dockerfile`s can be found in the [Reference section](https://docs.docker.com/reference/builder/). -We also have a page discussing best practices for writing `Dockerfile`s (TODO: link). +We also have a page discussing [best practices for writing `Dockerfile`s](/articles/dockerfile_best-practices). Your `Dockerfile` should adhere to the following: -* It must be written either by using `FROM scratch` or be based on another, established -Official Image. -* It must follow `Dockerfile` best practices. These are discussed in the [Best Practices -document](TODO: link). In addition, Docker, Inc. engineer Michael Crosby has a good -discussion of Dockerfiles in this [blog post](http://crosbymichael.com/dockerfile-best-practices-take-2.html). +* It must be written either by using `FROM scratch` or be based on another, +established Official Image. +* It must follow `Dockerfile` best practices. These are discussed in the +[Best Practices document](/articles/dockerfile_best-practices). In addition, +Docker, Inc. engineer Michael Crosby has a good discussion of Dockerfiles in +this [blog post](http://crosbymichael.com/dockerfile-best-practices-take-2.html). -While [`ONBUILD` triggers](https://docs.docker.com/reference/builder/#onbuild) are not -required, if you choose to use them you should: +While [`ONBUILD` triggers](https://docs.docker.com/reference/builder/#onbuild) +are not required, if you choose to use them you should: -* Build both `ONBUILD` and non-`ONBUILD` images, with the `ONBUILD` image built `FROM` -the non-`ONBUILD` image. -* The `ONBUILD` image should be specifically tagged, for example, `ruby:latest` and -`ruby:onbuild`, or `ruby:2` and `ruby:2-onbuild`. +* Build both `ONBUILD` and non-`ONBUILD` images, with the `ONBUILD` image +built `FROM` the non-`ONBUILD` image. +* The `ONBUILD` image should be specifically tagged, for example, `ruby: +latest`and `ruby:onbuild`, or `ruby:2` and `ruby:2-onbuild`. ### A short description -Include a brief description of your image (in plaintext). Only one description is -required; you don’t need additional descriptions for each tag. The file should also: +Include a brief description of your image (in plaintext). Only one description +is required; you don’t need additional descriptions for each tag. The file +should also: * Be named `README-short.txt` * 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 ### A logo -Include a logo of your company or the product (png format preferred). Only one logo is -required; you don’t need additional logo files for each tag. The logo file should have -the following characteristics: +Include a logo of your company or the product (png format preferred). Only one +logo is required; you don’t need additional logo files for each tag. The logo +file should have the following characteristics: * Be named `logo.png` * Should reside in the repo for the “latest” tag * Should be 200px min. in one dimension, 200px max. in the other. -* Square or wide (landscape) is preferred over tall (portrait), but exceptions can be -made based on the logo needed. +* Square or wide (landscape) is preferred over tall (portrait), but exceptions +can be made based on the logo needed. ### A long description -Include a comprehensive description of your image (in markdown format). Only one -description is required; you don’t need additional descriptions for each tag. The file -should also: +Include a comprehensive description of your image (in markdown format). Only +one description is required; you don’t need additional descriptions for each +tag. The file should also: * Be named `README.md` * Reside in the repo for the “latest” tag -* Be no longer than absolutely necessary, while still addressing all the content -requirements. +* Be no longer than absolutely necessary, while still addressing all the +content requirements. In terms of content, the long description must include the following sections: @@ -89,42 +93,43 @@ In terms of content, the long description must include the following sections: #### Overview & links -A section providing (a) an overview of the software contained in the image, similar to -the introduction in a Wikipedia entry and (b) a selection of links to outside resources -that help to describe the software. +A section providing (a) an overview of the software contained in the image, +similar to the introduction in a Wikipedia entry and (b) a selection of links +to outside resources that help to describe the software. This section *must* also include a link to the `Dockerfile`. #### How-to/usage -A section that describes how to run and use the image, including common use cases and -example `Dockerfile`s (if applicable). Try to provide clear, step-by-step instructions -wherever possible. +A section that describes how to run and use the image, including common use +cases and example `Dockerfile`s (if applicable). Try to provide clear,step-by- +step instructions wherever possible. ##### Contributing -In this part, point users to any resources that can help them contribute to the project. -Include contribution guidelines and any specific instructions related to your development -practices. Include a link to [Docker’s resources for contributors](https://docs.docker.com/contributing/contributing/). +In this part, point users to any resources that can help them contribute to the +project. Include contribution guidelines and any specific instructions related +to your development practices. Include a link to +[Docker’s resources for contributors](https://docs.docker.com/contributing/contributing/). Be sure to include contact info, handles, etc. for official maintainers. ##### Issues -Include a brief section letting users know where they can go for help and how they can -file issues with the repo. Point them to any specific IRC channels, issue trackers, -contacts, additional “how-to” information or other resources. +Include a brief section letting users know where they can go for help and how +they can file issues with the repo. Point them to any specific IRC channels, +issue trackers, contacts, additional “how-to” information or other resources. ### License -Include a file, `LICENSE`, of any applicable license. Docker recommends using the -license of the software contained in the image, provided it allows Docker, Inc. to -legally build and distribute the image. Otherwise Docker recommends adopting the -[Expat license](http://directory.fsf.org/wiki/License:Expat). +Include a file, `LICENSE`, of any applicable license. Docker recommends using +the license of the software contained in the image, provided it allows Docker, +Inc. to legally build and distribute the image. Otherwise Docker recommends +adopting the [Expat license](http://directory.fsf.org/wiki/License:Expat). ## Examples -Below are sample short and long description files for an imaginary image containing -Ruby on Rails. +Below are sample short and long description files for an imaginary image +containing Ruby on Rails. ### Short description @@ -165,4 +170,10 @@ Test it by visiting `http://container-ip:3000` in a browser. On the other hand, Then hit `http://localhost:8080` or `http://host-ip:8080` in a browser. ``` -For more examples, take a look at these repos: +For more examples, take a look at these repos: + +* [Go](https://github.com/docker-library/golang) +* [PostgreSQL](https://github.com/docker-library/postgres) +* [Buildpack-deps](https://github.com/docker-library/buildpack-deps) +* ["Hello World" minimal container](https://github.com/docker-library/hello-world) +* [Node](https://github.com/docker-library/node) diff --git a/docs/sources/reference/builder.md b/docs/sources/reference/builder.md index 796d07d98e..eca8dd618f 100644 --- a/docs/sources/reference/builder.md +++ b/docs/sources/reference/builder.md @@ -11,6 +11,11 @@ Docker image. By calling `docker build` from your terminal, you can have Docker build your image step by step, executing the instructions successively. +This page discusses the specifics of all the instructions you can use in your +`Dockerfile`. To further help you write a clear, readable, maintainable +`Dockerfile`, we've also written a [`Dockerfile` Best Practices guide](/articles/dockerfile_best-practices). + + ## Usage To [*build*](../commandline/cli/#cli-build) an image from a source repository, diff --git a/docs/sources/userguide/dockerimages.md b/docs/sources/userguide/dockerimages.md index e6583a0f82..2b64d900ab 100644 --- a/docs/sources/userguide/dockerimages.md +++ b/docs/sources/userguide/dockerimages.md @@ -468,11 +468,13 @@ We can then create a container from our new image. root@8196968dac35:/# > **Note:** -> This is just the briefest introduction to creating images. We've +> This is just a brief introduction to creating images. We've > skipped a whole bunch of other instructions that you can use. We'll see more of > those instructions in later sections of the Guide or you can refer to the > [`Dockerfile`](/reference/builder/) reference for a > detailed description and examples of every instruction. +> To help you write a clear, readable, maintainable `Dockerfile`, we've also +> written a [`Dockerfile` Best Practices guide](/articles/dockerfile_best-practices). ## Setting tags on an image