Skip to content
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

Introduce Docker images build #36246

Merged
merged 18 commits into from Dec 6, 2018
Merged

Conversation

jasontedor
Copy link
Member

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.

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.
@jasontedor jasontedor added >enhancement :Delivery/Packaging RPM and deb packaging, tar and zip archives, shell and batch scripts v7.0.0 v6.6.0 labels Dec 5, 2018
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-core-infra

@jasontedor
Copy link
Member Author

Testing will come in a follow-up, after we have discussion and agree on an approach.

@jasontedor jasontedor removed the v6.6.0 label Dec 5, 2018
Copy link
Contributor

@alpar-t alpar-t left a 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'
Copy link
Contributor

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@atorok I pushed 684fcb5.

Copy link
Member Author

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]

Your input @nik9000 @rjernst would be appreciated here too!

Copy link
Member

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nik9000 I pushed b20be22. It's okay?

Copy link
Contributor

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.

Copy link
Member Author

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.

return "${prefix}${oss ? 'Oss' : ''}${suffix}"
}

void addProcessDockerfileTask(final boolean oss) {
Copy link
Contributor

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.

Copy link
Member Author

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.

Copy link
Member

@rjernst rjernst left a 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) {
Copy link
Member

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.

Copy link
Contributor

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.

Copy link
Member Author

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(
Copy link
Member

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.

Copy link
Member Author

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?

Copy link
Member

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.

Copy link
Member

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.

from 'src/docker/bin'
}

from 'src/docker/config'
Copy link
Member

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. :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed 0c2e6ff.

Copy link
Contributor

@alpar-t alpar-t left a 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 }
Copy link
Contributor

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 onlyIfs 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

Copy link
Member Author

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()
Copy link
Contributor

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.

Copy link
Member Author

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) {
Copy link
Contributor

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
  ...
@jasontedor
Copy link
Member Author

@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.

Copy link
Member

@rjernst rjernst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jasontedor jasontedor merged commit 11dd412 into elastic:master Dec 6, 2018
jasontedor added a commit that referenced this pull request Dec 6, 2018
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.
@jasontedor jasontedor deleted the build-docker-images branch December 6, 2018 22:21
ebadyano added a commit to elastic/rally-teams that referenced this pull request Jan 18, 2019
ingest-geoip and ingest-user-agent are now packaged as modules in
Elasticsearch. Relates to elastic/elasticsearch#36956 and elastic/elasticsearch#36246
ebadyano added a commit to ebadyano/rally-teams that referenced this pull request Mar 14, 2019
ingest-geoip and ingest-user-agent are now packaged as modules in
Elasticsearch. Relates to elastic/elasticsearch#36956 and
elastic/elasticsearch#36246
@mark-vieira mark-vieira added the Team:Delivery Meta label for Delivery team label Nov 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
:Delivery/Packaging RPM and deb packaging, tar and zip archives, shell and batch scripts >enhancement release highlight Team:Delivery Meta label for Delivery team v6.6.0 v7.0.0-beta1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants