-
Notifications
You must be signed in to change notification settings - Fork 25.2k
Introduce Docker images build #36246
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
Conversation
This commit introduces the building of the Docker images as bonafide packaging formats alongside our existing archive and packaging distributions. This build is migrated from a dedicated repository, and converted to Gradle in the process.
Pinging @elastic/es-core-infra |
Testing will come in a follow-up, after we have discussion and agree on an approach. |
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.
LGTM, just a few points that I think are worth discussing.
"docker.elastic.co/elasticsearch/elasticsearch-full:${VersionProperties.elasticsearch}" | ||
] | ||
} | ||
executable 'docker' |
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.
This means that we'll need docker installed even for ./gradlew assemble
.
Are we ok with any version of docker for that?
It might make sense to add up-front checks like we have for the JDK to make sure it's there and it works.
Permissions are also something we are likely to run into as many tutorials online advertise the use of sudo docker
people might not have permissions set up for the user running the build.
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.
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.
@atorok I pushed one more change, to check if we can even run Docker: 26fe606
This gives output like:
FAILURE: Build failed with an exception.
* What went wrong:
a problem occurred running Docker yet it is required to run the following tasks:
:distribution:docker:buildDockerImage
:distribution:docker:buildOssDockerImage
the problem is that [docker images] exited with exit code [1] with error output [Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.39/images/json: dial unix /var/run/docker.sock: connect: permission denied]
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.
That seems right. We talked about making a parameter that let you explicitly skip the tasks which would be a nice thing to have. Something like -Dbuild.docker=false
.
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.
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.
I think this would be an ideal time to consider using img or Buildah as the build executor instead of the Docker daemon. I personally consider this to be the "next step" in improving the build, and it just seems like a great time to redefine the dependencies.
Getting away from the Docker daemon not only improves the local build experience for developers, especially if they don't run Linux on their workstations, it also makes a much better story for running builds in container environments, like the work that @mgreau is actively pursuing.
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.
Thank you for the suggestion. Alas the Docker daemon will stay around since we are migrating some of our testing away from Vagrant fixtures to Docker Compose fixtures. That’s not to say we won’t take your suggestion up.
distribution/docker/build.gradle
Outdated
return "${prefix}${oss ? 'Oss' : ''}${suffix}" | ||
} | ||
|
||
void addProcessDockerfileTask(final boolean oss) { |
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.
Why are we preferring multiple Copy
tasks over a single one that does this multiple times:
from ('...') {
into '..'
}
I think that would be easier to read and understand what's being copied where.
We could additionally make it a Sync
task to make sure no stale files end up in the build.
This won't be a problem so much in CI where we clean but could happen locally.
Having more tasks could save us a bit when only parts change but I don't think that's worth sacrificing visibility over it.
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.
Okay, I simplified into a single copy task for the static files, although I still left the generation of the Dockerfile
separate. See 8e78667.
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.
Looks good, a couple minor comments
@@ -232,6 +232,60 @@ class BuildPlugin implements Plugin<Project> { | |||
project.ext.java9Home = project.rootProject.ext.java9Home | |||
} | |||
|
|||
static void requireDocker(final Task task) { | |||
final Project rootProject = task.project.rootProject | |||
if (rootProject.hasProperty('requiresDocker') == false) { |
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.
Instead of using an essentially global property like this, can we have a property on the tasks using docker themselves? Then we can use a .all
closure on the tasks container looking for the property, and check for docker in the middle of configuration instead of waiting until all projects are configured. There would still be a rootProject property to "remember" docker was already checked, but the tasks won't (directly) modify the root project.
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.
+1 on marking the task, but I would make it a custom task and use tasks.withType
.
The checks could live in the same class as static methods.
We could at some time introduce an interface and have a generic "this task requires something that we need to check up-front" mechanism, we already have others: docker-compose, jdk versions tasks (tests) that require specific inputs to run.
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.
I think these are very good suggestions but I’m going to ask one of you to pick this up on a follow-up please?
} else { | ||
assert exitCode > 0 && dockerErrorOutput != null | ||
throw new GradleException( | ||
String.format( |
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.
I think it would be useful to clearly distinguish docker not being found in one of the two expected locations, vs an error when trying to run the binary.
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.
@rjernst So I think I did distinguished the two cases, or am I misunderstanding what you mean?
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.
Sorry, you are right. My eyes glossed over the first if block.
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.
If you use a task property and a tasks.all
as I suggested, I think this can all be moved together so that the if/elseif on the docker file check can end with an else that throws the error, so you don't need to fake out the exit code.
distribution/docker/build.gradle
Outdated
from 'src/docker/bin' | ||
} | ||
|
||
from 'src/docker/config' |
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.
Can we structure src/docker/config so it is flattened, like bin, so that there is a config dir in the output? This isn't critical, but the lack of parallelism annoys my OCD. :)
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.
I pushed 0c2e6ff.
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.
Thanks @jasontedor. I left some comments on the new commits.
} else { | ||
// do not overwrite an existing onlyIf closure | ||
final Closure onlyIf = task.onlyIf | ||
task.onlyIf { onlyIf && false } |
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 task can have multiple onlyIf
s but if any one of them return false the others don't really matter. This can be expressed more straight forward as task.enabled = false
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.
I pushed ed4bf10.
dockerErrorOutput = null | ||
} else { | ||
// the Docker binary executes, check that we can execute a privileged command | ||
final Process process = new ProcessBuilder(dockerBinary, "images").start() |
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.
nit: project.exec
or LoggedExec.exec(project
would be more idiomatic here.
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.
I pushed some changes related to this.
@@ -232,6 +232,60 @@ class BuildPlugin implements Plugin<Project> { | |||
project.ext.java9Home = project.rootProject.ext.java9Home | |||
} | |||
|
|||
static void requireDocker(final Task task) { | |||
final Project rootProject = task.project.rootProject | |||
if (rootProject.hasProperty('requiresDocker') == false) { |
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.
+1 on marking the task, but I would make it a custom task and use tasks.withType
.
The checks could live in the same class as static methods.
We could at some time introduce an interface and have a generic "this task requires something that we need to check up-front" mechanism, we already have others: docker-compose, jdk versions tasks (tests) that require specific inputs to run.
* master: (133 commits) SNAPSHOT: Increase Timeout to Stabilize Test (elastic#36294) Fix get certificates HLRC API (elastic#36198) Avoid shutting down the only master (elastic#36272) Fix typo in comment Fix total hits serialization of the search response (elastic#36290) Fix FullClusterRestartIT#testRollupIDSchemeAfterRestart Mute FullClusterRestartIT#testRollupIDSchemeAfterRestart as we await a fix. [Docs] Add Profile API limitations (elastic#36252) Make sure test don't use Math.random for reproducability (elastic#36241) Fix compilation ingest: support default pipeline through an alias (elastic#36231) Zen2: Rename tombstones to exclusions (elastic#36226) [Zen2] Hide not recovered state (elastic#36224) Test: mute testDataNodeRestartWithBusyMasterDuringSnapshot Test: mute testSnapshotAndRestoreWithNested Revert "Test: mute failing mtermvector rest test" Test: mute failing mtermvector rest test add version 6.5.3 (elastic#36268) Make hits.total an object in the search response (elastic#35849) [DOCS] Fixes broken link in execute watch ...
@rjernst @nik9000 @atorok Please take another look. I would like the mechanics of how we address requiring Docker in a follow-up with either @rjernst or @atorok taking the lead here as it seems the two of you have some thoughts to iterate on and it's not germane to our main story which is getting the building of the Docker images into this repository. |
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.
LGTM
This commit introduces the building of the Docker images as bonafide packaging formats alongside our existing archive and packaging distributions. This build is migrated from a dedicated repository, and converted to Gradle in the process.
ingest-geoip and ingest-user-agent are now packaged as modules in Elasticsearch. Relates to elastic/elasticsearch#36956 and elastic/elasticsearch#36246
ingest-geoip and ingest-user-agent are now packaged as modules in Elasticsearch. Relates to elastic/elasticsearch#36956 and elastic/elasticsearch#36246
This commit introduces the building of the Docker images as bonafide packaging formats alongside our existing archive and packaging distributions. This build is migrated from a dedicated repository, and converted to Gradle in the process.