Edits and fixes to Dockerfile Best Practices based on review feedback.
Docker-DCO-1.1-Signed-off-by: Fred Lifton <fred.lifton@docker.com> (github: fredlf)
This commit is contained in:
parent
42b377904b
commit
36db0a30fa
|
@ -2,7 +2,7 @@ page_title: Best Practices for Writing Dockerfiles
|
||||||
page_description: Hints, tips and guidelines for writing clean, reliable 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
|
page_keywords: Examples, Usage, base image, docker, documentation, dockerfile, best practices, hub, official repo
|
||||||
|
|
||||||
# Best Practices for Writing Dockerfiles
|
# Best practices for writing Dockerfiles
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ You can see many of these practices and recommendations in action in the [buildp
|
||||||
> Note: for more detailed explanations of any of the Dockerfile commands
|
> Note: for more detailed explanations of any of the Dockerfile commands
|
||||||
>mentioned here, visit the [Dockerfile Reference](https://docs.docker.com/reference/builder/) page.
|
>mentioned here, visit the [Dockerfile Reference](https://docs.docker.com/reference/builder/) page.
|
||||||
|
|
||||||
## General Guidelines and Recommendations
|
## General guidelines and recommendations
|
||||||
|
|
||||||
### Containers should be ephemeral
|
### Containers should be ephemeral
|
||||||
|
|
||||||
|
@ -42,7 +42,8 @@ megabytes worth of upload time.
|
||||||
|
|
||||||
### Avoid installing unnecessary packages
|
### Avoid installing unnecessary packages
|
||||||
|
|
||||||
In order to reduce complexity, dependencies, file sizes and build times, you should avoid installing extra or unnecessary packages just because they
|
In order to reduce complexity, dependencies, file sizes, and build times, 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
|
might be “nice to have.” For example, you don’t need to include a text editor
|
||||||
in a database image.
|
in a database image.
|
||||||
|
|
||||||
|
@ -75,7 +76,7 @@ Here’s an example from the [`buildpack-deps` image](https://github.com/docker-
|
||||||
mercurial \
|
mercurial \
|
||||||
subversion
|
subversion
|
||||||
|
|
||||||
### Build Cache
|
### Build cache
|
||||||
|
|
||||||
During the process of building an image Docker will step through the
|
During the process of building an image Docker will step through the
|
||||||
instructions in your `Dockerfile` executing each in the order specified.
|
instructions in your `Dockerfile` executing each in the order specified.
|
||||||
|
@ -118,7 +119,7 @@ generate new images and the cache will not be used.
|
||||||
mercurial \
|
mercurial \
|
||||||
subversion
|
subversion
|
||||||
|
|
||||||
## The `Dockerfile` instructions
|
## The Dockerfile instructions
|
||||||
|
|
||||||
Below you'll find recommendations for the best way to write the
|
Below you'll find recommendations for the best way to write the
|
||||||
various instructions available for use in a `Dockerfile`.
|
various instructions available for use in a `Dockerfile`.
|
||||||
|
@ -133,29 +134,25 @@ since it’s very tightly controlled and kept extremely minimal (currently under
|
||||||
### [`RUN`](https://docs.docker.com/reference/builder/#run)
|
### [`RUN`](https://docs.docker.com/reference/builder/#run)
|
||||||
|
|
||||||
As always, to make your `Dockerfile` more readable, understandable, and
|
As always, to make your `Dockerfile` more readable, understandable, and
|
||||||
maintainable, put long or complex `RUN` statements on multiple lines separate
|
maintainable, put long or complex `RUN` statements on multiple lines separated
|
||||||
with backslashes.
|
with backslashes.
|
||||||
|
|
||||||
Probably the most common use-case for `RUN` is an application of `apt-get`
|
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:
|
When using `apt-get`, here are a few things to keep in mind:
|
||||||
|
|
||||||
* Don’t do `RUN apt-get update` on a single line. This will cause
|
* Don’t do `RUN apt-get update` on a single line. This will cause
|
||||||
caching issues if the referenced archive gets updated, which will make your
|
caching issues if the referenced archive gets updated, which will make your
|
||||||
subsequent `apt-get install` fail without comment.
|
subsequent `apt-get install` fail without comment.
|
||||||
|
|
||||||
* For the most part, to keep your code more readable and maintainable, avoid instructions like:
|
|
||||||
|
|
||||||
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”
|
* 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
|
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
|
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
|
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.
|
updated, use `apt-get install -y foo` and it will update automatically.
|
||||||
|
|
||||||
* Do write something like:
|
* Do write instructions like:
|
||||||
|
|
||||||
`RUN apt-get update && apt-get install -y package-bar package-foo package-baz`.
|
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
|
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
|
and maintain, but also, by including `apt-get update`, ensures that the cache
|
||||||
|
@ -165,7 +162,7 @@ further coding or manual intervention required.
|
||||||
* Further natural cache-busting can be realized by version-pinning packages
|
* Further natural cache-busting can be realized by version-pinning packages
|
||||||
(e.g., `package-foo=1.3.*`). This will force retrieval of that version
|
(e.g., `package-foo=1.3.*`). This will force retrieval of that version
|
||||||
regardless of what’s in the cache.
|
regardless of what’s in the cache.
|
||||||
Forming your `apt-get` code this way will greatly ease maintenance and reduce
|
Writing your `apt-get` code this way will greatly ease maintenance and reduce
|
||||||
failures due to unanticipated changes in required packages.
|
failures due to unanticipated changes in required packages.
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
@ -196,6 +193,11 @@ the new version (which in this case had a new, required feature).
|
||||||
ruby1.9.1-dev \
|
ruby1.9.1-dev \
|
||||||
s3cmd=1.1.0*
|
s3cmd=1.1.0*
|
||||||
|
|
||||||
|
Writing the instruction this way also helps you avoid potential duplication of
|
||||||
|
a given package because it is much easier to read than an instruction like:
|
||||||
|
|
||||||
|
RUN apt-get install -y package-foo && apt-get install -y package-bar
|
||||||
|
|
||||||
### [`CMD`](https://docs.docker.com/reference/builder/#cmd)
|
### [`CMD`](https://docs.docker.com/reference/builder/#cmd)
|
||||||
|
|
||||||
The `CMD` instruction should be used to run the software contained by your
|
The `CMD` instruction should be used to run the software contained by your
|
||||||
|
@ -290,7 +292,11 @@ is much easier to understand than
|
||||||
|
|
||||||
....docker run -it --entrypoint bash official-image -i
|
....docker run -it --entrypoint bash official-image -i
|
||||||
|
|
||||||
especially for Docker beginners.
|
This is especially true for new Docker users, who might naturally assume the
|
||||||
|
above command will work fine. In cases where an image uses `ENTRYPOINT` for
|
||||||
|
anything other than just a wrapper script, the command will fail and the
|
||||||
|
beginning user will then be forced to learn about `ENTRYPOINT` and
|
||||||
|
`--entrypoint`.
|
||||||
|
|
||||||
In order to avoid a situation where commands are run without clear visibility
|
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
|
to the user, make sure your script ends with something like `exec "$@"`. After
|
||||||
|
@ -339,9 +345,9 @@ 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
|
user. Start by creating the user and group in the `Dockerfile` with something
|
||||||
like `RUN groupadd -r postgres && useradd -r -g postgres postgres`.
|
like `RUN groupadd -r postgres && useradd -r -g postgres postgres`.
|
||||||
|
|
||||||
>**Note** Users and groups in an image get a non-deterministic
|
> **Note:** Users and groups in an image get a non-deterministic
|
||||||
>UID/GID in that the “next” UID/GID gets assigned regardless of image
|
> UID/GID in that the “next” UID/GID gets assigned regardless of image
|
||||||
>rebuilds. So, if it’s critical, you should assign an explicit UID/GID.
|
> 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
|
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
|
signal-forwarding behavior that can cause more more problems than it solves. If
|
||||||
|
|
|
@ -41,7 +41,7 @@ Your `Dockerfile` should adhere to the following:
|
||||||
established Official Image.
|
established Official Image.
|
||||||
* It must follow `Dockerfile` best practices. These are discussed on the
|
* It must follow `Dockerfile` best practices. These are discussed on the
|
||||||
[best practices page](/articles/dockerfile_best-practices). In addition,
|
[best practices page](/articles/dockerfile_best-practices). In addition,
|
||||||
Docker engineer Michael Crosby has some good tips for Dockerfiles in
|
Docker engineer Michael Crosby has some good tips for `Dockerfiles` in
|
||||||
this [blog post](http://crosbymichael.com/dockerfile-best-practices-take-2.html).
|
this [blog post](http://crosbymichael.com/dockerfile-best-practices-take-2.html).
|
||||||
|
|
||||||
While [`ONBUILD` triggers](https://docs.docker.com/reference/builder/#onbuild)
|
While [`ONBUILD` triggers](https://docs.docker.com/reference/builder/#onbuild)
|
||||||
|
@ -77,7 +77,7 @@ can be made based on the logo needed
|
||||||
|
|
||||||
### A long description
|
### A long description
|
||||||
|
|
||||||
Include a comprehensive description of your image (in markdown format, GitHub
|
Include a comprehensive description of your image (in Markdown format, GitHub
|
||||||
flavor preferred). Only one description is required; you don’t need additional
|
flavor preferred). Only one description is required; you don’t need additional
|
||||||
descriptions for each tag. The file should also:
|
descriptions for each tag. The file should also:
|
||||||
|
|
||||||
|
@ -88,9 +88,9 @@ content requirements
|
||||||
|
|
||||||
In terms of content, the long description must include the following sections:
|
In terms of content, the long description must include the following sections:
|
||||||
|
|
||||||
* Overview & Links
|
* Overview & links
|
||||||
* How-to/Usage
|
* How-to/usage
|
||||||
* Issues & Contribution Info
|
* Issues & contributions
|
||||||
|
|
||||||
#### Overview & links
|
#### Overview & links
|
||||||
|
|
||||||
|
@ -109,15 +109,15 @@ 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-
|
cases and example `Dockerfile`s (if applicable). Try to provide clear, step-by-
|
||||||
step instructions wherever possible.
|
step instructions wherever possible.
|
||||||
|
|
||||||
##### Issues & contribution info
|
##### Issues & contributions
|
||||||
|
|
||||||
In this section, point users to any resources that can help them contribute to
|
In this section, point users to any resources that can help them contribute to
|
||||||
the project. Include contribution guidelines and any specific instructions
|
the project. Include contribution guidelines and any specific instructions
|
||||||
related to your development practices. Include a link to
|
related to your development practices. Include a link to
|
||||||
[Docker’s resources for contributors](https://docs.docker.com/contributing/contributing/).
|
[Docker’s resources for contributors](https://docs.docker.com/contributing/contributing/).
|
||||||
Be sure to include contact info, handles, etc. for official maintainers.
|
Be sure to include contact info, handles, etc. for official maintainers.
|
||||||
|
|
||||||
##### Issues
|
Also include information letting users know where they can go for help and how
|
||||||
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,
|
they can file issues with the repo. Point them to any specific IRC channels,
|
||||||
issue trackers, contacts, additional “how-to” information or other resources.
|
issue trackers, contacts, additional “how-to” information or other resources.
|
||||||
|
|
||||||
|
@ -125,8 +125,9 @@ issue trackers, contacts, additional “how-to” information or other resources
|
||||||
|
|
||||||
Include a file, `LICENSE`, of any applicable license. Docker recommends using
|
Include a file, `LICENSE`, of any applicable license. Docker recommends using
|
||||||
the license of the software contained in the image, provided it allows Docker,
|
the license of the software contained in the image, provided it allows Docker,
|
||||||
Inc. to legally build and distribute the image. Otherwise, Docker recommends
|
Inc. to legally build and distribute the image. Otherwise, Docker recommends
|
||||||
adopting the [Expat license](http://directory.fsf.org/wiki/License:Expat).
|
adopting the [Expat license](http://directory.fsf.org/wiki/License:Expat)
|
||||||
|
(a.k.a., the MIT or X11 license).
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
@ -160,7 +161,7 @@ Put this file in the root of your app, next to the `Gemfile`.
|
||||||
|
|
||||||
This image includes multiple `ONBUILD` triggers so that should be all that you need for most applications. The build will `ADD . /usr/src/app`, `RUN bundle install`, `EXPOSE 3000`, and set the default command to `rails server`.
|
This image includes multiple `ONBUILD` triggers so that should be all that you need for most applications. The build will `ADD . /usr/src/app`, `RUN bundle install`, `EXPOSE 3000`, and set the default command to `rails server`.
|
||||||
|
|
||||||
Then build and run the docker image.
|
Then build and run the Docker image.
|
||||||
|
|
||||||
docker build -t my-rails-app .
|
docker build -t my-rails-app .
|
||||||
docker run --name some-rails-app -d my-rails-app
|
docker run --name some-rails-app -d my-rails-app
|
||||||
|
@ -169,7 +170,7 @@ Test it by visiting `http://container-ip:3000` in a browser. On the other hand,
|
||||||
|
|
||||||
docker run --name some-rails-app -p 8080:3000 -d my-rails-app
|
docker run --name some-rails-app -p 8080:3000 -d my-rails-app
|
||||||
|
|
||||||
Then hit `http://localhost:8080` or `http://host-ip:8080` in a browser.
|
Then go to `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:
|
||||||
|
@ -182,4 +183,7 @@ For more examples, take a look at these repos:
|
||||||
|
|
||||||
## Submit your repo
|
## Submit your repo
|
||||||
|
|
||||||
Once you've checked off everything in these guidelines, and are confident your image is ready for primetime, please contact us at [partners@docker.com](mailto:partners@docker.com) to have your project considered for the Official Repos program.
|
Once you've checked off everything in these guidelines, and are confident your
|
||||||
|
image is ready for primetime, please contact us at
|
||||||
|
[partners@docker.com](mailto:partners@docker.com) to have your project
|
||||||
|
considered for the Official Repos program.
|
||||||
|
|
Loading…
Reference in New Issue