mirror of https://github.com/docker/docs.git
Merge pull request #15603 from jedevc/cache-docs
Add build cache introduction docs
This commit is contained in:
commit
99370cd8dc
|
@ -1387,6 +1387,8 @@ manuals:
|
|||
section:
|
||||
- path: /build/building/packaging/
|
||||
title: Packaging your software
|
||||
- path: /build/building/cache/
|
||||
title: Optimizing builds with cache management
|
||||
- sectiontitle: Choosing a build driver
|
||||
section:
|
||||
- path: /build/building/drivers/
|
||||
|
|
|
@ -180,6 +180,11 @@ body.night {
|
|||
img.white-bg {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
/* apply to images that support being inverted */
|
||||
img.invertible {
|
||||
filter: invert(100%) hue-rotate(180deg);
|
||||
}
|
||||
|
||||
/* accordion */
|
||||
.panel {
|
||||
|
|
|
@ -0,0 +1,294 @@
|
|||
---
|
||||
title: Optimizing builds with cache management
|
||||
description: Improve your build speeds by taking advantage of the builtin cache
|
||||
keywords: >
|
||||
build, buildx, buildkit, dockerfile, image layers, build instructions, build
|
||||
context
|
||||
---
|
||||
|
||||
You will likely find yourself rebuilding the same Docker image over and over
|
||||
again. Whether it's for the next release of your software, or locally during
|
||||
development. Because building images is a common task, Docker provides several
|
||||
tools that speed up builds.
|
||||
|
||||
The most important feature for improving build speeds is Docker's build cache.
|
||||
|
||||
## How does the build cache work?
|
||||
|
||||
Understanding Docker's build cache helps you write better Dockerfiles that
|
||||
result in faster builds.
|
||||
|
||||
Have a look at the following example, which shows a simple Dockerfile for a
|
||||
program written in C.
|
||||
|
||||
```dockerfile
|
||||
FROM ubuntu:latest
|
||||
|
||||
RUN apt-get update && apt-get install -y build-essentials
|
||||
COPY main.c /src/
|
||||
WORKDIR /src/
|
||||
RUN make build
|
||||
```
|
||||
|
||||
Each instruction in this Dockerfile translates (roughly) to a layer in your
|
||||
final image. You can think of image layers as a stack, with each layer adding
|
||||
more content on top of the layers that came before it:
|
||||
|
||||
{:.invertible}
|
||||
|
||||
Whenever a layer changes, that layer will need to be re-built. For example,
|
||||
suppose you make a change to your program in the `main.c` file. After this
|
||||
change, the `COPY` command will have to run again in order for those changes to
|
||||
appear in the image. In other words, Docker will invalidate the cache for this
|
||||
layer.
|
||||
|
||||
{:.invertible}
|
||||
|
||||
If a layer changes, all other layers that come after it are also affected. When
|
||||
the layer with the `COPY` command gets invalidated, all layers that follow will
|
||||
need to run again, too:
|
||||
|
||||
{:.invertible}
|
||||
|
||||
And that's the Docker build cache in a nutshell. Once a layer changes, then all
|
||||
downstream layers need to be rebuilt as well. Even if they wouldn't build
|
||||
anything differently, they still need to re-run.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> Suppose you have a `RUN apt-get update && apt-get upgrade -y` step in your
|
||||
> Dockerfile to upgrade all the software packages in your Debian-based image to
|
||||
> the latest version.
|
||||
>
|
||||
> This doesn't mean that the images you build are always up to date. Rebuilding
|
||||
> the image on the same host one week later will still get you the same packages
|
||||
> as before. The only way to force a rebuild is by making sure that a layer
|
||||
> before it has changed, or by clearing the build cache using
|
||||
> [`docker builder prune`](/engine/reference/commandline/builder_build/).
|
||||
|
||||
## How can I use the cache efficiently?
|
||||
|
||||
Now that you understand how the cache works, you can begin to use the cache to
|
||||
your advantage. While the cache will automatically work on any `docker build`
|
||||
that you run, you can often refactor your Dockerfile to get even better
|
||||
performance. These optimizations can save precious seconds (or even minutes) off
|
||||
of your builds.
|
||||
|
||||
### Order your layers
|
||||
|
||||
Putting the commands in your Dockerfile into a logical order is a great place to
|
||||
start. Because a change causes a rebuild for steps that follow, try to make
|
||||
expensive steps appear near the beginning of the Dockerfile. Steps that change
|
||||
often should appear near the end of the Dockerfile, to avoid triggering rebuilds
|
||||
of layers that haven't changed.
|
||||
|
||||
Consider the following example. A Dockerfile snippet that runs a JavaScript
|
||||
build from the source files in the current directory:
|
||||
|
||||
```dockerfile
|
||||
FROM node
|
||||
WORKDIR /app
|
||||
COPY . . # Copy over all files in the current directory
|
||||
RUN npm install # Install dependencies
|
||||
RUN npm build # Run build
|
||||
```
|
||||
|
||||
This Dockerfile is rather inefficient. Updating any file causes a reinstall of
|
||||
all dependencies every time you build the Docker image &emdash; even if the
|
||||
dependencies didn't change since last time!
|
||||
|
||||
Instead, the `COPY` command can be split in two. First, copy over the package
|
||||
management files (in this case, `package.json` and `yarn.lock`). Then, install
|
||||
the dependencies. Finally, copy over the project source code, which is subject
|
||||
to frequent change.
|
||||
|
||||
```dockerfile
|
||||
FROM node
|
||||
WORKDIR /app
|
||||
COPY package.json yarn.lock . # Copy package management files
|
||||
RUN npm install # Install dependencies
|
||||
COPY . . # Copy over project files
|
||||
RUN npm build # Run build
|
||||
```
|
||||
|
||||
By installing dependencies in earlier layers of the Dockerfile, there is no need
|
||||
to rebuild those layers when a project file has changed.
|
||||
|
||||
### Keep layers small
|
||||
|
||||
One of the best things you can do to speed up image building is to just put less
|
||||
stuff into your build. Fewer parts means the cache stay smaller, but also that
|
||||
there should be fewer things that could be out-of-date and need rebuilding.
|
||||
|
||||
To get started, here are a few tips and tricks:
|
||||
|
||||
#### Don't include unnecessary files
|
||||
|
||||
Be considerate of what files you add to the image.
|
||||
|
||||
Running a command like `COPY . /src` will `COPY` your entire build context into
|
||||
the image. If you've got logs, package manager artifacts, or even previous build
|
||||
results in your current directory, those will also be copied over. This could
|
||||
make your image larger than it needs to be, especially as those files are
|
||||
usually not useful.
|
||||
|
||||
Avoid adding unnecessary files to your builds by explicitly stating the files or
|
||||
directories you intend to copy over. For example, you might only want to add a
|
||||
`Makefile` and your `src` directory to the image filesystem. In that case,
|
||||
consider adding this to your Dockerfile:
|
||||
|
||||
```dockerfile
|
||||
COPY ./src ./Makefile /src
|
||||
```
|
||||
|
||||
As opposed to this:
|
||||
|
||||
```dockerfile
|
||||
COPY . /src
|
||||
```
|
||||
|
||||
You can also create a
|
||||
[`.dockerignore` file](https://docs.docker.com/engine/reference/builder/#dockerignore-file),
|
||||
and use that to specify which files and directories to exclude from the build
|
||||
context.
|
||||
|
||||
#### Use your package manager wisely
|
||||
|
||||
Most Docker image builds involve using a package manager to help install
|
||||
software into the image. Debian has `apt`, Alpine has `apk`, Python has `pip`,
|
||||
NodeJS has `npm`, and so on.
|
||||
|
||||
When installing packages, be considerate. Make sure to only install the packages
|
||||
that you need. If you're not going to use them, don't install them. Remember
|
||||
that this might be a different list for your local development environment and
|
||||
your production environment. You can use multi-stage builds to split these up
|
||||
efficiently.
|
||||
|
||||
#### Use the dedicated `RUN` cache
|
||||
|
||||
The `RUN` command supports a specialized cache, which you can use when you need
|
||||
a more fine-grained cache between runs. For example, when installing packages,
|
||||
you don't always need to fetch all of your packages from the internet each time.
|
||||
You only need the ones that have changed.
|
||||
|
||||
To solve this problem, you can use `RUN --mount type=cache`. For example, for
|
||||
your Debian-based image you might use the following:
|
||||
|
||||
```dockerfile
|
||||
RUN \
|
||||
--mount=type=cache,target=/var/cache/apt \
|
||||
apt-get update && apt-get install -y git
|
||||
```
|
||||
|
||||
Using the explicit cache with the `--mount` flag keeps the contents of the
|
||||
`target` directory preserved between builds. When this layer needs to be
|
||||
rebuilt, then it'll use the `apt` cache in `/var/cache/apt`.
|
||||
|
||||
### Minimize the number of layers
|
||||
|
||||
Keeping your layers small is a good first step, and the logical next step is to
|
||||
reduce the number of layers that you have. Fewer layers mean that you have less
|
||||
to rebuild, when something in your Dockerfile changes, so your build will
|
||||
complete faster.
|
||||
|
||||
The following sections outline some tips you can use to keep the number of
|
||||
layers to a minimum.
|
||||
|
||||
#### Use an appropriate base image
|
||||
|
||||
Docker provides over 170 pre-built
|
||||
[official images](https://hub.docker.com/search?q=&image_filter=official) for
|
||||
almost every common development scenario. For example, if you're building a Java
|
||||
web server, use a dedicated image such as
|
||||
[`openjdk`](https://hub.docker.com/_/openjdk/). Even when there's not an
|
||||
official image for what you might want, Docker provides images from
|
||||
[verified publishers](https://hub.docker.com/search?q=&image_filter=store) and
|
||||
[open source partners](https://hub.docker.com/search?q=&image_filter=open_source)
|
||||
that can help you on your way. The Docker community often produces third-party
|
||||
images to use as well.
|
||||
|
||||
Using official images saves you time and ensures you stay up to date and secure
|
||||
by default.
|
||||
|
||||
#### Use multi-stage builds
|
||||
|
||||
<!-- x-link to multi-stage builds once we have some reworked content for that -->
|
||||
|
||||
Multi-stage builds let you split up your Dockerfile into multiple distinct
|
||||
stages. Each stage completes a step in the build process, and you can bridge the
|
||||
different stages to create your final image at the end. The Docker builder will
|
||||
work out dependencies between the stages and run them using the most efficient
|
||||
strategy. This even allows you to run multiple builds concurrently.
|
||||
|
||||
Multi-stage builds use two or more `FROM` commands. The following example
|
||||
illustrates building a simple web server that serves HTML from your `docs`
|
||||
directory in Git:
|
||||
|
||||
```dockerfile
|
||||
# stage 1
|
||||
FROM alpine as git
|
||||
RUN apk add git
|
||||
|
||||
# stage 2
|
||||
FROM git as fetch
|
||||
WORKDIR /repo
|
||||
RUN git clone https://github.com/your/repository.git .
|
||||
|
||||
# stage 3
|
||||
FROM nginx as site
|
||||
COPY --from=fetch /repo/docs/ /usr/share/nginx/html
|
||||
```
|
||||
|
||||
This build has 3 stages: `git`, `fetch` and `site`. In this example, `git` is
|
||||
the base for the `fetch` stage. It uses the `COPY --from` flag to copy the data
|
||||
from the `docs/` directory into the Nginx server directory.
|
||||
|
||||
Each stage has only a few instructions, and when possible, Docker will run these
|
||||
stages in parallel. Only the instructions in the `site` stage will end up as
|
||||
layers in the final image. The entire `git` history doesn't get embedded into
|
||||
the final result, which helps keep the image small and secure.
|
||||
|
||||
#### Combine commands together wherever possible.
|
||||
|
||||
Most Dockerfile commands, and `RUN` commands in particular, can often be joined
|
||||
together. For example, instead of using `RUN` like this:
|
||||
|
||||
```dockerfile
|
||||
RUN echo "the first command"
|
||||
RUN echo "the second command"
|
||||
```
|
||||
|
||||
It's possible to run both of these commands inside a single `RUN`, which means
|
||||
that they will share the same cache! This can is achievable using the `&&` shell
|
||||
operator to run one command after another:
|
||||
|
||||
```dockerfile
|
||||
RUN echo "the first command" && echo "the second command"
|
||||
# or to split to multiple lines
|
||||
RUN echo "the first command" && \
|
||||
echo "the second command"
|
||||
```
|
||||
|
||||
Another shell feature that allows you to simplify and concatenate commands in a
|
||||
neat way are [`heredocs`](https://en.wikipedia.org/wiki/Here_document){:
|
||||
target="blank" rel="noopener" class="\_"}. It enables you to create multi-line
|
||||
scripts with good readability:
|
||||
|
||||
```dockerfile
|
||||
RUN <<EOF
|
||||
set -e
|
||||
echo "the first command"
|
||||
echo "the second command"
|
||||
EOF
|
||||
```
|
||||
|
||||
(Note the `set -e` command to exit immediately after any command fails, instead
|
||||
of continuing.)
|
||||
|
||||
## Other resources
|
||||
|
||||
For more information on using cache to do efficient builds:
|
||||
|
||||
<!-- x-link to dedicated cache exporter content once that's written -->
|
||||
|
||||
- [Export your build cache](https://github.com/moby/buildkit#export-cache)
|
|
@ -0,0 +1,19 @@
|
|||
// dot -Tsvg ./cache-invalidate-copy.dot > ./cache-invalidate-copy.svg
|
||||
digraph {
|
||||
rankdir="LR";
|
||||
nodesep=0.3;
|
||||
edge[minlen=0];
|
||||
bgcolor="#00000000";
|
||||
node [ shape=rect, width=5, height=0.4, fontname=monospace, fontsize=10 ];
|
||||
|
||||
from [ label = <<B>FROM </B>ubuntu:latest> ];
|
||||
deps [ label = <<B>RUN </B>apt-get update && \\<br/>apt-get install -y build-essentials> ];
|
||||
copy [ label = <<B>COPY </B>main.c /src/>, color = "red" ];
|
||||
workdir [ label = <<B>WORKDIR </B>/src/> ];
|
||||
build [ label = <<B>RUN </B>make build> ];
|
||||
|
||||
from -> deps;
|
||||
deps -> copy;
|
||||
copy -> workdir [ color = "red", label = " ❌ " ];
|
||||
workdir -> build;
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 6.0.1 (20220911.1526)
|
||||
-->
|
||||
<!-- Pages: 1 -->
|
||||
<svg width="368pt" height="256pt"
|
||||
viewBox="0.00 0.00 368.00 256.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 252)">
|
||||
<polygon fill="none" stroke="none" points="-4,4 -4,-252 364,-252 364,4 -4,4"/>
|
||||
<!-- from -->
|
||||
<g id="node1" class="node">
|
||||
<title>from</title>
|
||||
<polygon fill="none" stroke="black" points="360,-248 0,-248 0,-219 360,-219 360,-248"/>
|
||||
<text text-anchor="start" x="125" y="-232" font-family="monospace" font-weight="bold" font-size="10.00">FROM </text>
|
||||
<text text-anchor="start" x="156" y="-232" font-family="monospace" font-size="10.00">ubuntu:latest</text>
|
||||
</g>
|
||||
<!-- deps -->
|
||||
<g id="node2" class="node">
|
||||
<title>deps</title>
|
||||
<polygon fill="none" stroke="black" points="360,-197 0,-197 0,-168 360,-168 360,-197"/>
|
||||
<text text-anchor="start" x="110" y="-185.5" font-family="monospace" font-weight="bold" font-size="10.00">RUN </text>
|
||||
<text text-anchor="start" x="135" y="-185.5" font-family="monospace" font-size="10.00">apt-get update && \</text>
|
||||
<text text-anchor="start" x="74.5" y="-175.5" font-family="monospace" font-size="10.00">apt-get install -y build-essentials</text>
|
||||
</g>
|
||||
<!-- from->deps -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>from->deps</title>
|
||||
<path fill="none" stroke="black" d="M180,-218.77C180,-214.96 180,-211.15 180,-207.33"/>
|
||||
<polygon fill="black" stroke="black" points="183.5,-207.24 180,-197.24 176.5,-207.24 183.5,-207.24"/>
|
||||
</g>
|
||||
<!-- copy -->
|
||||
<g id="node3" class="node">
|
||||
<title>copy</title>
|
||||
<polygon fill="none" stroke="red" points="360,-146 0,-146 0,-117 360,-117 360,-146"/>
|
||||
<text text-anchor="start" x="128" y="-130" font-family="monospace" font-weight="bold" font-size="10.00">COPY </text>
|
||||
<text text-anchor="start" x="159" y="-130" font-family="monospace" font-size="10.00">main.c /src/</text>
|
||||
</g>
|
||||
<!-- deps->copy -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>deps->copy</title>
|
||||
<path fill="none" stroke="black" d="M180,-167.77C180,-163.96 180,-160.15 180,-156.33"/>
|
||||
<polygon fill="black" stroke="black" points="183.5,-156.24 180,-146.24 176.5,-156.24 183.5,-156.24"/>
|
||||
</g>
|
||||
<!-- workdir -->
|
||||
<g id="node4" class="node">
|
||||
<title>workdir</title>
|
||||
<polygon fill="none" stroke="black" points="360,-80 0,-80 0,-51 360,-51 360,-80"/>
|
||||
<text text-anchor="start" x="140" y="-64" font-family="monospace" font-weight="bold" font-size="10.00">WORKDIR </text>
|
||||
<text text-anchor="start" x="189" y="-64" font-family="monospace" font-size="10.00">/src/</text>
|
||||
</g>
|
||||
<!-- copy->workdir -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>copy->workdir</title>
|
||||
<path fill="none" stroke="red" d="M180,-116.89C180,-109.12 180,-99.36 180,-90.43"/>
|
||||
<polygon fill="red" stroke="red" points="183.5,-90.15 180,-80.15 176.5,-90.15 183.5,-90.15"/>
|
||||
<text text-anchor="middle" x="169.5" y="-94.8" font-family="Times,serif" font-size="14.00"> ❌  </text>
|
||||
</g>
|
||||
<!-- build -->
|
||||
<g id="node5" class="node">
|
||||
<title>build</title>
|
||||
<polygon fill="none" stroke="black" points="360,-29 0,-29 0,0 360,0 360,-29"/>
|
||||
<text text-anchor="start" x="137" y="-13" font-family="monospace" font-weight="bold" font-size="10.00">RUN </text>
|
||||
<text text-anchor="start" x="162" y="-13" font-family="monospace" font-size="10.00">make build</text>
|
||||
</g>
|
||||
<!-- workdir->build -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>workdir->build</title>
|
||||
<path fill="none" stroke="black" d="M180,-50.77C180,-46.96 180,-43.15 180,-39.33"/>
|
||||
<polygon fill="black" stroke="black" points="183.5,-39.24 180,-29.24 176.5,-39.24 183.5,-39.24"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
|
@ -0,0 +1,19 @@
|
|||
// dot -Tsvg ./cache-invalidate-rest.dot > ./cache-invalidate-rest.svg
|
||||
digraph {
|
||||
rankdir="LR";
|
||||
nodesep=0.3;
|
||||
edge[minlen=0];
|
||||
bgcolor="#00000000";
|
||||
node [ shape=rect, width=5, height=0.4, fontname=monospace, fontsize=10 ];
|
||||
|
||||
from [ label = <<B>FROM </B>ubuntu:latest> ];
|
||||
deps [ label = <<B>RUN </B>apt-get update && \\<br/>apt-get install -y build-essentials> ];
|
||||
copy [ label = <<B>COPY </B>main.c /src/>, color = "red" ];
|
||||
workdir [ label = <<B>WORKDIR </B>/src/>, color = "red" ];
|
||||
build [ label = <<B>RUN </B>make build>, color = "red" ];
|
||||
|
||||
from -> deps;
|
||||
deps -> copy;
|
||||
copy -> workdir [ color = "red", label = " ❌ " ];
|
||||
workdir -> build [ color = "red", label = " ❌ " ];
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 6.0.1 (20220911.1526)
|
||||
-->
|
||||
<!-- Pages: 1 -->
|
||||
<svg width="368pt" height="271pt"
|
||||
viewBox="0.00 0.00 368.00 271.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 267)">
|
||||
<polygon fill="none" stroke="none" points="-4,4 -4,-267 364,-267 364,4 -4,4"/>
|
||||
<!-- from -->
|
||||
<g id="node1" class="node">
|
||||
<title>from</title>
|
||||
<polygon fill="none" stroke="black" points="360,-263 0,-263 0,-234 360,-234 360,-263"/>
|
||||
<text text-anchor="start" x="125" y="-247" font-family="monospace" font-weight="bold" font-size="10.00">FROM </text>
|
||||
<text text-anchor="start" x="156" y="-247" font-family="monospace" font-size="10.00">ubuntu:latest</text>
|
||||
</g>
|
||||
<!-- deps -->
|
||||
<g id="node2" class="node">
|
||||
<title>deps</title>
|
||||
<polygon fill="none" stroke="black" points="360,-212 0,-212 0,-183 360,-183 360,-212"/>
|
||||
<text text-anchor="start" x="110" y="-200.5" font-family="monospace" font-weight="bold" font-size="10.00">RUN </text>
|
||||
<text text-anchor="start" x="135" y="-200.5" font-family="monospace" font-size="10.00">apt-get update && \</text>
|
||||
<text text-anchor="start" x="74.5" y="-190.5" font-family="monospace" font-size="10.00">apt-get install -y build-essentials</text>
|
||||
</g>
|
||||
<!-- from->deps -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>from->deps</title>
|
||||
<path fill="none" stroke="black" d="M180,-233.77C180,-229.96 180,-226.15 180,-222.33"/>
|
||||
<polygon fill="black" stroke="black" points="183.5,-222.24 180,-212.24 176.5,-222.24 183.5,-222.24"/>
|
||||
</g>
|
||||
<!-- copy -->
|
||||
<g id="node3" class="node">
|
||||
<title>copy</title>
|
||||
<polygon fill="none" stroke="red" points="360,-161 0,-161 0,-132 360,-132 360,-161"/>
|
||||
<text text-anchor="start" x="128" y="-145" font-family="monospace" font-weight="bold" font-size="10.00">COPY </text>
|
||||
<text text-anchor="start" x="159" y="-145" font-family="monospace" font-size="10.00">main.c /src/</text>
|
||||
</g>
|
||||
<!-- deps->copy -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>deps->copy</title>
|
||||
<path fill="none" stroke="black" d="M180,-182.77C180,-178.96 180,-175.15 180,-171.33"/>
|
||||
<polygon fill="black" stroke="black" points="183.5,-171.24 180,-161.24 176.5,-171.24 183.5,-171.24"/>
|
||||
</g>
|
||||
<!-- workdir -->
|
||||
<g id="node4" class="node">
|
||||
<title>workdir</title>
|
||||
<polygon fill="none" stroke="red" points="360,-95 0,-95 0,-66 360,-66 360,-95"/>
|
||||
<text text-anchor="start" x="140" y="-79" font-family="monospace" font-weight="bold" font-size="10.00">WORKDIR </text>
|
||||
<text text-anchor="start" x="189" y="-79" font-family="monospace" font-size="10.00">/src/</text>
|
||||
</g>
|
||||
<!-- copy->workdir -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>copy->workdir</title>
|
||||
<path fill="none" stroke="red" d="M180,-131.89C180,-124.12 180,-114.36 180,-105.43"/>
|
||||
<polygon fill="red" stroke="red" points="183.5,-105.15 180,-95.15 176.5,-105.15 183.5,-105.15"/>
|
||||
<text text-anchor="middle" x="169.5" y="-109.8" font-family="Times,serif" font-size="14.00"> ❌  </text>
|
||||
</g>
|
||||
<!-- build -->
|
||||
<g id="node5" class="node">
|
||||
<title>build</title>
|
||||
<polygon fill="none" stroke="red" points="360,-29 0,-29 0,0 360,0 360,-29"/>
|
||||
<text text-anchor="start" x="137" y="-13" font-family="monospace" font-weight="bold" font-size="10.00">RUN </text>
|
||||
<text text-anchor="start" x="162" y="-13" font-family="monospace" font-size="10.00">make build</text>
|
||||
</g>
|
||||
<!-- workdir->build -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>workdir->build</title>
|
||||
<path fill="none" stroke="red" d="M180,-65.89C180,-58.12 180,-48.36 180,-39.43"/>
|
||||
<polygon fill="red" stroke="red" points="183.5,-39.15 180,-29.15 176.5,-39.15 183.5,-39.15"/>
|
||||
<text text-anchor="middle" x="169.5" y="-43.8" font-family="Times,serif" font-size="14.00"> ❌  </text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.8 KiB |
|
@ -0,0 +1,19 @@
|
|||
// dot -Tsvg ./cache-stack.dot > ./cache-stack.svg
|
||||
digraph {
|
||||
rankdir="LR";
|
||||
nodesep=0.3;
|
||||
edge[minlen=0];
|
||||
bgcolor="#00000000";
|
||||
node [ shape=rect, width=5, height=0.4, fontname=monospace, fontsize=10 ];
|
||||
|
||||
from [ label = <<B>FROM </B>ubuntu:latest> ];
|
||||
deps [ label = <<B>RUN </B>apt-get update && \\<br/>apt-get install -y build-essentials> ];
|
||||
copy [ label = <<B>COPY </B>main.c /src/> ];
|
||||
workdir [ label = <<B>WORKDIR </B>/src/> ];
|
||||
build [ label = <<B>RUN </B>make build> ];
|
||||
|
||||
from -> deps;
|
||||
deps -> copy;
|
||||
copy -> workdir;
|
||||
workdir -> build;
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 6.0.1 (20220911.1526)
|
||||
-->
|
||||
<!-- Pages: 1 -->
|
||||
<svg width="368pt" height="241pt"
|
||||
viewBox="0.00 0.00 368.00 241.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 237)">
|
||||
<polygon fill="none" stroke="none" points="-4,4 -4,-237 364,-237 364,4 -4,4"/>
|
||||
<!-- from -->
|
||||
<g id="node1" class="node">
|
||||
<title>from</title>
|
||||
<polygon fill="none" stroke="black" points="360,-233 0,-233 0,-204 360,-204 360,-233"/>
|
||||
<text text-anchor="start" x="125" y="-217" font-family="monospace" font-weight="bold" font-size="10.00">FROM </text>
|
||||
<text text-anchor="start" x="156" y="-217" font-family="monospace" font-size="10.00">ubuntu:latest</text>
|
||||
</g>
|
||||
<!-- deps -->
|
||||
<g id="node2" class="node">
|
||||
<title>deps</title>
|
||||
<polygon fill="none" stroke="black" points="360,-182 0,-182 0,-153 360,-153 360,-182"/>
|
||||
<text text-anchor="start" x="110" y="-170.5" font-family="monospace" font-weight="bold" font-size="10.00">RUN </text>
|
||||
<text text-anchor="start" x="135" y="-170.5" font-family="monospace" font-size="10.00">apt-get update && \</text>
|
||||
<text text-anchor="start" x="74.5" y="-160.5" font-family="monospace" font-size="10.00">apt-get install -y build-essentials</text>
|
||||
</g>
|
||||
<!-- from->deps -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>from->deps</title>
|
||||
<path fill="none" stroke="black" d="M180,-203.77C180,-199.96 180,-196.15 180,-192.33"/>
|
||||
<polygon fill="black" stroke="black" points="183.5,-192.24 180,-182.24 176.5,-192.24 183.5,-192.24"/>
|
||||
</g>
|
||||
<!-- copy -->
|
||||
<g id="node3" class="node">
|
||||
<title>copy</title>
|
||||
<polygon fill="none" stroke="black" points="360,-131 0,-131 0,-102 360,-102 360,-131"/>
|
||||
<text text-anchor="start" x="128" y="-115" font-family="monospace" font-weight="bold" font-size="10.00">COPY </text>
|
||||
<text text-anchor="start" x="159" y="-115" font-family="monospace" font-size="10.00">main.c /src/</text>
|
||||
</g>
|
||||
<!-- deps->copy -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>deps->copy</title>
|
||||
<path fill="none" stroke="black" d="M180,-152.77C180,-148.96 180,-145.15 180,-141.33"/>
|
||||
<polygon fill="black" stroke="black" points="183.5,-141.24 180,-131.24 176.5,-141.24 183.5,-141.24"/>
|
||||
</g>
|
||||
<!-- workdir -->
|
||||
<g id="node4" class="node">
|
||||
<title>workdir</title>
|
||||
<polygon fill="none" stroke="black" points="360,-80 0,-80 0,-51 360,-51 360,-80"/>
|
||||
<text text-anchor="start" x="140" y="-64" font-family="monospace" font-weight="bold" font-size="10.00">WORKDIR </text>
|
||||
<text text-anchor="start" x="189" y="-64" font-family="monospace" font-size="10.00">/src/</text>
|
||||
</g>
|
||||
<!-- copy->workdir -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>copy->workdir</title>
|
||||
<path fill="none" stroke="black" d="M180,-101.77C180,-97.96 180,-94.15 180,-90.33"/>
|
||||
<polygon fill="black" stroke="black" points="183.5,-90.24 180,-80.24 176.5,-90.24 183.5,-90.24"/>
|
||||
</g>
|
||||
<!-- build -->
|
||||
<g id="node5" class="node">
|
||||
<title>build</title>
|
||||
<polygon fill="none" stroke="black" points="360,-29 0,-29 0,0 360,0 360,-29"/>
|
||||
<text text-anchor="start" x="137" y="-13" font-family="monospace" font-weight="bold" font-size="10.00">RUN </text>
|
||||
<text text-anchor="start" x="162" y="-13" font-family="monospace" font-size="10.00">make build</text>
|
||||
</g>
|
||||
<!-- workdir->build -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>workdir->build</title>
|
||||
<path fill="none" stroke="black" d="M180,-50.77C180,-46.96 180,-43.15 180,-39.33"/>
|
||||
<polygon fill="black" stroke="black" points="183.5,-39.24 180,-29.24 176.5,-39.24 183.5,-39.24"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.6 KiB |
Loading…
Reference in New Issue