-
Bug
-
Resolution: Unresolved
-
Minor
-
None
-
Jenkins ver. 2.121.3
Docker Pipeline 1.17
Summary
The following code may push a completely unrelated image.
def image = docker.build('foo') image.push('v0.0.1')
Explanation
The plugin will store foo:latest as the identifier for that image variable, so that image.push will execute docker push foo:latest, for example. This has unexpected consequences in some situations. Examples follow.
Scenario 1
- Two separate jobs execute docker.build('foo') in parallel (using the same docker daemon)
- Both jobs finish building the image before either pushes the image, with job #2 finishing last
- Both jobs will now push the image built by job #2, although it may use completely different source for building the image than job #1
Scenario 2
We recently ran into this one. This is even worse than the first scenario, because there's no race condition here - no need to run multiple jobs with specific timings.
- Job uses pods (agents) provisioned by Kubernetes. Docker commands use the underlying node's (host's) docker daemon.
- docker.build is run in one pod, and docker.push is run in another (nested, in the plugin's terminology) pod.
- When the two pods run on different nodes, then the push will either fail (if the project hasn't been built on that node before) or worse, it will push whatever image was last built on that node - likely something very different from the expected image.
Workaraound
In simple cases there's a pretty straight forward workaround - use unique tags when building the image. The workaround doesn't help us, however, because we're developing a library and don't have control over how the image is created. We simply get the image variable as input.
Proposed solution
Add --iidfile flag when building docker images and then refer to the built image by the shasum printed into that file.
There's a couple of things to keep in mind with that implementation.
- Users may already be specifying that flag, so the plugin may have to use whatever file the user has specified in that case.
- The same Image class is also used for pulling images etc, so the old behavior of using name + tag has to remain. Only in the case where the image is created with docker.build should the mechanism for finding the image change.