Damien Duportal
added a comment - 2017-06-12 14:05 One clue here that might be useful here: https://github.com/moby/moby/pull/33185/files
There is a "–target" option to docker build that can help. But if you target only the build part in your example
docker build -t myimage:1.0.0 --target=build ./
then, the child images (the other FROM) will be ignored.
The user need for the docker workflow plugin to express instructions to build in the docker-provided build environment are the same as this multi-stage build.
The plugin does not seems currently useful with multi stage: moving to a simple sh 'docker build -t image ./' should be enough there, outside the need for fingerprinting maybe ?
=> The big concern is "how to make jenkins access the intermediate container, like for publishing tests units or reports" ?
For today, I'm trying to parse the docker build output, and the use docker cp to get the files in the workspace, which is portable in term of UID, and less painful.

Oleksandr Korniienko
added a comment - 2017-06-12 21:00 - edited Another way you can add the first line
#Build environment
#
FROM alpine:3.6
FROM alpine:3.6 AS builder
<SNIP>
#Create final container
#
FROM alpine:3.6
<SNIP>
#Copy artifacts from builder
COPY --from=builder /usr/local .

Docker multi-stage build throws away intermediate containers as it goes, so the concern above is not going to be able to be fixed in Jenkins code. You can see this in the build output with lines like: `Removing intermediate container 66e6311b3971`

(unless you were meaning to say image, instead of container)

A quick fix to get the final "FROM" would be as simple as changing the "break" to a "continue" in the loop at

Eric Smalling
added a comment - 2017-08-09 18:36 Docker multi-stage build throws away intermediate containers as it goes, so the concern above is not going to be able to be fixed in Jenkins code. You can see this in the build output with lines like: `Removing intermediate container 66e6311b3971`
(unless you were meaning to say image , instead of container )
A quick fix to get the final "FROM" would be as simple as changing the "break" to a "continue" in the loop at
https://github.com/jenkinsci/docker-workflow-plugin/blob/111b78e2c110a77826a2d6c7607fd24db4c8e440/src/main/java/org/jenkinsci/plugins/docker/workflow/FromFingerprintStep.java#L100
If, however, you want to get at the intermediate images, that's going to take a lot more effort.

