-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Clean docker image cache #1636
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Clean docker image cache #1636
Changes from 166 commits
032014e
c3d0ad2
10889fd
8f0375a
96ebf42
db8403e
90a5345
b041c00
9580444
a34ac47
6613f78
1b3eae9
4275382
618f25a
100a9cd
4b9056b
315a85b
ed3c264
446d630
6821a28
9e95a8a
02840b1
7e31d65
926f4d7
344e1d4
e91ac12
ba6e088
49025e8
a647bb3
16b09ab
c8d8a72
591f340
c331bd0
f48b22b
900843d
76ecdd5
b69d4a6
df2ddcc
3ff1cdd
bd89cc8
39ef510
d389953
b676bac
b1473c9
83ff113
33dfbb7
316af58
425d30b
763280a
3afbaef
cb97ba1
b33edc8
7a1fdf1
a8beed9
2e445d9
5b51db1
b0ce76c
918bb7f
c629951
ccfc0bf
0f3fa24
b60a283
901cb66
251002b
fedeb17
004f95b
10168be
dc811cf
3dfe77d
619c8d0
12ca211
a91c1e1
be2e809
1c84e33
1319fe7
9424c2e
cddd550
f8d34f2
31d2fb8
fa9fd09
22f3f51
bb44f4b
9714f2c
0f9cb3d
6e60174
78c5575
5eb5c51
48f7cb0
8a18085
e4cab39
ba4cab0
bbc6e30
0e9f1ad
8a5243c
cbf83c4
3dd0260
1408d44
2925ee1
af3a12b
f5a27dc
494454a
add0f67
b6a4b45
00a559d
882f9c1
6c9071e
09c10bb
3615396
116c199
f1447cd
14b165b
3ce8fac
41eaa8d
4f89298
ee1031d
f6707d5
9930c7d
0043006
4e292ec
3129276
1c90fc2
fa0888a
ab680d1
4023ca3
7ed7f5d
3be81b7
dd710ec
4fdd06a
bf61054
f059697
013cc6a
13ff3b3
88021bb
dcf4e62
a600c69
3f1a180
85ca441
65acfe6
5526b50
0c131b5
af8a8ee
9c74e14
a410606
8c38ece
dcb8fb4
73e9765
1a3a4d9
926d2b0
02737d4
24defb8
14c9780
719ccbc
5784dfa
ecf13b8
658a5f6
f6c0b43
dacd84d
ef76c9e
81d571f
4eb0e3c
1b165a1
9201dc9
8e72ad6
e16b685
81779ee
8a6b3a3
8979a5a
1348cb6
d1d62ee
256332d
eb55382
4a88031
ca5dde4
0b18c29
818ab9f
3244dae
b7af072
816e44c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| name: restore-docker-images | ||
| description: upload docker images | ||
| runs: | ||
| using: "composite" | ||
| steps: | ||
|
|
||
| - name: restore images if cache matches | ||
| uses: actions/cache/restore@v4 | ||
| id: images-cache | ||
| with: | ||
| path: /tmp/docker/images | ||
| key: docker-images-cache-${{ hashFiles('**/current-images.txt') }} | ||
|
|
||
| - name: pull docker images | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if cache is not present, issue It also replaces the |
||
| shell: bash | ||
| if: steps.images-cache.outputs.cache-hit != 'true' | ||
| run: | | ||
| echo 'start pulling common images' | ||
| mkdir -p /tmp/docker/images | ||
| result=$(find . -name 'current-images.txt') | ||
| while read line; do | ||
| docker pull "$line" | ||
| replace_slash=$(tr '/' '-' <<< "$line") | ||
| docker save "${line}" > "/tmp/docker/images/${replace_slash}.tar" | ||
| done <$result | ||
|
|
||
| ls /tmp/docker/images | ||
|
|
||
| - name: save docker images | ||
| id: save-docker-images | ||
| uses: actions/cache/save@v4 | ||
| if: steps.images-cache.outputs.cache-hit != 'true' | ||
| with: | ||
| path: | | ||
| /tmp/docker/images | ||
| key: docker-images-cache-${{ hashFiles('**/current-images.txt') }} | ||
|
|
||
|
|
||
|
|
||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,7 @@ | |
| import java.time.Duration; | ||
| import java.util.Arrays; | ||
| import java.util.List; | ||
| import java.util.Optional; | ||
| import java.util.concurrent.TimeUnit; | ||
|
|
||
| import com.github.dockerjava.api.command.ListImagesCmd; | ||
|
|
@@ -57,11 +58,14 @@ public final class Commons { | |
| private static final Log LOG = LogFactory.getLog(Commons.class); | ||
|
|
||
| /** | ||
| * istio version used in our integration tests. | ||
| * this path is generated by the pipeline of github actions. | ||
| */ | ||
| public static final String ISTIO_VERSION = "1.16.0"; | ||
| private static final String TMP_IMAGES = "/tmp/docker/images"; | ||
|
|
||
| private static final String LOCAL_ISTIO_BIN_PATH = "istio-cli/istio-" + ISTIO_VERSION + "/bin"; | ||
| /** | ||
| * istio version used in our integration tests. | ||
| */ | ||
| public static final String ISTIO_VERSION = "1.20.5"; | ||
|
|
||
| private Commons() { | ||
| throw new AssertionError("No instance provided"); | ||
|
|
@@ -92,7 +96,7 @@ private Commons() { | |
|
|
||
| private static final K3sContainer CONTAINER = new FixedPortsK3sContainer(DockerImageName.parse(Commons.RANCHER)) | ||
| .configureFixedPorts(EXPOSED_PORTS).withFileSystemBind(TEMP_FOLDER, TEMP_FOLDER) | ||
| .withCommand(Commons.RANCHER_COMMAND).withReuse(true); | ||
| .withFileSystemBind(TMP_IMAGES, TMP_IMAGES).withCommand(Commons.RANCHER_COMMAND).withReuse(true); | ||
|
|
||
| public static K3sContainer container() { | ||
| return CONTAINER; | ||
|
|
@@ -168,6 +172,51 @@ public static void loadImage(String image, String tag, String tarName, K3sContai | |
|
|
||
| } | ||
|
|
||
| public static void load(K3sContainer container, String name, String image) { | ||
| File dockerImagesRootDir = Paths.get(Commons.TMP_IMAGES).toFile(); | ||
| if (dockerImagesRootDir.exists() && dockerImagesRootDir.isDirectory()) { | ||
| File[] tars = dockerImagesRootDir.listFiles(); | ||
| if (tars != null && tars.length > 0) { | ||
| Optional<String> found = Arrays.stream(tars).map(File::getName) | ||
| .filter(tarName -> tarName.contains(name)).findFirst(); | ||
| if (found.isPresent()) { | ||
| LOG.info("running in github actions, will load from : " + Commons.TMP_IMAGES); | ||
| Commons.loadImageFromPath(found.get(), container); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. my 2p is to make the GH workflow do this, as it is distracting in the normal code. In my go code, I only pull if the image doesn't already exist (or it is a locally built one). So, if you can have in the GH action the images safely restored from tar, then "pull if not exists" here for the non-test/tagged images will be simpler code. Also, it centralizes the responsibility vs picking a magic tar directory. When I look at other code that uses k3s or testcontainers it is a lot simpler than the code here, and I think we need to keep in mind how difficult this is vs the intent of testcontainers (just use it sort of thing)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let me see if I got your point correct. You are suggesting to do the "docker load" part in the GH action itself, right? If so, good point, I did not think about it this way
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah in fact when I have something complicated for GH action, I put it into a shell script and have the GH action call that. This way it is easier to ad-hoc test. I have it on my TODO to look at https://dagger.io/ instead of this approach
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I took a closer look, and I don't think that your suggestion is possible. At this point, there is no instance of k3s starter, so no way to import an image via I am really interested how you are doing it to be honest and where I can take a look.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And sorry it took a while to respond, I had to recollect why it is like this, and create that PR. Your comments triggered that, so thank you :)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks for raising it. Most of the time testcontainers-java is ahead of go, and this is a rare place where we need to catch up the main one. 👍
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. neah, thank you actually. I never saw the problem from this angle until you came here, so all the credits go to you. kudos!
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to be clear when we run the tests locally (or internally on Jenkins) we will still pull the images like we did before because this cache will never exist?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that's correct. it's like running the test locally, without having the images already pulled |
||
| return; | ||
| } | ||
| else { | ||
| LOG.info(name + " not found, resorting to pulling the image"); | ||
| } | ||
| } | ||
| else { | ||
| LOG.info("no tars found, will resort to pulling the image"); | ||
| } | ||
| } | ||
| else { | ||
| LOG.info("running outside github actions"); | ||
| } | ||
|
|
||
| try { | ||
| LOG.info("no tars found, will resort to pulling the image"); | ||
| Commons.pullImage(image, Commons.ISTIO_VERSION, container); | ||
| Commons.loadImage(image, Commons.ISTIO_VERSION, name, container); | ||
| } | ||
| catch (Exception e) { | ||
| throw new RuntimeException(e); | ||
| } | ||
| } | ||
|
|
||
| private static void loadImageFromPath(String tarName, K3sContainer container) { | ||
| await().atMost(Duration.ofMinutes(2)).pollInterval(Duration.ofSeconds(1)).until(() -> { | ||
| Container.ExecResult result = container.execInContainer("ctr", "i", "import", TMP_IMAGES + "/" + tarName); | ||
| boolean noErrors = result.getStderr() == null || result.getStderr().isEmpty(); | ||
| if (!noErrors) { | ||
| LOG.info("error is : " + result.getStderr()); | ||
| } | ||
| return noErrors; | ||
| }); | ||
| } | ||
|
|
||
| public static void cleanUp(String image, K3sContainer container) throws Exception { | ||
| container.execInContainer("crictl", "rmi", "docker.io/springcloud/" + image + ":" + pomVersion()); | ||
| container.execInContainer("rm", TEMP_FOLDER + "/" + image + ".tar"); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| busybox:1.35 | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what I have realized is that we download docker images specific to integration tests all the time. I am proposing to cache them via github actions instead. In order to do that, we are going to track what images we use and their versions in this file. It is used in the pipeline as the key of the cache : If this file changed, we will re-download them; it if stays the same and such a cache is present, it will download from the cache.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would recommend unit testing this somehow. Possibly you can make a test that dumps the images from k3s ctl and fails if it has something that isn't in here or visa versa? Just a thought, as this is very likely to drift.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. another way could be to make this like DockerImages.go, and give it a main function that prints out a list like this. Then, as long as you checked out the source first and installed go, you could run that main and also have no drift.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is just a helper, really. It is supposed to help with the times we run integration tests (that we plan to reduce in the long run anyway). So even if an image is not downloaded from the cache, it is still going to be pulled in the test. I, personally, would not test this "too much" and a few runs that I had proved that it works exactly as intended.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. p.s. I meant DockerImages.java ;) ok you can also solve this by making a comment in the java code that defines the istio versions saying "// please update current-images.txt when you update this" because at the end of the day, it is about drift making the infrastructure added here serve no value.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if you look closely into
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. neither does P.S. I doubt that I want to wait until that PR in test-containers is reviewed and released, so I am inclined to suggest merge/review this one the way it is. When that PR sees day light, I will go for another round of minor refactor.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👌 |
||
| istio/istioctl:1.20.5 | ||
| istio/proxyv2:1.20.5 | ||
| istio/pilot:1.20.5 | ||
| confluentinc/cp-kafka:7.2.1 | ||
| rabbitmq:3-management | ||
| wiremock/wiremock:3.4.2 | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a new stage that basically does this:
docker-images-cache-${{ hashFiles('**/current-images.txt') }}use it and restore to/tmp/docker/imagescurrent-images.txtline by line. For each of those lines, do adocker pullthen adocker saveto/tmp/docker/images/tmp/docker/images