mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #15773 from charleswhchan/patch-3
Fix #14572: Improve explaination for using `RUN` command inside Docke…
This commit is contained in:
commit
5e8038d0b0
1 changed files with 72 additions and 48 deletions
|
@ -140,72 +140,96 @@ since it’s very tightly controlled and kept extremely minimal (currently under
|
|||
[Dockerfile reference for the RUN instruction](https://docs.docker.com/reference/builder/#run)
|
||||
|
||||
As always, to make your `Dockerfile` more readable, understandable, and
|
||||
maintainable, put long or complex `RUN` statements on multiple lines separated
|
||||
maintainable, split long or complex `RUN` 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 are a few things to keep in mind:
|
||||
### apt-get
|
||||
|
||||
* 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
|
||||
subsequent `apt-get install` fail without comment.
|
||||
Probably the most common use-case for `RUN` is an application of `apt-get`. The
|
||||
`RUN apt-get` command, because it installs packages, has several gotchas to look
|
||||
out for.
|
||||
|
||||
* 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.
|
||||
You should avoid `RUN apt-get upgrade` or `dist-upgrade`, as many of the
|
||||
“essential” packages from the base images won't upgrade inside an unprivileged
|
||||
container. If a package contained in the base image 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` to update automatically.
|
||||
|
||||
* Do write instructions like:
|
||||
Always combine `RUN apt-get update` with `apt-get install` in the same `RUN`
|
||||
statement, for example:
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
package-bar \
|
||||
package-baz \
|
||||
package-foo
|
||||
|
||||
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.*`). This will force retrieval of that version
|
||||
regardless of what’s in the cache.
|
||||
Writing your `apt-get` code this way will greatly ease maintenance and reduce
|
||||
failures due to unanticipated changes in required packages.
|
||||
Using `apt-get update` alone in a `RUN` statement causes caching issues and
|
||||
subsequent `apt-get install` instructions fail.
|
||||
For example, say you have a Dockerfile:
|
||||
|
||||
#### Example
|
||||
FROM ubuntu:14.04
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y curl
|
||||
|
||||
Below is a well-formed `RUN` instruction that demonstrates the above
|
||||
recommendations. Note that the last package, `s3cmd`, specifies a version
|
||||
`1.1.0*`. If the image previously used an older version, specifying the new one
|
||||
will cause a cache bust of `apt-get update` and ensure the installation of
|
||||
the new version (which in this case had a new, required feature).
|
||||
After building the image, all layers are in the Docker cache. Suppose you later
|
||||
modify `apt-get install` by adding extra package:
|
||||
|
||||
FROM ubuntu:14.04
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y curl nginx
|
||||
|
||||
Docker sees the initial and modified instructions as identical and reuses the
|
||||
cache from previous steps. As a result the `apt-get update` is *NOT* executed
|
||||
because the build uses the cached version. Because the `apt-get update` is not
|
||||
run, your build can potentially get an outdated version of the `curl` and `nginx`
|
||||
packages.
|
||||
|
||||
Using `RUN apt-get update && apt-get install -y` ensures your Dockerfile
|
||||
installs the latest package versions with no further coding or manual
|
||||
intervention. This technique is known as "cache busting". You can also achieve
|
||||
cache-busting by specifying a package version. This is known as version pinning,
|
||||
for example:
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
package-bar \
|
||||
package-baz \
|
||||
package-foo=1.3.*
|
||||
|
||||
Version pinning forces the build to retrieve a particular version regardless of
|
||||
what’s in the cache. This technique can also reduce failures due to unanticipated changes
|
||||
in required packages.
|
||||
|
||||
Below is a well-formed `RUN` instruction that demonstrates all the `apt-get`
|
||||
recommendations.
|
||||
|
||||
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*
|
||||
s3cmd=1.1.* \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
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:
|
||||
The `s3cmd` instructions specifies a version `1.1.0*`. If the image previously
|
||||
used an older version, specifying the new one causes a cache bust of `apt-get
|
||||
update` and ensure the installation of the new version. Listing packages on
|
||||
each line can also prevent mistakes in package duplication.
|
||||
|
||||
RUN apt-get install -y package-foo && apt-get install -y package-bar
|
||||
In addition, cleaning up the apt cache and removing `/var/lib/apt/lists` helps
|
||||
keep the image size down. Since the `RUN` statement starts with
|
||||
`apt-get update`, the package cache will always be refreshed prior to
|
||||
`apt-get install`.
|
||||
|
||||
### CMD
|
||||
|
||||
|
|
Loading…
Reference in a new issue