Damien Duportal
added a comment - 2017-08-09 18:44 Eric Smalling be careful, you only need the intermediate image, not the intermediate container (which are effectively deleted as you said).
Those intermediate images are used for the "caching" of the docker builds, and contains the FS (so all the files).
The containers are just instantiations of this immutable image. They are deleted by default because duplicating things (not really true, in term of layers, but let's see things like this).
You can access these intermediate images with the flag "-a" added to "docker image ls" of to "docker images" (if you have an older docker version):
docker image ls -a

Damien Duportal - I think we are saying the same thing. (I was quoting your original comment where you mentioned the intermediate containers.)

What I am saying is that a simple change to loop until the last FROM statement would fix the parsing error and would make docker.build work like it does for non-multi-stage builds.

The problem of obtaining the image ID's for the intermediate images is a bigger one to try to solve which probably should be a separate feature enhancement as opposed to the bug that is occurring with grabbing the first one and pulling the " AS..." part of the line.

Eric Smalling
added a comment - 2017-08-09 18:53 Damien Duportal - I think we are saying the same thing. (I was quoting your original comment where you mentioned the intermediate containers .)
What I am saying is that a simple change to loop until the last FROM statement would fix the parsing error and would make docker.build work like it does for non-multi-stage builds.
The problem of obtaining the image ID's for the intermediate images is a bigger one to try to solve which probably should be a separate feature enhancement as opposed to the bug that is occurring with grabbing the first one and pulling the " AS..." part of the line.

More details. Here is a stub of my Dockerfile. If I understand the attempted fix in 1.13, we are now looking at the last FROM. Since I am aliasing the "Release" step that may be why this is still blowing up.

Kevin Gorlick
added a comment - 2017-09-12 16:54 More details. Here is a stub of my Dockerfile. If I understand the attempted fix in 1.13, we are now looking at the last FROM. Since I am aliasing the "Release" step that may be why this is still blowing up.
# Base image
FROM 12345/node-base:latest AS base
WORKDIR /app
# Dependencies
FROM base AS dependencies
*STUFF*
# Test
FROM dependencies AS test
*STUFF*
# Build
FROM dependencies AS build
*STUFF*
# Release
FROM base AS release
COPY --from=dependencies /app/prod_node_modules ./node_modules
COPY --from=build /app/dist ./dist
*STUFF*

Kevin Gorlick
added a comment - 2017-09-12 17:39 Eric Smalling , as a temp workaround, I bet I can change the last from to (instead of "FROM base")
FROM 12345/node-base:latest AS base
WORKDIR /app
But at some point someone (maybe even me) will be doing something a bit more complex in the base image and not want to have to duplicate all the steps in the final build.

Ah - I missed the fact that your were coming from a prior stage in your last FROM... not something I've heard people doing since they usually want to come from alpine or something. I can see why you're doing it though - I'll try to get a fix in this week and will post here when I have an hpi to test.

Eric Smalling
added a comment - 2017-09-12 17:45 Ah - I missed the fact that your were coming from a prior stage in your last FROM... not something I've heard people doing since they usually want to come from alpine or something. I can see why you're doing it though - I'll try to get a fix in this week and will post here when I have an hpi to test.

Eric Smalling
added a comment - 2017-09-18 16:05 Sorry, I've not had time to look at this further yet. Until I (or someone else) does, I recommend doing as Jesse Glick says and just run docker build via an "sh".

I have been given the go-ahead to attempt to fix this using the --iidfile option with a few hours of my paid work time to fix our use of this feature. Jesse Glick in an informal email exchange agreed that this sounded like a reasonable mode of repair, for what that's worth.

....

So having determined the problem had to do not with being able to acquire the specific id of the just created image but the SOURCE image ids, I decided that the proper way to fix it for multi-stage builds was to make the primitive naive parser (which is making the 'space in my FROM line cause exception bug thanks to a unnamed constant (5) ) more smart - so that 1. knows about build-arg so it can substitute in 2. understands whitespace the same way Docker does.

Unfortunately, ain't got time for that. What I DID notice in analyzing the code is that this exceedingly naive parser will ignore any FROM line that isn't pegged to the first column - so I can put 'FROM scratch\n FROM ${whatever}/thing:${whateverelse} and it won't spot the line with the space on the first column. Fortunately, Docker 17.09 doesn't care about that space - allowing me to fool the plugin into thinking I sourced from scratch when I didn't.

Its a workaround, but it works. I have no further action here at this time, but I hope to sometime get to make this work.

David Ihnen
added a comment - 2017-11-30 14:01 - edited I have been given the go-ahead to attempt to fix this using the --iidfile option with a few hours of my paid work time to fix our use of this feature. Jesse Glick in an informal email exchange agreed that this sounded like a reasonable mode of repair, for what that's worth.
....
So having determined the problem had to do not with being able to acquire the specific id of the just created image but the SOURCE image ids, I decided that the proper way to fix it for multi-stage builds was to make the primitive naive parser (which is making the 'space in my FROM line cause exception bug thanks to a unnamed constant (5) ) more smart - so that 1. knows about build-arg so it can substitute in 2. understands whitespace the same way Docker does.
Unfortunately, ain't got time for that. What I DID notice in analyzing the code is that this exceedingly naive parser will ignore any FROM line that isn't pegged to the first column - so I can put 'FROM scratch\n FROM ${whatever}/thing:${whateverelse} and it won't spot the line with the space on the first column. Fortunately, Docker 17.09 doesn't care about that space - allowing me to fool the plugin into thinking I sourced from scratch when I didn't.
Its a workaround, but it works. I have no further action here at this time, but I hope to sometime get to make this work.
WORKAROUND - MAKE IT LOOK MORE LIKE THIS:
FROM scratch
FROM buildimage:$\{POSSIBLY_ARGS}
RUN build stuff
FROM runimage:${whatever}
COPY --from=1 /built/code /deploy/location
CMD startup

Andreas Lutro
added a comment - 2018-08-14 19:25 I'm not an experienced java developer but this has been annoying me for way too long. I've opened a PR here with more fixes for this issue, but could use some guidance. https://github.com/jenkinsci/docker-workflow-plugin/pull/149

workflow and add additional parameter to DSL like `iidfile="path/to/file"`, so on the other side Docker Workflow plugin can check whether it is set or not and use ID from file instead of relying on naive parser.

I could create PRs for both plugins, but would prefer to discuss this solutions first.

Theoretically `–iidfile` can be added as a part of `buildArgs`, but then Workflow plugin will have to parse build args, in case of separate DSL parameter it is just a simple isEmpty check and a logic like this to get ID:

Alex Dubrouski
added a comment - 2018-08-15 22:53 - edited Andreas Lutro et al.
I feel it is rather work around. We faced this issue couple of weeks ago and I tried to poke around. So far the only solution I see is to change:
https://github.com/jenkinsci/pipeline-model-definition-plugin/blob/6cd7cb80203bd34cc0909e0e0a673c0d5d6a178b/pipeline-model-definition/src/main/resources/org/jenkinsci/plugins/pipeline/modeldefinition/agent/impl/DockerPipelineFromDockerfileScript.groovy
workflow and add additional parameter to DSL like `iidfile="path/to/file"`, so on the other side Docker Workflow plugin can check whether it is set or not and use ID from file instead of relying on naive parser.
I could create PRs for both plugins, but would prefer to discuss this solutions first.
Theoretically `–iidfile` can be added as a part of `buildArgs`, but then Workflow plugin will have to parse build args, in case of separate DSL parameter it is just a simple isEmpty check and a logic like this to get ID:
FilePath dockeridfile = workspace.child(step.iidfile);
String id;
try (InputStream isid = dockeridfile.read()) {
try (BufferedReader r = new BufferedReader( new InputStreamReader(isid, "ISO-8859-1" ))) {
id = r.readLine();
}
}
Just to be clear I mean pipeline scenario like this:
stage( 'Build' ) {
agent {
dockerfile {
filename 'Dockerfile'
dir 'deployment'
additionalBuildArgs '--target base'
}
}
steps {
sh "echo TEST123"
}
}
where Dockerfile is multi-stage and contains aliases like " FROM base AS prod "

If you want to submit a "better" PR then don't let me stop you, but I'd rather have a working plugin with workarounds than a non-working one until someone (whoever that is) submits a "proper" solution.

That being said, is this plugin even being maintained? Am I wasting my time commenting here and making a PR?

Andreas Lutro
added a comment - 2018-08-27 08:24 If you want to submit a "better" PR then don't let me stop you, but I'd rather have a working plugin with workarounds than a non-working one until someone (whoever that is) submits a "proper" solution.
That being said, is this plugin even being maintained? Am I wasting my time commenting here and making a PR?

Not that I know of. IMO you should not use the docker DSL, nor the withDockerContainer step (including Declarative Pipeline’s agent {docker …} and agent {dockerfile …}), and at most use the withDockerRegistry and withDockerServer steps.

Jesse Glick
added a comment - 2018-08-27 14:44 - edited is this plugin even being maintained?
Not that I know of. IMO you should not use the docker DSL, nor the withDockerContainer step (including Declarative Pipeline’s agent {docker … } and agent {dockerfile … }), and at most use the withDockerRegistry and withDockerServer steps.

Antoine Monnet
added a comment - 2018-11-12 22:41 I've modified FromFingerprintStep, removed the Dockerfile parser and use docker inspect to walk up the image history up to the previous properly tagged image.
This solves the multistage issue for me.
https://github.com/jenkinsci/docker-workflow-plugin/pull/155

Matic Gacar
added a comment - 2018-11-15 11:55 We are also having trouble because of this, since we have to rewrite all of our Dockerfiles to be compatible with jenkins.
Any news on this is appreciated.

Jesse Glick that's one thing I tried but makes things like deploying to registry more of a hassle. Overall I've since abandoned trying to use Jenkins and have gone with another CI that worked flawlessly from the start since it was docker oriented.

Steven Weathers
added a comment - 2019-01-11 23:27 Jesse Glick that's one thing I tried but makes things like deploying to registry more of a hassle. Overall I've since abandoned trying to use Jenkins and have gone with another CI that worked flawlessly from the start since it was docker oriented.

A fix for this issue was just released in Docker Pipeline plugin version 1.19. From the release notes:

Deprecate the dockerFingerprintFrom and dockerFingerprintRun steps and stop calling them during docker.build and image.run. Fixes various issues with Dockerfile parsing and parsing arguments to docker build.

Devin Nusbaum
added a comment - 2019-08-02 21:40 A fix for this issue was just released in Docker Pipeline plugin version 1.19. From the release notes:
Deprecate the dockerFingerprintFrom and dockerFingerprintRun steps and stop calling them during docker.build and image.run . Fixes various issues with Dockerfile parsing and parsing arguments to docker build .