Typo and formatting fixes. Copy edits.
Docker-DCO-1.1-Signed-off-by: Fred Lifton <fred.lifton@docker.com> (github: fredlf)
This commit is contained in:
parent
d9fd5f6199
commit
6747dfc803
|
@ -2,8 +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 `Dockerfile`s
|
||||||
# Best Practices for Writing `Dockerfile`s
|
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
|
@ -90,7 +89,7 @@ mb), while still being a full distribution.
|
||||||
### [`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 statements on multiple lines separated with
|
maintainable, put long or complex `RUN` statements on multiple lines separated with
|
||||||
backslashes.
|
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`.
|
||||||
|
@ -103,7 +102,7 @@ subsequent `apt-get install` fail without comment.
|
||||||
* For the most part, to keep your code more readable and maintainable, avoid
|
* 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`.
|
`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.
|
* 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
|
* 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
|
package-baz`. Writing the instruction this way not only makes it easier to read
|
||||||
|
@ -112,9 +111,8 @@ will naturally be busted and the latest versions will be installed with no
|
||||||
further coding or manual intervention required.
|
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*`) since it will force retrieval of that version
|
(e.g., `package-foo=1.3.*`) since it 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
|
Forming 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.
|
||||||
|
|
||||||
|
@ -150,13 +148,13 @@ that version (which in this case had a new, required feature).
|
||||||
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
|
||||||
image, along with any arguments. `CMD` should almost always be used in the
|
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
|
form of `CMD [“executable”, “param1”, “param2”…]`. Thus, if the image is for a
|
||||||
service (Apache, Rails, etc.), you would run something like `CMD ["apache2",
|
service (Apache, Rails, etc.), you would run something like
|
||||||
"-DFOREGROUND"]`. Indeed, this form of the instruction is recommended for any
|
`CMD ["apache2","-DFOREGROUND"]`. Indeed, this form of the instruction is
|
||||||
service-based image.
|
recommended for any service-based image.
|
||||||
|
|
||||||
In most other cases, `CMD` should be given an interactive shell (bash, python,
|
In most other cases, `CMD` should be given an interactive shell (bash, python,
|
||||||
perl, etc). For example, `CMD ["perl", "-de0"]`, `CMD ["python"]`, or `CMD
|
perl, etc). For example, `CMD ["perl", "-de0"]`, `CMD ["python"]`, or
|
||||||
[“php”, “-a”]`. Using this form means that when you execute something like
|
`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.
|
`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
|
`CMD` should rarely be used in the manner of `CMD [“param”, “param”]` in
|
||||||
conjunction with [`ENTRYPOINT`](https://docs.docker.com/reference/builder/#entrypoint), unless
|
conjunction with [`ENTRYPOINT`](https://docs.docker.com/reference/builder/#entrypoint), unless
|
||||||
|
@ -199,17 +197,15 @@ Similar to having constant variables in a program (as opposed to hard-coding
|
||||||
values), this approach lets you change a single `ENV` instruction to
|
values), this approach lets you change a single `ENV` instruction to
|
||||||
auto-magically bump the version of the software in your container.
|
auto-magically bump the version of the software in your container.
|
||||||
|
|
||||||
### [`ADD`](https://docs.docker.com/reference/builder/#add) or
|
### [`ADD`](https://docs.docker.com/reference/builder/#add) or [`COPY`](https://docs.docker.com/reference/builder/#copy)
|
||||||
[`COPY`](https://docs.docker.com/reference/builder/#copy)
|
|
||||||
|
|
||||||
Although `ADD` and `COPY` are functionally similar, generally speaking, `COPY`
|
Although `ADD` and `COPY` are functionally similar, generally speaking, `COPY`
|
||||||
is preferred. That’s because it’s more transparent than `ADD`. `COPY` only
|
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
|
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
|
some features (like local-only tar extraction and remote URL support) that are
|
||||||
not immediately obvious.
|
not immediately obvious. Consequently, the best use for `ADD` is local tar file
|
||||||
|
auto-extraction into the image, as in `ADD rootfs.tar.xz /`.
|
||||||
|
|
||||||
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
|
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
|
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
|
extracted without having to add another layer in your image. For example, you
|
||||||
|
@ -220,27 +216,29 @@ should avoid doing things like:
|
||||||
RUN make -C /usr/src/things all
|
RUN make -C /usr/src/things all
|
||||||
|
|
||||||
And instead, do something like:
|
And instead, do something like:
|
||||||
|
|
||||||
RUN mdkir -p /usr/src/things \
|
RUN mdkir -p /usr/src/things \
|
||||||
&& curl -SL http://example.com/big.tar.gz \
|
&& curl -SL http://example.com/big.tar.gz \
|
||||||
| tar -xJC /usr/src/things \
|
| tar -xJC /usr/src/things \
|
||||||
&& make -C /usr/src/things all
|
&& make -C /usr/src/things all
|
||||||
|
|
||||||
For other items (files, directories) that do not require `ADD`’s tar
|
For other items (files, directories) that do not require `ADD`’s tar
|
||||||
auto-extraction capability, you should always use `COPY`.
|
auto-extraction capability, you should always use `COPY`.
|
||||||
|
|
||||||
### [`ENTRYPOINT`](https://docs.docker.com/reference/builder/#entrypoint)
|
### [`ENTRYPOINT`](https://docs.docker.com/reference/builder/#entrypoint)
|
||||||
|
|
||||||
The best use for `ENTRYPOINT` is as a helper script. Using `ENTRYPOINT` for
|
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
|
other tasks can make your code harder to understand. For example,
|
||||||
-it official-image bash` is much easier to understand than `docker run -it
|
`docker run -it official-image bash` is much easier to understand than
|
||||||
--entrypoint bash official-image -i`, especially for Docker beginners.
|
`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
|
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
|
||||||
the entrypoint completes, the script will transparently bootstrap the command
|
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,
|
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
|
`docker run -it mysql mysqld --some --flags` will transparently run
|
||||||
--some --flags` after `ENTRYPOINT` runs `initdb`).
|
`mysqld --some --flags` after `ENTRYPOINT` runs `initdb`).
|
||||||
|
|
||||||
For example, let’s look at the `Dockerfile` for the
|
For example, let’s look at the `Dockerfile` for the
|
||||||
[Postgres Official Image](https://github.com/docker-library/postgres).
|
[Postgres Official Image](https://github.com/docker-library/postgres).
|
||||||
|
@ -271,10 +269,10 @@ container startup:
|
||||||
|
|
||||||
### [`VOLUME`](https://docs.docker.com/reference/builder/#volume)
|
### [`VOLUME`](https://docs.docker.com/reference/builder/#volume)
|
||||||
|
|
||||||
`VOLUME` should be used to expose any database storage area, configuration
|
The `VOLUME` instruction should be used to expose any database storage area,
|
||||||
storage, or files/folders created by your docker container. You are strongly
|
configuration storage, or files/folders created by your docker container. You
|
||||||
encouraged to use `VOLUME` for any mutable and/or user-serviceable parts of
|
are strongly encouraged to use `VOLUME` for any mutable and/or user-serviceable
|
||||||
your image.
|
parts of your image.
|
||||||
|
|
||||||
### [`USER`](https://docs.docker.com/reference/builder/#user)
|
### [`USER`](https://docs.docker.com/reference/builder/#user)
|
||||||
|
|
||||||
|
@ -282,9 +280,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** that users/groups in an image get assigned nondeterministic UID/GID in
|
>**Note** that users/groups in an image get assigned a non-deterministic
|
||||||
>that the “next” UID/GID will be assigned regardless of image rebuilds. So, if
|
>UID/GID in that the “next” UID/GID gets assigned regardless of image
|
||||||
>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
|
||||||
|
@ -320,6 +318,7 @@ separate tag, as recommended above, will help mitigate this by allowing the
|
||||||
## Examples For Official Repositories
|
## Examples For Official Repositories
|
||||||
|
|
||||||
These Official Repos have exemplary `Dockerfile`s:
|
These Official Repos have exemplary `Dockerfile`s:
|
||||||
|
|
||||||
* [Go](https://registry.hub.docker.com/_/golang/)
|
* [Go](https://registry.hub.docker.com/_/golang/)
|
||||||
* [Perl](https://registry.hub.docker.com/_/perl/)
|
* [Perl](https://registry.hub.docker.com/_/perl/)
|
||||||
* [Hy](https://registry.hub.docker.com/_/hylang/)
|
* [Hy](https://registry.hub.docker.com/_/hylang/)
|
||||||
|
|
|
@ -7,16 +7,15 @@ page_keywords: Docker, docker, registry, accounts, plans, Dockerfile, Docker Hub
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
You’ve been given the job of creating an image for an Official Repository
|
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
|
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
|
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
|
planning to create an Official Repo, you can think of these guidelines as best
|
||||||
practices for image creation generally.
|
practices for image creation generally.
|
||||||
|
|
||||||
This document consists of three major sections:
|
This document consists of two major sections:
|
||||||
|
|
||||||
* Expected files, resources and supporting items for your image
|
* A list of expected files, resources and supporting items for your image
|
||||||
* Examples embodying those practices
|
* Examples embodying those practices
|
||||||
* Instructions for submitting contributions and reporting issues
|
|
||||||
|
|
||||||
## Expected Files & Resources
|
## Expected Files & Resources
|
||||||
|
|
||||||
|
@ -28,8 +27,8 @@ directly.) Docker **strongly** recommends that this repo be publicly
|
||||||
accessible.
|
accessible.
|
||||||
|
|
||||||
If the repo is private or has otherwise limited access, you must provide a
|
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-
|
means of at least “read-only” access for both general users and for the
|
||||||
library maintainers, who need access for review and building purposes.
|
docker-library maintainers, who need access for review and building purposes.
|
||||||
|
|
||||||
### A `Dockerfile`
|
### A `Dockerfile`
|
||||||
|
|
||||||
|
@ -41,7 +40,7 @@ Your `Dockerfile` should adhere to the following:
|
||||||
established Official Image.
|
established Official Image.
|
||||||
* It must follow `Dockerfile` best practices. These are discussed in the
|
* It must follow `Dockerfile` best practices. These are discussed in the
|
||||||
[Best Practices document](/articles/dockerfile_best-practices). In addition,
|
[Best Practices document](/articles/dockerfile_best-practices). In addition,
|
||||||
Docker, Inc. engineer Michael Crosby has a good discussion of Dockerfiles in
|
Docker engineer Michael Crosby has a good discussion of 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)
|
||||||
|
@ -89,10 +88,9 @@ In terms of content, the long description must include the following sections:
|
||||||
|
|
||||||
* Overview & Links
|
* Overview & Links
|
||||||
* How-to/Usage
|
* How-to/Usage
|
||||||
* User Feedback
|
* Issues & Contribution Info
|
||||||
|
|
||||||
#### Overview & links
|
#### Overview & links
|
||||||
|
|
||||||
A section providing (a) an overview of the software contained in the image,
|
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
|
similar to the introduction in a Wikipedia entry and (b) a selection of links
|
||||||
to outside resources that help to describe the software.
|
to outside resources that help to describe the software.
|
||||||
|
@ -100,13 +98,11 @@ to outside resources that help to describe the software.
|
||||||
This section *must* also include a link to the `Dockerfile`.
|
This section *must* also include a link to the `Dockerfile`.
|
||||||
|
|
||||||
#### How-to/usage
|
#### How-to/usage
|
||||||
|
|
||||||
A section that describes how to run and use the image, including common use
|
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.
|
||||||
|
|
||||||
##### Contributing
|
##### Issues & Contribution Info
|
||||||
|
|
||||||
In this part, point users to any resources that can help them contribute to the
|
In this part, point users to any resources that can help them contribute to the
|
||||||
project. Include contribution guidelines and any specific instructions related
|
project. Include contribution guidelines and any specific instructions related
|
||||||
to your development practices. Include a link to
|
to your development practices. Include a link to
|
||||||
|
@ -114,7 +110,6 @@ to your development practices. Include a link to
|
||||||
Be sure to include contact info, handles, etc. for official maintainers.
|
Be sure to include contact info, handles, etc. for official maintainers.
|
||||||
|
|
||||||
##### Issues
|
##### Issues
|
||||||
|
|
||||||
Include a brief section 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.
|
||||||
|
|
Loading…
Reference in New Issue